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/class-internals.h"
19 #include "mono/metadata/gc-internals.h"
20 #include "mono/metadata/mono-endian.h"
21 #include "mono/metadata/object-internals.h"
22 #include "mono/metadata/custom-attrs-internals.h"
23 #include "mono/metadata/sre-internals.h"
24 #include "mono/metadata/reflection-internals.h"
25 #include "mono/metadata/tabledefs.h"
26 #include "mono/metadata/tokentype.h"
27 #include "mono/metadata/verify-internals.h"
28 #include "mono/metadata/icall-decl.h"
29 #include "mono/utils/checked-build.h"
31 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
32 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
34 #if SIZEOF_VOID_P == 4
35 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
37 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
40 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
41 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
43 #define CATTR_TYPE_SYSTEM_TYPE 0x50
44 #define CATTR_BOXED_VALUETYPE_PREFIX 0x51
45 #define CATTR_TYPE_FIELD 0x53
46 #define CATTR_TYPE_PROPERTY 0x54
48 static gboolean
type_is_reference (MonoType
*type
);
50 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument
, "System.Reflection", "CustomAttributeTypedArgument");
51 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument
, "System.Reflection", "CustomAttributeNamedArgument");
52 static GENERATE_TRY_GET_CLASS_WITH_CACHE (customattribute_data
, "System.Reflection", "CustomAttributeData");
54 static MonoCustomAttrInfo
*
55 mono_custom_attrs_from_builders_handle (MonoImage
*alloc_img
, MonoImage
*image
, MonoArrayHandle cattrs
);
58 bcheck_blob (const char *ptr
, int bump
, const char *endp
, MonoError
*error
);
61 decode_blob_value_checked (const char *ptr
, const char *endp
, guint32
*size_out
, const char **retp
, MonoError
*error
);
64 custom_attrs_idx_from_class (MonoClass
*klass
);
67 custom_attrs_idx_from_method (MonoMethod
*method
);
70 metadata_foreach_custom_attr_from_index (MonoImage
*image
, guint32 idx
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
);
74 * LOCKING: Acquires the loader lock.
76 static MonoCustomAttrInfo
*
77 lookup_custom_attr (MonoImage
*image
, gpointer member
)
79 MONO_REQ_GC_NEUTRAL_MODE
;
81 MonoCustomAttrInfo
* res
;
83 res
= (MonoCustomAttrInfo
*)mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
88 res
= (MonoCustomAttrInfo
*)g_memdup (res
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * res
->num_attrs
);
94 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttrHandle cattr
, MonoReflectionMethodHandle ctor_handle
, MonoMethod
**ctor_method
)
95 // ctor_handle is local to this function, allocated by its caller for efficiency.
97 MONO_REQ_GC_UNSAFE_MODE
;
99 MONO_HANDLE_GET (ctor_handle
, cattr
, ctor
);
100 *ctor_method
= MONO_HANDLE_GETVAL (ctor_handle
, method
);
102 /* FIXME: Need to do more checks */
104 MonoClass
*klass
= (*ctor_method
)->klass
;
105 if (m_class_get_image (klass
) != image
) {
106 const int visibility
= (mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
);
107 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
116 type_is_reference (MonoType
*type
)
118 switch (type
->type
) {
119 case MONO_TYPE_BOOLEAN
:
133 case MONO_TYPE_VALUETYPE
:
141 free_param_data (MonoMethodSignature
*sig
, void **params
) {
143 for (i
= 0; i
< sig
->param_count
; ++i
) {
144 if (!type_is_reference (sig
->params
[i
]))
150 * Find the field index in the metadata FieldDef table.
153 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
154 int fcount
= mono_class_get_field_count (klass
);
155 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
156 int index
= field
- klass_fields
;
160 g_assert (field
== &klass_fields
[index
]);
161 return mono_class_get_first_field_idx (klass
) + 1 + index
;
165 * Find the property index in the metadata Property table.
168 find_property_index (MonoClass
*klass
, MonoProperty
*property
)
171 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
173 for (i
= 0; i
< info
->count
; ++i
) {
174 if (property
== &info
->properties
[i
])
175 return info
->first
+ 1 + i
;
181 * Find the event index in the metadata Event table.
184 find_event_index (MonoClass
*klass
, MonoEvent
*event
)
187 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
189 for (i
= 0; i
< info
->count
; ++i
) {
190 if (event
== &info
->events
[i
])
191 return info
->first
+ 1 + i
;
197 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
198 * The @is_enum flag only affects the error message that's displayed on failure.
201 cattr_type_from_name (char *n
, MonoImage
*image
, gboolean is_enum
, MonoError
*error
)
203 ERROR_DECL (inner_error
);
204 MonoAssemblyLoadContext
*alc
= mono_domain_ambient_alc (mono_domain_get ());
205 MonoType
*t
= mono_reflection_type_from_name_checked (n
, alc
, image
, inner_error
);
207 mono_error_set_type_load_name (error
, g_strdup(n
), NULL
,
208 "Could not load %s %s while decoding custom attribute: %s",
209 is_enum
? "enum type": "type",
211 mono_error_get_message (inner_error
));
212 mono_error_cleanup (inner_error
);
219 load_cattr_enum_type (MonoImage
*image
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
)
226 if (!decode_blob_value_checked (p
, boundp
, &slen
, &p
, error
))
229 if (boundp
&& slen
> 0 && !bcheck_blob (p
, slen
- 1, boundp
, error
))
231 n
= (char *)g_memdup (p
, slen
+ 1);
233 t
= cattr_type_from_name (n
, image
, TRUE
, error
);
235 return_val_if_nok (error
, NULL
);
238 return mono_class_from_mono_type_internal (t
);
242 load_cattr_type (MonoImage
*image
, MonoType
*t
, gboolean header
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
, guint32
*slen
)
248 if (!bcheck_blob (p
, 0, boundp
, error
))
250 MONO_DISABLE_WARNING(4310) // cast truncates constant value
251 if (*p
== (char)0xFF) {
258 if (!decode_blob_value_checked (p
, boundp
, slen
, &p
, error
))
260 if (*slen
> 0 && !bcheck_blob (p
, *slen
- 1, boundp
, error
))
262 n
= (char *)g_memdup (p
, *slen
+ 1);
264 res
= cattr_type_from_name (n
, image
, FALSE
, error
);
266 return_val_if_nok (error
, NULL
);
274 * If OUT_OBJ is non-NULL, created objects are stored into it and NULL is returned.
275 * If OUT_OBJ is NULL, assert if objects were to be created.
278 load_cattr_value (MonoImage
*image
, MonoType
*t
, MonoObject
**out_obj
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
)
282 MonoClass
*tklass
= t
->data
.klass
;
289 if (type
== MONO_TYPE_GENERICINST
) {
290 MonoGenericClass
* mgc
= t
->data
.generic_class
;
291 MonoClass
* cc
= mgc
->container_class
;
292 if (m_class_is_enumtype (cc
)) {
293 tklass
= m_class_get_element_class (cc
);
294 t
= m_class_get_byval_arg (tklass
);
297 g_error ("Unhandled type of generic instance in load_cattr_value: %s", m_class_get_name (cc
));
305 case MONO_TYPE_BOOLEAN
: {
306 MonoBoolean
*bval
= (MonoBoolean
*)g_malloc (sizeof (MonoBoolean
));
307 if (!bcheck_blob (p
, 0, boundp
, error
))
316 guint16
*val
= (guint16
*)g_malloc (sizeof (guint16
));
317 if (!bcheck_blob (p
, 1, boundp
, error
))
323 #if SIZEOF_VOID_P == 4
330 guint32
*val
= (guint32
*)g_malloc (sizeof (guint32
));
331 if (!bcheck_blob (p
, 3, boundp
, error
))
337 #if SIZEOF_VOID_P == 8
338 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
343 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
344 if (!bcheck_blob (p
, 7, boundp
, error
))
351 double *val
= (double *)g_malloc (sizeof (double));
352 if (!bcheck_blob (p
, 7, boundp
, error
))
358 case MONO_TYPE_VALUETYPE
:
359 if (m_class_is_enumtype (t
->data
.klass
)) {
360 type
= mono_class_enum_basetype_internal (t
->data
.klass
)->type
;
363 MonoClass
*k
= t
->data
.klass
;
365 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){
366 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
367 if (!bcheck_blob (p
, 7, boundp
, error
))
374 g_error ("generic valutype %s not handled in custom attr value decoding", m_class_get_name (t
->data
.klass
));
377 case MONO_TYPE_STRING
:
378 if (!bcheck_blob (p
, 0, boundp
, error
))
380 MONO_DISABLE_WARNING (4310) // cast truncates constant value
381 if (*p
== (char)0xFF) {
386 if (!decode_blob_value_checked (p
, boundp
, &slen
, &p
, error
))
388 if (slen
> 0 && !bcheck_blob (p
, slen
- 1, boundp
, error
))
393 // https://bugzilla.xamarin.com/show_bug.cgi?id=60848
394 // Custom attribute strings are encoded as wtf-8 instead of utf-8.
395 // If we decode using utf-8 like the spec says, we will silently fail
396 // to decode some attributes in assemblies that Windows .NET Framework
397 // and CoreCLR both manage to decode.
398 // See https://simonsapin.github.io/wtf-8/ for a description of wtf-8.
399 *out_obj
= (MonoObject
*)mono_string_new_wtf8_len_checked (mono_domain_get (), p
, slen
, error
);
401 case MONO_TYPE_CLASS
: {
402 MonoType
*type
= load_cattr_type (image
, t
, TRUE
, p
, boundp
, end
, error
, &slen
);
406 *out_obj
= (MonoObject
*)mono_type_get_object_checked (mono_domain_get (), type
, error
);
412 case MONO_TYPE_OBJECT
: {
413 if (!bcheck_blob (p
, 0, boundp
, error
))
417 MonoClass
*subc
= NULL
;
420 if (subt
== CATTR_TYPE_SYSTEM_TYPE
) {
421 MonoType
*type
= load_cattr_type (image
, t
, FALSE
, p
, boundp
, end
, error
, &slen
);
425 *out_obj
= (MonoObject
*)mono_type_get_object_checked (mono_domain_get (), type
, error
);
430 } else if (subt
== 0x0E) {
431 type
= MONO_TYPE_STRING
;
433 } else if (subt
== 0x1D) {
434 MonoType simple_type
= {{0}};
435 if (!bcheck_blob (p
, 0, boundp
, error
))
440 type
= MONO_TYPE_SZARRAY
;
441 if (etype
== CATTR_TYPE_SYSTEM_TYPE
) {
442 tklass
= mono_defaults
.systemtype_class
;
443 } else if (etype
== MONO_TYPE_ENUM
) {
444 tklass
= load_cattr_enum_type (image
, p
, boundp
, &p
, error
);
448 if (etype
== CATTR_BOXED_VALUETYPE_PREFIX
)
449 /* See Partition II, Appendix B3 */
450 etype
= MONO_TYPE_OBJECT
;
451 simple_type
.type
= (MonoTypeEnum
)etype
;
452 tklass
= mono_class_from_mono_type_internal (&simple_type
);
455 } else if (subt
== MONO_TYPE_ENUM
) {
458 if (!decode_blob_value_checked (p
, boundp
, &slen
, &p
, error
))
460 if (slen
> 0 && !bcheck_blob (p
, slen
- 1, boundp
, error
))
462 n
= (char *)g_memdup (p
, slen
+ 1);
464 t
= cattr_type_from_name (n
, image
, FALSE
, error
);
466 return_val_if_nok (error
, NULL
);
468 subc
= mono_class_from_mono_type_internal (t
);
469 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
470 MonoType simple_type
= {{0}};
471 simple_type
.type
= (MonoTypeEnum
)subt
;
472 subc
= mono_class_from_mono_type_internal (&simple_type
);
474 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
476 val
= load_cattr_value (image
, m_class_get_byval_arg (subc
), NULL
, p
, boundp
, end
, error
);
478 obj
= mono_object_new_checked (mono_domain_get (), subc
, error
);
479 g_assert (!m_class_has_references (subc
));
481 mono_gc_memmove_atomic (mono_object_get_data (obj
), val
, mono_class_value_size (subc
, NULL
));
489 case MONO_TYPE_SZARRAY
: {
491 guint32 i
, alen
, basetype
;
493 if (!bcheck_blob (p
, 3, boundp
, error
))
497 if (alen
== 0xffffffff) {
502 arr
= mono_array_new_checked (mono_domain_get(), tklass
, alen
, error
);
503 return_val_if_nok (error
, NULL
);
505 basetype
= m_class_get_byval_arg (tklass
)->type
;
506 if (basetype
== MONO_TYPE_VALUETYPE
&& m_class_is_enumtype (tklass
))
507 basetype
= mono_class_enum_basetype_internal (tklass
)->type
;
509 if (basetype
== MONO_TYPE_GENERICINST
) {
510 MonoGenericClass
* mgc
= m_class_get_byval_arg (tklass
)->data
.generic_class
;
511 MonoClass
* cc
= mgc
->container_class
;
512 if (m_class_is_enumtype (cc
)) {
513 basetype
= m_class_get_byval_arg (m_class_get_element_class (cc
))->type
;
515 g_error ("Unhandled type of generic instance in load_cattr_value: %s[]", m_class_get_name (cc
));
522 case MONO_TYPE_BOOLEAN
:
523 for (i
= 0; i
< alen
; i
++) {
524 if (!bcheck_blob (p
, 0, boundp
, error
))
526 MonoBoolean val
= *p
++;
527 mono_array_set_internal (arr
, MonoBoolean
, i
, val
);
533 for (i
= 0; i
< alen
; i
++) {
534 if (!bcheck_blob (p
, 1, boundp
, error
))
536 guint16 val
= read16 (p
);
537 mono_array_set_internal (arr
, guint16
, i
, val
);
544 for (i
= 0; i
< alen
; i
++) {
545 if (!bcheck_blob (p
, 3, boundp
, error
))
547 guint32 val
= read32 (p
);
548 mono_array_set_internal (arr
, guint32
, i
, val
);
553 for (i
= 0; i
< alen
; i
++) {
554 if (!bcheck_blob (p
, 7, boundp
, error
))
558 mono_array_set_internal (arr
, double, i
, val
);
564 for (i
= 0; i
< alen
; i
++) {
565 if (!bcheck_blob (p
, 7, boundp
, error
))
567 guint64 val
= read64 (p
);
568 mono_array_set_internal (arr
, guint64
, i
, val
);
572 case MONO_TYPE_CLASS
:
573 case MONO_TYPE_OBJECT
:
574 case MONO_TYPE_STRING
:
575 case MONO_TYPE_SZARRAY
: {
576 HANDLE_FUNCTION_ENTER ();
577 MONO_HANDLE_NEW (MonoArray
, arr
);
579 for (i
= 0; i
< alen
; i
++) {
580 MonoObject
*item
= NULL
;
581 load_cattr_value (image
, m_class_get_byval_arg (tklass
), &item
, p
, boundp
, &p
, error
);
584 mono_array_setref_internal (arr
, i
, item
);
586 HANDLE_FUNCTION_RETURN ();
590 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
594 *out_obj
= (MonoObject
*)arr
;
599 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
605 load_cattr_value_boxed (MonoDomain
*domain
, MonoImage
*image
, MonoType
*t
, const char* p
, const char *boundp
, const char** end
, MonoError
*error
)
609 gboolean is_ref
= type_is_reference (t
);
612 MonoObject
*obj
= NULL
;
613 gpointer val
= load_cattr_value (image
, t
, &obj
, p
, boundp
, end
, error
);
619 void *val
= load_cattr_value (image
, t
, NULL
, p
, boundp
, end
, error
);
623 MonoObject
*boxed
= mono_value_box_checked (domain
, mono_class_from_mono_type_internal (t
), val
, error
);
630 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
, MonoError
*error
)
633 void *params
[2], *unboxed
;
637 HANDLE_FUNCTION_ENTER ();
639 MONO_STATIC_POINTER_INIT (MonoMethod
, ctor
)
641 ctor
= mono_class_get_method_from_name_checked (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2, 0, error
);
642 mono_error_assert_ok (error
);
644 MONO_STATIC_POINTER_INIT_END (MonoMethod
, ctor
)
646 params
[0] = mono_type_get_object_checked (mono_domain_get (), t
, error
);
647 return_val_if_nok (error
, NULL
);
648 MONO_HANDLE_PIN ((MonoObject
*)params
[0]);
651 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error
);
652 return_val_if_nok (error
, NULL
);
653 MONO_HANDLE_PIN (retval
);
655 unboxed
= mono_object_unbox_internal (retval
);
657 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
658 return_val_if_nok (error
, NULL
);
660 HANDLE_FUNCTION_RETURN ();
666 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
, MonoError
*error
)
669 void *unboxed
, *params
[2];
673 HANDLE_FUNCTION_ENTER ();
675 MONO_STATIC_POINTER_INIT (MonoMethod
, ctor
)
677 ctor
= mono_class_get_method_from_name_checked (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2, 0, error
);
678 mono_error_assert_ok (error
);
680 MONO_STATIC_POINTER_INIT_END (MonoMethod
, ctor
)
683 params
[1] = typedarg
;
684 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error
);
685 return_val_if_nok (error
, NULL
);
686 MONO_HANDLE_PIN (retval
);
688 unboxed
= mono_object_unbox_internal (retval
);
690 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
691 return_val_if_nok (error
, NULL
);
693 HANDLE_FUNCTION_RETURN ();
698 static MonoCustomAttrInfo
*
699 mono_custom_attrs_from_builders_handle (MonoImage
*alloc_img
, MonoImage
*image
, MonoArrayHandle cattrs
)
701 MONO_REQ_GC_UNSAFE_MODE
;
703 if (!MONO_HANDLE_BOOL (cattrs
))
706 HANDLE_FUNCTION_ENTER ();
708 /* FIXME: check in assembly the Run flag is set */
710 MonoReflectionCustomAttrHandle cattr
= MONO_HANDLE_NEW (MonoReflectionCustomAttr
, NULL
);
711 MonoArrayHandle cattr_data
= MONO_HANDLE_NEW (MonoArray
, NULL
);
712 MonoReflectionMethodHandle ctor_handle
= MONO_HANDLE_NEW (MonoReflectionMethod
, NULL
);
714 int const count
= mono_array_handle_length (cattrs
);
715 MonoMethod
*ctor_method
= NULL
;
717 /* Skip nonpublic attributes since MS.NET seems to do the same */
718 /* FIXME: This needs to be done more globally */
719 int count_visible
= 0;
720 for (int i
= 0; i
< count
; ++i
) {
721 MONO_HANDLE_ARRAY_GETREF (cattr
, cattrs
, i
);
722 count_visible
+= custom_attr_visible (image
, cattr
, ctor_handle
, &ctor_method
);
725 MonoCustomAttrInfo
*ainfo
;
726 ainfo
= (MonoCustomAttrInfo
*)mono_image_g_malloc0 (alloc_img
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * count_visible
);
728 ainfo
->image
= image
;
729 ainfo
->num_attrs
= count_visible
;
730 ainfo
->cached
= alloc_img
!= NULL
;
732 for (int i
= 0; i
< count
; ++i
) {
733 MONO_HANDLE_ARRAY_GETREF (cattr
, cattrs
, i
);
734 if (!custom_attr_visible (image
, cattr
, ctor_handle
, &ctor_method
))
737 if (image_is_dynamic (image
))
738 mono_reflection_resolution_scope_from_image ((MonoDynamicImage
*)image
->assembly
->image
, m_class_get_image (ctor_method
->klass
));
740 MONO_HANDLE_GET (cattr_data
, cattr
, data
);
741 unsigned char *saved
= (unsigned char *)mono_image_alloc (image
, mono_array_handle_length (cattr_data
));
742 MonoGCHandle gchandle
= NULL
;
743 memcpy (saved
, MONO_ARRAY_HANDLE_PIN (cattr_data
, char, 0, &gchandle
), mono_array_handle_length (cattr_data
));
744 mono_gchandle_free_internal (gchandle
);
745 ainfo
->attrs
[index
].ctor
= ctor_method
;
746 g_assert (ctor_method
);
747 ainfo
->attrs
[index
].data
= saved
;
748 ainfo
->attrs
[index
].data_size
= mono_array_handle_length (cattr_data
);
751 g_assert (index
== count_visible
);
752 HANDLE_FUNCTION_RETURN_VAL (ainfo
);
756 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
* cattrs
)
758 HANDLE_FUNCTION_ENTER ();
759 MonoCustomAttrInfo
* const result
= mono_custom_attrs_from_builders_handle (alloc_img
, image
, MONO_HANDLE_NEW (MonoArray
, cattrs
));
760 HANDLE_FUNCTION_RETURN_VAL (result
);
764 set_custom_attr_fmt_error (MonoError
*error
)
767 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
772 * \param ptr a pointer into a blob
773 * \param bump how far we plan on reading past \p ptr.
774 * \param endp upper bound for \p ptr - one past the last valid value for \p ptr.
775 * \param error set on error
777 * Check that ptr+bump is below endp. Returns TRUE on success, or FALSE on
778 * failure and sets \p error.
781 bcheck_blob (const char *ptr
, int bump
, const char *endp
, MonoError
*error
)
784 if (ADDP_IS_GREATER_OR_OVF (ptr
, bump
, endp
- 1)) {
785 set_custom_attr_fmt_error (error
);
792 * decode_blob_size_checked:
793 * \param ptr a pointer into a blob
794 * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
795 * \param size_out on success set to the decoded size
796 * \param retp on success set to the next byte after the encoded size
797 * \param error set on error
799 * Decode an encoded size value which takes 1, 2, or 4 bytes and set \p
800 * size_out to the decoded size and \p retp to the next byte after the encoded
801 * size. Returns TRUE on success, or FALASE on failure and sets \p error.
804 decode_blob_size_checked (const char *ptr
, const char *endp
, guint32
*size_out
, const char **retp
, MonoError
*error
)
807 if (endp
&& !bcheck_blob (ptr
, 0, endp
, error
))
809 if ((*ptr
& 0x80) != 0) {
810 if ((*ptr
& 0x40) == 0 && !bcheck_blob (ptr
, 1, endp
, error
))
812 else if (!bcheck_blob (ptr
, 3, endp
, error
))
815 *size_out
= mono_metadata_decode_blob_size (ptr
, retp
);
817 return is_ok (error
);
821 * decode_blob_value_checked:
822 * \param ptr a pointer into a blob
823 * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
824 * \param value_out on success set to the decoded value
825 * \param retp on success set to the next byte after the encoded size
826 * \param error set on error
828 * Decode an encoded uint32 value which takes 1, 2, or 4 bytes and set \p
829 * value_out to the decoded value and \p retp to the next byte after the
830 * encoded value. Returns TRUE on success, or FALASE on failure and sets \p
834 decode_blob_value_checked (const char *ptr
, const char *endp
, guint32
*value_out
, const char **retp
, MonoError
*error
)
836 /* This similar to decode_blob_size_checked, above but delegates to
837 * mono_metadata_decode_value which is semantically different. */
839 if (!bcheck_blob (ptr
, 0, endp
, error
))
841 if ((*ptr
& 0x80) != 0) {
842 if ((*ptr
& 0x40) == 0 && !bcheck_blob (ptr
, 1, endp
, error
))
844 else if (!bcheck_blob (ptr
, 3, endp
, error
))
847 *value_out
= mono_metadata_decode_value (ptr
, retp
);
849 return is_ok (error
);
852 static MonoObjectHandle
853 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoError
*error
)
855 HANDLE_FUNCTION_ENTER ();
857 const char *p
= (const char*)data
;
858 const char *data_end
= (const char*)data
+ len
;
860 guint32 i
, j
, num_named
;
861 MonoObjectHandle attr
= NULL_HANDLE
;
862 void *params_buf
[32];
863 void **params
= NULL
;
864 MonoMethodSignature
*sig
;
865 MonoClassField
*field
= NULL
;
867 void *pparams
[1] = { NULL
};
868 MonoType
*prop_type
= NULL
;
869 void *val
= NULL
; // FIXMEcoop is this a raw pointer or a value?
873 mono_class_init_internal (method
->klass
);
875 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, error
))
879 attr
= mono_object_new_handle (mono_domain_get (), method
->klass
, error
);
880 goto_if_nok (error
, fail
);
882 mono_runtime_invoke_handle_void (method
, attr
, NULL
, error
);
883 goto_if_nok (error
, fail
);
888 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
891 /*g_print ("got attr %s\n", method->klass->name);*/
893 sig
= mono_method_signature_internal (method
);
894 if (sig
->param_count
< 32) {
896 memset (params
, 0, sizeof (void*) * sig
->param_count
);
898 /* Allocate using GC so it gets GC tracking */
899 params
= (void **)mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), MONO_GC_DESCRIPTOR_NULL
, MONO_ROOT_SOURCE_REFLECTION
, NULL
, "Reflection Custom Attribute Parameters");
904 for (i
= 0; i
< mono_method_signature_internal (method
)->param_count
; ++i
) {
905 MonoObject
*param_obj
;
906 params
[i
] = load_cattr_value (image
, mono_method_signature_internal (method
)->params
[i
], ¶m_obj
, p
, data_end
, &p
, error
);
908 params
[i
] = param_obj
;
909 goto_if_nok (error
, fail
);
913 attr
= mono_object_new_handle (mono_domain_get (), method
->klass
, error
);
914 goto_if_nok (error
, fail
);
916 (void)mono_runtime_try_invoke_handle (method
, attr
, params
, error
);
917 goto_if_nok (error
, fail
);
919 if (named
+ 1 < data_end
) {
920 num_named
= read16 (named
);
923 /* CoreCLR allows p == data + len */
924 if (named
== data_end
)
927 set_custom_attr_fmt_error (error
);
931 for (j
= 0; j
< num_named
; j
++) {
933 char named_type
, data_type
;
934 if (!bcheck_blob (named
, 1, data_end
, error
))
936 named_type
= *named
++;
937 data_type
= *named
++; /* type of data */
938 if (data_type
== MONO_TYPE_SZARRAY
) {
939 if (!bcheck_blob (named
, 0, data_end
, error
))
941 data_type
= *named
++;
943 if (data_type
== MONO_TYPE_ENUM
) {
946 if (!decode_blob_size_checked (named
, data_end
, &type_len
, &named
, error
))
948 if (type_len
> 0 && !bcheck_blob (named
, type_len
- 1, data_end
, error
))
950 type_name
= (char *)g_malloc (type_len
+ 1);
951 memcpy (type_name
, named
, type_len
);
952 type_name
[type_len
] = 0;
954 /* FIXME: lookup the type and check type consistency */
957 if (!decode_blob_size_checked (named
, data_end
, &name_len
, &named
, error
))
959 if (name_len
> 0 && !bcheck_blob (named
, name_len
- 1, data_end
, error
))
961 name
= (char *)g_malloc (name_len
+ 1);
962 memcpy (name
, named
, name_len
);
965 if (named_type
== CATTR_TYPE_FIELD
) {
966 /* how this fail is a blackbox */
967 field
= mono_class_get_field_from_name_full (mono_handle_class (attr
), name
, NULL
);
969 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name
);
973 MonoObject
*param_obj
;
974 val
= load_cattr_value (image
, field
->type
, ¶m_obj
, named
, data_end
, &named
, error
);
977 goto_if_nok (error
, fail
);
979 mono_field_set_value_internal (MONO_HANDLE_RAW (attr
), field
, val
); // FIXMEcoop
980 } else if (named_type
== CATTR_TYPE_PROPERTY
) {
982 prop
= mono_class_get_property_from_name_internal (mono_handle_class (attr
), name
);
984 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name
);
989 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name
);
993 /* can we have more that 1 arg in a custom attr named property? */
994 prop_type
= prop
->get
? mono_method_signature_internal (prop
->get
)->ret
:
995 mono_method_signature_internal (prop
->set
)->params
[mono_method_signature_internal (prop
->set
)->param_count
- 1];
997 MonoObject
*param_obj
;
998 pparams
[0] = load_cattr_value (image
, prop_type
, ¶m_obj
, named
, data_end
, &named
, error
);
1000 pparams
[0] = param_obj
;
1001 goto_if_nok (error
, fail
);
1003 mono_property_set_value_handle (prop
, attr
, pparams
, error
);
1004 goto_if_nok (error
, fail
);
1015 attr
= mono_new_null ();
1017 if (field
&& !type_is_reference (field
->type
))
1019 if (prop_type
&& !type_is_reference (prop_type
))
1020 g_free (pparams
[0]);
1022 free_param_data (method
->signature
, params
);
1023 if (params
!= params_buf
)
1024 mono_gc_free_fixed (params
);
1027 HANDLE_FUNCTION_RETURN_REF (MonoObject
, attr
);
1031 create_custom_attr_into_array (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
,
1032 guint32 len
, MonoArrayHandle array
, int index
, MonoError
*error
)
1034 // This function serves to avoid creating handles in a loop.
1035 HANDLE_FUNCTION_ENTER ();
1036 MonoObjectHandle attr
= create_custom_attr (image
, method
, data
, len
, error
);
1037 MONO_HANDLE_ARRAY_SETREF (array
, index
, attr
);
1038 HANDLE_FUNCTION_RETURN ();
1042 * mono_reflection_create_custom_attr_data_args:
1044 * Create an array of typed and named arguments from the cattr blob given by DATA.
1045 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
1046 * NAMED_ARG_INFO will contain information about the named arguments.
1049 mono_reflection_create_custom_attr_data_args (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoArrayHandleOut typed_args_h
, MonoArrayHandleOut named_args_h
, CattrNamedArg
**named_arg_info
, MonoError
*error
)
1051 MonoArray
*typed_args
, *named_args
;
1052 MonoClass
*attrklass
;
1054 const char *p
= (const char*)data
;
1055 const char *data_end
= p
+ len
;
1057 guint32 i
, j
, num_named
;
1058 CattrNamedArg
*arginfo
= NULL
;
1060 MONO_HANDLE_ASSIGN_RAW (typed_args_h
, NULL
);
1061 MONO_HANDLE_ASSIGN_RAW (named_args_h
, NULL
);
1062 *named_arg_info
= NULL
;
1069 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, error
))
1072 mono_class_init_internal (method
->klass
);
1074 domain
= mono_domain_get ();
1076 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
1081 /* Parse each argument corresponding to the signature's parameters from
1082 * the blob and store in typed_args.
1084 typed_args
= mono_array_new_checked (domain
, mono_get_object_class (), mono_method_signature_internal (method
)->param_count
, error
);
1085 return_if_nok (error
);
1086 MONO_HANDLE_ASSIGN_RAW (typed_args_h
, typed_args
);
1088 for (i
= 0; i
< mono_method_signature_internal (method
)->param_count
; ++i
) {
1091 obj
= load_cattr_value_boxed (domain
, image
, mono_method_signature_internal (method
)->params
[i
], p
, data_end
, &p
, error
);
1092 return_if_nok (error
);
1093 mono_array_setref_internal (typed_args
, i
, obj
);
1098 /* Parse mandatory count of named arguments (could be zero) */
1099 if (!bcheck_blob (named
, 1, data_end
, error
))
1101 num_named
= read16 (named
);
1102 named_args
= mono_array_new_checked (domain
, mono_get_object_class (), num_named
, error
);
1103 return_if_nok (error
);
1104 MONO_HANDLE_ASSIGN_RAW (named_args_h
, named_args
);
1106 attrklass
= method
->klass
;
1108 arginfo
= g_new0 (CattrNamedArg
, num_named
);
1109 *named_arg_info
= arginfo
;
1111 /* Parse each named arg, and add to arginfo. Each named argument could
1112 * be a field name or a property name followed by a value. */
1113 for (j
= 0; j
< num_named
; j
++) {
1115 char *name
, named_type
, data_type
;
1116 if (!bcheck_blob (named
, 1, data_end
, error
))
1118 named_type
= *named
++; /* field or property? */
1119 data_type
= *named
++; /* type of data */
1120 if (data_type
== MONO_TYPE_SZARRAY
) {
1121 if (!bcheck_blob (named
, 0, data_end
, error
))
1123 data_type
= *named
++;
1125 if (data_type
== MONO_TYPE_ENUM
) {
1128 if (!decode_blob_size_checked (named
, data_end
, &type_len
, &named
, error
))
1130 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, type_len
, data
+ len
))
1133 type_name
= (char *)g_malloc (type_len
+ 1);
1134 memcpy (type_name
, named
, type_len
);
1135 type_name
[type_len
] = 0;
1137 /* FIXME: lookup the type and check type consistency */
1140 /* named argument name: length, then name */
1141 if (!decode_blob_size_checked(named
, data_end
, &name_len
, &named
, error
))
1143 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, name_len
, data
+ len
))
1145 name
= (char *)g_malloc (name_len
+ 1);
1146 memcpy (name
, named
, name_len
);
1147 name
[name_len
] = 0;
1149 if (named_type
== CATTR_TYPE_FIELD
) {
1150 /* Named arg is a field. */
1152 MonoClassField
*field
= mono_class_get_field_from_name_full (attrklass
, name
, NULL
);
1159 arginfo
[j
].type
= field
->type
;
1160 arginfo
[j
].field
= field
;
1162 obj
= load_cattr_value_boxed (domain
, image
, field
->type
, named
, data_end
, &named
, error
);
1163 if (!is_ok (error
)) {
1167 mono_array_setref_internal (named_args
, j
, obj
);
1169 } else if (named_type
== CATTR_TYPE_PROPERTY
) {
1170 /* Named arg is a property */
1172 MonoType
*prop_type
;
1173 MonoProperty
*prop
= mono_class_get_property_from_name_internal (attrklass
, name
);
1175 if (!prop
|| !prop
->set
) {
1180 prop_type
= prop
->get
? mono_method_signature_internal (prop
->get
)->ret
:
1181 mono_method_signature_internal (prop
->set
)->params
[mono_method_signature_internal (prop
->set
)->param_count
- 1];
1183 arginfo
[j
].type
= prop_type
;
1184 arginfo
[j
].prop
= prop
;
1186 obj
= load_cattr_value_boxed (domain
, image
, prop_type
, named
, data_end
, &named
, error
);
1187 if (!is_ok (error
)) {
1191 mono_array_setref_internal (named_args
, j
, obj
);
1198 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
1200 *named_arg_info
= NULL
;
1204 * mono_reflection_create_custom_attr_data_args_noalloc:
1206 * Same as mono_reflection_create_custom_attr_data_args but allocate no managed objects, return values
1207 * using C arrays. Only usable for cattrs with primitive/type arguments.
1208 * TYPED_ARGS, NAMED_ARGS, and NAMED_ARG_INFO should be freed using g_free ().
1211 mono_reflection_create_custom_attr_data_args_noalloc (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
,
1212 gpointer
**typed_args_out
, gpointer
**named_args_out
, int *num_named_args
,
1213 CattrNamedArg
**named_arg_info
, MonoError
*error
)
1215 gpointer
*typed_args
, *named_args
;
1216 MonoClass
*attrklass
;
1217 const char *p
= (const char*)data
;
1218 const char *data_end
= p
+ len
;
1220 guint32 i
, j
, num_named
;
1221 CattrNamedArg
*arginfo
= NULL
;
1222 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
1224 *typed_args_out
= NULL
;
1225 *named_args_out
= NULL
;
1226 *named_arg_info
= NULL
;
1233 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, error
))
1236 mono_class_init_internal (method
->klass
);
1238 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
1244 typed_args
= g_new0 (gpointer
, sig
->param_count
);
1246 for (i
= 0; i
< sig
->param_count
; ++i
) {
1247 typed_args
[i
] = load_cattr_value (image
, sig
->params
[i
], NULL
, p
, data_end
, &p
, error
);
1248 return_if_nok (error
);
1253 /* Parse mandatory count of named arguments (could be zero) */
1254 if (!bcheck_blob (named
, 1, data_end
, error
))
1256 num_named
= read16 (named
);
1257 named_args
= g_new0 (gpointer
, num_named
);
1258 return_if_nok (error
);
1260 attrklass
= method
->klass
;
1262 arginfo
= g_new0 (CattrNamedArg
, num_named
);
1263 *named_arg_info
= arginfo
;
1264 *num_named_args
= num_named
;
1266 /* Parse each named arg, and add to arginfo. Each named argument could
1267 * be a field name or a property name followed by a value. */
1268 for (j
= 0; j
< num_named
; j
++) {
1270 char *name
, named_type
, data_type
;
1271 if (!bcheck_blob (named
, 1, data_end
, error
))
1273 named_type
= *named
++; /* field or property? */
1274 data_type
= *named
++; /* type of data */
1275 if (data_type
== MONO_TYPE_SZARRAY
) {
1276 if (!bcheck_blob (named
, 0, data_end
, error
))
1278 data_type
= *named
++;
1280 if (data_type
== MONO_TYPE_ENUM
) {
1283 if (!decode_blob_size_checked (named
, data_end
, &type_len
, &named
, error
))
1285 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, type_len
, data
+ len
))
1288 type_name
= (char *)g_malloc (type_len
+ 1);
1289 memcpy (type_name
, named
, type_len
);
1290 type_name
[type_len
] = 0;
1292 /* FIXME: lookup the type and check type consistency */
1295 /* named argument name: length, then name */
1296 if (!decode_blob_size_checked(named
, data_end
, &name_len
, &named
, error
))
1298 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, name_len
, data
+ len
))
1300 name
= (char *)g_malloc (name_len
+ 1);
1301 memcpy (name
, named
, name_len
);
1302 name
[name_len
] = 0;
1304 if (named_type
== CATTR_TYPE_FIELD
) {
1305 /* Named arg is a field. */
1306 MonoClassField
*field
= mono_class_get_field_from_name_full (attrklass
, name
, NULL
);
1313 arginfo
[j
].type
= field
->type
;
1314 arginfo
[j
].field
= field
;
1316 named_args
[j
] = load_cattr_value (image
, field
->type
, NULL
, named
, data_end
, &named
, error
);
1317 if (!is_ok (error
)) {
1321 } else if (named_type
== CATTR_TYPE_PROPERTY
) {
1322 /* Named arg is a property */
1323 MonoType
*prop_type
;
1324 MonoProperty
*prop
= mono_class_get_property_from_name_internal (attrklass
, name
);
1326 if (!prop
|| !prop
->set
) {
1331 prop_type
= prop
->get
? mono_method_signature_internal (prop
->get
)->ret
:
1332 mono_method_signature_internal (prop
->set
)->params
[mono_method_signature_internal (prop
->set
)->param_count
- 1];
1334 arginfo
[j
].type
= prop_type
;
1335 arginfo
[j
].prop
= prop
;
1337 named_args
[j
] = load_cattr_value (image
, prop_type
, NULL
, named
, data_end
, &named
, error
);
1338 if (!is_ok (error
)) {
1346 *typed_args_out
= typed_args
;
1347 *named_args_out
= named_args
;
1350 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
1351 g_free (typed_args
);
1352 g_free (named_args
);
1354 *named_arg_info
= NULL
;
1358 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethodHandle ref_method_h
, MonoReflectionAssemblyHandle assembly_h
,
1359 gpointer data
, guint32 len
,
1360 MonoArrayHandleOut ctor_args_h
, MonoArrayHandleOut named_args_h
,
1364 MonoArray
*typed_args
, *named_args
;
1367 CattrNamedArg
*arginfo
= NULL
;
1368 MonoReflectionMethod
*ref_method
= MONO_HANDLE_RAW (ref_method_h
);
1369 MonoReflectionAssembly
*assembly
= MONO_HANDLE_RAW (assembly_h
);
1370 MonoMethodSignature
*sig
;
1371 MonoObjectHandle obj_h
, namedarg_h
, typedarg_h
, minfo_h
;
1377 obj_h
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1378 namedarg_h
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1379 typedarg_h
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1380 minfo_h
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1382 image
= assembly
->assembly
->image
;
1383 method
= ref_method
->method
;
1384 domain
= mono_object_domain (ref_method
);
1386 if (!mono_class_init_internal (method
->klass
)) {
1387 mono_error_set_for_class_failure (error
, method
->klass
);
1392 mono_reflection_create_custom_attr_data_args (image
, method
, (const guchar
*)data
, len
, ctor_args_h
, named_args_h
, &arginfo
, error
);
1393 goto_if_nok (error
, leave
);
1394 typed_args
= MONO_HANDLE_RAW (ctor_args_h
);
1395 named_args
= MONO_HANDLE_RAW (named_args_h
);
1397 if (!typed_args
|| !named_args
)
1400 sig
= mono_method_signature_internal (method
);
1401 for (i
= 0; i
< sig
->param_count
; ++i
) {
1403 MonoObject
*typedarg
;
1406 obj
= mono_array_get_internal (typed_args
, MonoObject
*, i
);
1407 MONO_HANDLE_ASSIGN_RAW (obj_h
, obj
);
1409 t
= sig
->params
[i
];
1410 if (t
->type
== MONO_TYPE_OBJECT
&& obj
)
1411 t
= m_class_get_byval_arg (obj
->vtable
->klass
);
1412 typedarg
= create_cattr_typed_arg (t
, obj
, error
);
1413 goto_if_nok (error
, leave
);
1414 mono_array_setref_internal (typed_args
, i
, typedarg
);
1417 for (i
= 0; i
< mono_array_length_internal (named_args
); ++i
) {
1419 MonoObject
*namedarg
, *minfo
;
1421 obj
= mono_array_get_internal (named_args
, MonoObject
*, i
);
1422 MONO_HANDLE_ASSIGN_RAW (obj_h
, obj
);
1423 if (arginfo
[i
].prop
) {
1424 minfo
= (MonoObject
*)mono_property_get_object_checked (domain
, arginfo
[i
].prop
->parent
, arginfo
[i
].prop
, error
);
1428 minfo
= (MonoObject
*)mono_field_get_object_checked (domain
, NULL
, arginfo
[i
].field
, error
);
1429 goto_if_nok (error
, leave
);
1431 MONO_HANDLE_ASSIGN_RAW (minfo_h
, minfo
);
1434 namedarg
= create_cattr_named_arg (minfo
, obj
, error
);
1435 MONO_HANDLE_ASSIGN_RAW (namedarg_h
, namedarg
);
1437 MonoObject
* typedarg
= create_cattr_typed_arg (arginfo
[i
].type
, obj
, error
);
1438 MONO_HANDLE_ASSIGN_RAW (typedarg_h
, typedarg
);
1439 goto_if_nok (error
, leave
);
1440 namedarg
= create_cattr_named_arg (minfo
, typedarg
, error
);
1441 MONO_HANDLE_ASSIGN_RAW (namedarg_h
, namedarg
);
1443 goto_if_nok (error
, leave
);
1445 mono_array_setref_internal (named_args
, i
, namedarg
);
1453 try_get_cattr_data_class (MonoError
* error
)
1456 MonoClass
*res
= mono_class_try_get_customattribute_data_class ();
1458 mono_error_set_execution_engine (error
, "Class System.Reflection.CustomAttributeData not found, probably removed by the linker");
1462 static MonoObjectHandle
1463 create_custom_attr_data (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoError
*error
)
1465 HANDLE_FUNCTION_ENTER ();
1467 static MonoMethod
*ctor
;
1474 g_assert (image
->assembly
);
1475 MonoObjectHandle attr
;
1477 MonoClass
*cattr_data
= try_get_cattr_data_class (error
);
1478 goto_if_nok (error
, result_null
);
1481 MonoMethod
*tmp
= mono_class_get_method_from_name_checked (cattr_data
, ".ctor", 4, 0, error
);
1482 mono_error_assert_ok (error
);
1485 mono_memory_barrier (); //safe publish!
1489 domain
= mono_domain_get ();
1491 attr
= mono_object_new_handle (domain
, cattr_data
, error
);
1492 goto_if_nok (error
, fail
);
1494 MonoReflectionMethodHandle ctor_obj
;
1495 ctor_obj
= mono_method_get_object_handle (domain
, cattr
->ctor
, NULL
, error
);
1496 goto_if_nok (error
, fail
);
1497 MonoReflectionAssemblyHandle assm
;
1498 assm
= mono_assembly_get_object_handle (domain
, image
->assembly
, error
);
1499 goto_if_nok (error
, fail
);
1500 params
[0] = MONO_HANDLE_RAW (ctor_obj
);
1501 params
[1] = MONO_HANDLE_RAW (assm
);
1502 params
[2] = &cattr
->data
;
1503 params
[3] = &cattr
->data_size
;
1505 mono_runtime_invoke_handle_void (ctor
, attr
, params
, error
);
1508 attr
= MONO_HANDLE_CAST (MonoObject
, mono_new_null ());
1510 HANDLE_FUNCTION_RETURN_REF (MonoObject
, attr
);
1516 create_custom_attr_data_into_array (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoArrayHandle result
, int index
, MonoError
*error
)
1518 // This function serves to avoid creating handles in a loop.
1519 HANDLE_FUNCTION_ENTER ();
1520 MonoObjectHandle attr
= create_custom_attr_data (image
, cattr
, error
);
1521 goto_if_nok (error
, exit
);
1522 MONO_HANDLE_ARRAY_SETREF (result
, index
, attr
);
1524 HANDLE_FUNCTION_RETURN ();
1527 static MonoArrayHandle
1528 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
, MonoError
*error
)
1530 HANDLE_FUNCTION_ENTER ();
1532 MonoArrayHandle result
;
1537 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1538 MonoCustomAttrEntry
*centry
= &cinfo
->attrs
[i
];
1539 if (!centry
->ctor
) {
1540 /* The cattr type is not finished yet */
1541 /* We should include the type name but cinfo doesn't contain it */
1542 mono_error_set_type_load_name (error
, NULL
, NULL
, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1549 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1550 MonoMethod
*ctor
= cinfo
->attrs
[i
].ctor
;
1552 if (mono_class_is_assignable_from_internal (attr_klass
, ctor
->klass
))
1556 n
= cinfo
->num_attrs
;
1559 result
= mono_array_new_cached_handle (mono_domain_get (), mono_defaults
.attribute_class
, n
, error
);
1560 goto_if_nok (error
, return_null
);
1562 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1563 MonoCustomAttrEntry
*centry
= &cinfo
->attrs
[i
];
1564 if (!attr_klass
|| mono_class_is_assignable_from_internal (attr_klass
, centry
->ctor
->klass
)) {
1565 create_custom_attr_into_array (cinfo
->image
, centry
->ctor
, centry
->data
,
1566 centry
->data_size
, result
, n
, error
);
1567 goto_if_nok (error
, exit
);
1573 result
= MONO_HANDLE_CAST (MonoArray
, mono_new_null ());
1575 HANDLE_FUNCTION_RETURN_REF (MonoArray
, result
);
1579 * mono_custom_attrs_construct:
1582 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
1584 HANDLE_FUNCTION_ENTER ();
1586 MonoArrayHandle result
= mono_custom_attrs_construct_by_type (cinfo
, NULL
, error
);
1587 mono_error_assert_ok (error
); /*FIXME proper error handling*/
1588 HANDLE_FUNCTION_RETURN_OBJ (result
);
1591 static MonoArrayHandle
1592 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
, MonoError
*error
)
1594 HANDLE_FUNCTION_ENTER ();
1596 MonoArrayHandle result
;
1597 MonoClass
*cattr_data
= try_get_cattr_data_class (error
);
1598 goto_if_nok (error
, return_null
);
1600 result
= mono_array_new_handle (mono_domain_get (), cattr_data
, cinfo
->num_attrs
, error
);
1601 goto_if_nok (error
, return_null
);
1602 for (int i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1603 create_custom_attr_data_into_array (cinfo
->image
, &cinfo
->attrs
[i
], result
, i
, error
);
1604 goto_if_nok (error
, return_null
);
1608 result
= MONO_HANDLE_CAST (MonoArray
, mono_new_null ());
1610 HANDLE_FUNCTION_RETURN_REF (MonoArray
, result
);
1614 * mono_custom_attrs_from_index:
1616 * Returns: NULL if no attributes are found or if a loading error occurs.
1619 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
1622 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1623 mono_error_cleanup (error
);
1627 * mono_custom_attrs_from_index_checked:
1628 * \returns NULL if no attributes are found. On error returns NULL and sets \p error.
1631 mono_custom_attrs_from_index_checked (MonoImage
*image
, guint32 idx
, gboolean ignore_missing
, MonoError
*error
)
1633 guint32 mtoken
, i
, len
;
1634 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
1636 MonoCustomAttrInfo
*ainfo
;
1639 MonoCustomAttrEntry
* attr
;
1643 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1645 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
1649 // initial size chosen arbitrarily, but default is 16 which is rather small
1650 attr_array
= g_array_sized_new (TRUE
, TRUE
, sizeof (guint32
), 128);
1651 while (i
< ca
->rows
) {
1652 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
1654 attr_array
= g_array_append_val (attr_array
, i
);
1657 len
= attr_array
->len
;
1659 g_array_free (attr_array
, TRUE
);
1662 ainfo
= (MonoCustomAttrInfo
*)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * len
);
1663 ainfo
->num_attrs
= len
;
1664 ainfo
->image
= image
;
1665 for (i
= 0; i
< len
; ++i
) {
1666 mono_metadata_decode_row (ca
, g_array_index (attr_array
, guint32
, i
), cols
, MONO_CUSTOM_ATTR_SIZE
);
1667 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
1668 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
1669 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
1670 mtoken
|= MONO_TOKEN_METHOD_DEF
;
1672 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
1673 mtoken
|= MONO_TOKEN_MEMBER_REF
;
1676 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
1679 attr
= &ainfo
->attrs
[i
];
1680 attr
->ctor
= mono_get_method_checked (image
, mtoken
, NULL
, NULL
, error
);
1682 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image
->name
, mtoken
, mono_error_get_message (error
));
1683 if (ignore_missing
) {
1684 mono_error_cleanup (error
);
1687 g_array_free (attr_array
, TRUE
);
1693 if (!mono_verifier_verify_cattr_blob (image
, cols
[MONO_CUSTOM_ATTR_VALUE
], error
)) {
1694 g_array_free (attr_array
, TRUE
);
1698 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
1699 attr
->data_size
= mono_metadata_decode_value (data
, &data
);
1700 attr
->data
= (guchar
*)data
;
1702 g_array_free (attr_array
, TRUE
);
1708 * mono_custom_attrs_from_method:
1711 mono_custom_attrs_from_method (MonoMethod
*method
)
1714 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_method_checked (method
, error
);
1715 mono_error_cleanup (error
); /* FIXME want a better API that doesn't swallow the error */
1720 mono_custom_attrs_from_method_checked (MonoMethod
*method
, MonoError
*error
)
1727 * An instantiated method has the same cattrs as the generic method definition.
1729 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1730 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1732 if (method
->is_inflated
)
1733 method
= ((MonoMethodInflated
*) method
)->declaring
;
1735 if (method_is_dynamic (method
) || image_is_dynamic (m_class_get_image (method
->klass
)))
1736 return lookup_custom_attr (m_class_get_image (method
->klass
), method
);
1739 /* Synthetic methods */
1742 idx
= custom_attrs_idx_from_method (method
);
1743 return mono_custom_attrs_from_index_checked (m_class_get_image (method
->klass
), idx
, FALSE
, error
);
1747 * mono_custom_attrs_from_class:
1750 mono_custom_attrs_from_class (MonoClass
*klass
)
1753 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_class_checked (klass
, error
);
1754 mono_error_cleanup (error
);
1759 custom_attrs_idx_from_class (MonoClass
*klass
)
1762 g_assert (!image_is_dynamic (m_class_get_image (klass
)));
1763 if (m_class_get_byval_arg (klass
)->type
== MONO_TYPE_VAR
|| m_class_get_byval_arg (klass
)->type
== MONO_TYPE_MVAR
) {
1764 idx
= mono_metadata_token_index (m_class_get_sizes (klass
).generic_param_token
);
1765 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1766 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
1768 idx
= mono_metadata_token_index (m_class_get_type_token (klass
));
1769 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1770 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
1776 custom_attrs_idx_from_method (MonoMethod
*method
)
1779 g_assert (!image_is_dynamic (m_class_get_image (method
->klass
)));
1780 idx
= mono_method_get_index (method
);
1781 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1782 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
1787 mono_custom_attrs_from_class_checked (MonoClass
*klass
, MonoError
*error
)
1793 if (mono_class_is_ginst (klass
))
1794 klass
= mono_class_get_generic_class (klass
)->container_class
;
1796 if (image_is_dynamic (m_class_get_image (klass
)))
1797 return lookup_custom_attr (m_class_get_image (klass
), klass
);
1799 idx
= custom_attrs_idx_from_class (klass
);
1801 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1805 * mono_custom_attrs_from_assembly:
1808 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
1811 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_assembly_checked (assembly
, FALSE
, error
);
1812 mono_error_cleanup (error
);
1817 mono_custom_attrs_from_assembly_checked (MonoAssembly
*assembly
, gboolean ignore_missing
, MonoError
*error
)
1823 if (image_is_dynamic (assembly
->image
))
1824 return lookup_custom_attr (assembly
->image
, assembly
);
1825 idx
= 1; /* there is only one assembly */
1826 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1827 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
1828 return mono_custom_attrs_from_index_checked (assembly
->image
, idx
, ignore_missing
, error
);
1831 static MonoCustomAttrInfo
*
1832 mono_custom_attrs_from_module (MonoImage
*image
, MonoError
*error
)
1838 if (image_is_dynamic (image
))
1839 return lookup_custom_attr (image
, image
);
1840 idx
= 1; /* there is only one module */
1841 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1842 idx
|= MONO_CUSTOM_ATTR_MODULE
;
1843 return mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1847 * mono_custom_attrs_from_property:
1850 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
1853 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_property_checked (klass
, property
, error
);
1854 mono_error_cleanup (error
);
1859 mono_custom_attrs_from_property_checked (MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
1865 if (image_is_dynamic (m_class_get_image (klass
))) {
1866 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
1867 return lookup_custom_attr (m_class_get_image (klass
), property
);
1869 idx
= find_property_index (klass
, property
);
1870 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1871 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
1872 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1876 * mono_custom_attrs_from_event:
1879 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
1882 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_event_checked (klass
, event
, error
);
1883 mono_error_cleanup (error
);
1888 mono_custom_attrs_from_event_checked (MonoClass
*klass
, MonoEvent
*event
, MonoError
*error
)
1894 if (image_is_dynamic (m_class_get_image (klass
))) {
1895 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
1896 return lookup_custom_attr (m_class_get_image (klass
), event
);
1898 idx
= find_event_index (klass
, event
);
1899 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1900 idx
|= MONO_CUSTOM_ATTR_EVENT
;
1901 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1905 * mono_custom_attrs_from_field:
1908 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
1911 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_field_checked (klass
, field
, error
);
1912 mono_error_cleanup (error
);
1917 mono_custom_attrs_from_field_checked (MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
1922 if (image_is_dynamic (m_class_get_image (klass
))) {
1923 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
1924 return lookup_custom_attr (m_class_get_image (klass
), field
);
1926 idx
= find_field_index (klass
, field
);
1927 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1928 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
1929 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1933 * mono_custom_attrs_from_param:
1934 * \param method handle to the method that we want to retrieve custom parameter information from
1935 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1937 * The result must be released with mono_custom_attrs_free().
1939 * \returns the custom attribute object for the specified parameter, or NULL if there are none.
1942 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
1945 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_param_checked (method
, param
, error
);
1946 mono_error_cleanup (error
);
1951 * mono_custom_attrs_from_param_checked:
1952 * \param method handle to the method that we want to retrieve custom parameter information from
1953 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1954 * \param error set on error
1956 * The result must be released with mono_custom_attrs_free().
1958 * \returns the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets \p error.
1961 mono_custom_attrs_from_param_checked (MonoMethod
*method
, guint32 param
, MonoError
*error
)
1964 guint32 i
, idx
, method_index
;
1965 guint32 param_list
, param_last
, param_pos
, found
;
1967 MonoReflectionMethodAux
*aux
;
1972 * An instantiated method has the same cattrs as the generic method definition.
1974 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1975 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1977 if (method
->is_inflated
)
1978 method
= ((MonoMethodInflated
*) method
)->declaring
;
1980 if (image_is_dynamic (m_class_get_image (method
->klass
))) {
1981 MonoCustomAttrInfo
*res
, *ainfo
;
1984 aux
= (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)m_class_get_image (method
->klass
))->method_aux_hash
, method
);
1985 if (!aux
|| !aux
->param_cattr
)
1988 /* Need to copy since it will be freed later */
1989 ainfo
= aux
->param_cattr
[param
];
1992 size
= MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * ainfo
->num_attrs
;
1993 res
= (MonoCustomAttrInfo
*)g_malloc0 (size
);
1994 memcpy (res
, ainfo
, size
);
1998 image
= m_class_get_image (method
->klass
);
1999 method_index
= mono_method_get_index (method
);
2002 ca
= &image
->tables
[MONO_TABLE_METHOD
];
2004 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
2005 if (method_index
== ca
->rows
) {
2006 ca
= &image
->tables
[MONO_TABLE_PARAM
];
2007 param_last
= ca
->rows
+ 1;
2009 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
2010 ca
= &image
->tables
[MONO_TABLE_PARAM
];
2013 for (i
= param_list
; i
< param_last
; ++i
) {
2014 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
2015 if (param_pos
== param
) {
2023 idx
<<= MONO_CUSTOM_ATTR_BITS
;
2024 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
2025 return mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
2029 * mono_custom_attrs_has_attr:
2032 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
2035 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
2036 MonoCustomAttrEntry
*centry
= &ainfo
->attrs
[i
];
2037 if (centry
->ctor
== NULL
)
2039 MonoClass
*klass
= centry
->ctor
->klass
;
2040 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
)))
2047 * mono_custom_attrs_get_attr:
2050 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
2053 MonoObject
*res
= mono_custom_attrs_get_attr_checked (ainfo
, attr_klass
, error
);
2054 mono_error_assert_ok (error
); /*FIXME proper error handling*/
2059 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
, MonoError
*error
)
2062 MonoCustomAttrEntry
*centry
= NULL
;
2064 g_assert (attr_klass
!= NULL
);
2068 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
2069 centry
= &ainfo
->attrs
[i
];
2070 if (centry
->ctor
== NULL
)
2072 MonoClass
*klass
= centry
->ctor
->klass
;
2073 if (attr_klass
== klass
|| mono_class_is_assignable_from_internal (attr_klass
, klass
)) {
2074 HANDLE_FUNCTION_ENTER ();
2075 MonoObjectHandle result
= create_custom_attr (ainfo
->image
, centry
->ctor
, centry
->data
, centry
->data_size
, error
);
2076 HANDLE_FUNCTION_RETURN_OBJ (result
);
2084 * mono_reflection_get_custom_attrs_info:
2085 * \param obj a reflection object handle
2087 * \returns the custom attribute info for attributes defined for the
2088 * reflection handle \p obj. The objects.
2090 * FIXME this function leaks like a sieve for SRE objects.
2093 mono_reflection_get_custom_attrs_info (MonoObject
*obj_raw
)
2095 HANDLE_FUNCTION_ENTER ();
2097 MONO_HANDLE_DCL (MonoObject
, obj
);
2098 MonoCustomAttrInfo
* const result
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
2099 mono_error_assert_ok (error
);
2100 HANDLE_FUNCTION_RETURN_VAL (result
);
2104 * mono_reflection_get_custom_attrs_info_checked:
2105 * \param obj a reflection object handle
2106 * \param error set on error
2108 * \returns the custom attribute info for attributes defined for the
2109 * reflection handle \p obj. The objects. On failure returns NULL and sets \p error.
2111 * FIXME this function leaks like a sieve for SRE objects.
2114 mono_reflection_get_custom_attrs_info_checked (MonoObjectHandle obj
, MonoError
*error
)
2116 HANDLE_FUNCTION_ENTER ();
2118 MonoCustomAttrInfo
*cinfo
= NULL
;
2122 klass
= mono_handle_class (obj
);
2123 const char *klass_name
= m_class_get_name (klass
);
2124 if (klass
== mono_defaults
.runtimetype_class
) {
2125 MonoType
*type
= mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST(MonoReflectionType
, obj
), error
);
2126 goto_if_nok (error
, leave
);
2127 klass
= mono_class_from_mono_type_internal (type
);
2128 /*We cannot mono_class_init_internal the class from which we'll load the custom attributes since this must work with broken types.*/
2129 cinfo
= mono_custom_attrs_from_class_checked (klass
, error
);
2130 goto_if_nok (error
, leave
);
2131 } else if (strcmp ("Assembly", klass_name
) == 0 || strcmp ("RuntimeAssembly", klass_name
) == 0) {
2132 MonoReflectionAssemblyHandle rassembly
= MONO_HANDLE_CAST (MonoReflectionAssembly
, obj
);
2133 cinfo
= mono_custom_attrs_from_assembly_checked (MONO_HANDLE_GETVAL (rassembly
, assembly
), FALSE
, error
);
2134 goto_if_nok (error
, leave
);
2135 } else if (strcmp ("RuntimeModule", klass_name
) == 0) {
2136 MonoReflectionModuleHandle module
= MONO_HANDLE_CAST (MonoReflectionModule
, obj
);
2137 cinfo
= mono_custom_attrs_from_module (MONO_HANDLE_GETVAL (module
, image
), error
);
2138 goto_if_nok (error
, leave
);
2139 } else if (strcmp ("RuntimePropertyInfo", klass_name
) == 0) {
2140 MonoReflectionPropertyHandle rprop
= MONO_HANDLE_CAST (MonoReflectionProperty
, obj
);
2141 MonoProperty
*property
= MONO_HANDLE_GETVAL (rprop
, property
);
2142 cinfo
= mono_custom_attrs_from_property_checked (property
->parent
, property
, error
);
2143 goto_if_nok (error
, leave
);
2144 } else if (strcmp ("RuntimeEventInfo", klass_name
) == 0) {
2145 MonoReflectionMonoEventHandle revent
= MONO_HANDLE_CAST (MonoReflectionMonoEvent
, obj
);
2146 MonoEvent
*event
= MONO_HANDLE_GETVAL (revent
, event
);
2147 cinfo
= mono_custom_attrs_from_event_checked (event
->parent
, event
, error
);
2148 goto_if_nok (error
, leave
);
2149 } else if (strcmp ("RuntimeFieldInfo", klass_name
) == 0) {
2150 MonoReflectionFieldHandle rfield
= MONO_HANDLE_CAST (MonoReflectionField
, obj
);
2151 MonoClassField
*field
= MONO_HANDLE_GETVAL (rfield
, field
);
2152 cinfo
= mono_custom_attrs_from_field_checked (field
->parent
, field
, error
);
2153 goto_if_nok (error
, leave
);
2154 } else if ((strcmp ("RuntimeMethodInfo", klass_name
) == 0) || (strcmp ("RuntimeConstructorInfo", klass_name
) == 0)) {
2155 MonoReflectionMethodHandle rmethod
= MONO_HANDLE_CAST (MonoReflectionMethod
, obj
);
2156 cinfo
= mono_custom_attrs_from_method_checked (MONO_HANDLE_GETVAL (rmethod
, method
), error
);
2157 goto_if_nok (error
, leave
);
2158 } else if (strcmp ("ParameterInfo", klass_name
) == 0 || strcmp ("RuntimeParameterInfo", klass_name
) == 0) {
2159 MonoReflectionParameterHandle param
= MONO_HANDLE_CAST (MonoReflectionParameter
, obj
);
2161 MonoObjectHandle member_impl
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2163 mono_reflection_get_param_info_member_and_pos (param
, member_impl
, &position
);
2165 MonoClass
*member_class
= mono_handle_class (member_impl
);
2166 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
2167 MonoReflectionMethodHandle rmethod
= MONO_HANDLE_CAST (MonoReflectionMethod
, member_impl
);
2168 cinfo
= mono_custom_attrs_from_param_checked (MONO_HANDLE_GETVAL (rmethod
, method
), position
+ 1, error
);
2169 goto_if_nok (error
, leave
);
2170 } else if (mono_is_sr_mono_property (member_class
)) {
2171 MonoReflectionPropertyHandle prop
= MONO_HANDLE_CAST (MonoReflectionProperty
, member_impl
);
2172 MonoProperty
*property
= MONO_HANDLE_GETVAL (prop
, property
);
2174 if (!(method
= property
->get
))
2175 method
= property
->set
;
2178 cinfo
= mono_custom_attrs_from_param_checked (method
, position
+ 1, error
);
2179 goto_if_nok (error
, leave
);
2181 #ifndef DISABLE_REFLECTION_EMIT
2182 else if (mono_is_sre_method_on_tb_inst (member_class
)) {/*XXX This is a workaround for Compiler Context*/
2183 // FIXME: Is this still needed ?
2184 g_assert_not_reached ();
2185 } else if (mono_is_sre_ctor_on_tb_inst (member_class
)) { /*XX This is a workaround for Compiler Context*/
2186 // FIXME: Is this still needed ?
2187 g_assert_not_reached ();
2191 char *type_name
= mono_type_get_full_name (member_class
);
2192 mono_error_set_not_supported (error
,
2193 "Custom attributes on a ParamInfo with member %s are not supported",
2198 } else if (strcmp ("AssemblyBuilder", klass_name
) == 0) {
2199 MonoReflectionAssemblyBuilderHandle assemblyb
= MONO_HANDLE_CAST (MonoReflectionAssemblyBuilder
, obj
);
2200 MonoReflectionAssemblyHandle assembly
= MONO_HANDLE_CAST (MonoReflectionAssembly
, assemblyb
);
2201 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, assemblyb
, cattrs
);
2202 MonoImage
* image
= MONO_HANDLE_GETVAL (assembly
, assembly
)->image
;
2204 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, image
, cattrs
);
2205 } else if (strcmp ("TypeBuilder", klass_name
) == 0) {
2206 MonoReflectionTypeBuilderHandle tb
= MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, obj
);
2207 MonoReflectionModuleBuilderHandle module
= MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder
, tb
, module
);
2208 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (module
, dynamic_image
);
2209 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, tb
, cattrs
);
2210 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, &dynamic_image
->image
, cattrs
);
2211 } else if (strcmp ("ModuleBuilder", klass_name
) == 0) {
2212 MonoReflectionModuleBuilderHandle mb
= MONO_HANDLE_CAST (MonoReflectionModuleBuilder
, obj
);
2213 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (mb
, dynamic_image
);
2214 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, mb
, cattrs
);
2215 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, &dynamic_image
->image
, cattrs
);
2216 } else if (strcmp ("ConstructorBuilder", klass_name
) == 0) {
2217 #ifdef ENABLE_NETCORE
2218 mono_error_set_not_supported (error
, "");
2221 MonoReflectionCtorBuilderHandle cb
= MONO_HANDLE_CAST (MonoReflectionCtorBuilder
, obj
);
2222 MonoMethod
*mhandle
= MONO_HANDLE_GETVAL (cb
, mhandle
);
2223 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, cb
, cattrs
);
2224 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, m_class_get_image (mhandle
->klass
), cattrs
);
2226 } else if (strcmp ("MethodBuilder", klass_name
) == 0) {
2227 MonoReflectionMethodBuilderHandle mb
= MONO_HANDLE_CAST (MonoReflectionMethodBuilder
, obj
);
2228 MonoMethod
*mhandle
= MONO_HANDLE_GETVAL (mb
, mhandle
);
2229 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, mb
, cattrs
);
2230 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, m_class_get_image (mhandle
->klass
), cattrs
);
2231 } else if (strcmp ("FieldBuilder", klass_name
) == 0) {
2232 MonoReflectionFieldBuilderHandle fb
= MONO_HANDLE_CAST (MonoReflectionFieldBuilder
, obj
);
2233 MonoReflectionTypeBuilderHandle tb
= MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, MONO_HANDLE_NEW_GET (MonoReflectionType
, fb
, typeb
));
2234 MonoReflectionModuleBuilderHandle mb
= MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder
, tb
, module
);
2235 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (mb
, dynamic_image
);
2236 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, fb
, cattrs
);
2237 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, &dynamic_image
->image
, cattrs
);
2238 } else if (strcmp ("MonoGenericClass", klass_name
) == 0) {
2239 MonoReflectionGenericClassHandle gclass
= MONO_HANDLE_CAST (MonoReflectionGenericClass
, obj
);
2240 MonoReflectionTypeHandle generic_type
= MONO_HANDLE_NEW_GET (MonoReflectionType
, gclass
, generic_type
);
2241 cinfo
= mono_reflection_get_custom_attrs_info_checked (MONO_HANDLE_CAST (MonoObject
, generic_type
), error
);
2242 goto_if_nok (error
, leave
);
2243 } else { /* handle other types here... */
2244 g_error ("get custom attrs not yet supported for %s", m_class_get_name (klass
));
2248 HANDLE_FUNCTION_RETURN_VAL (cinfo
);
2252 * mono_reflection_get_custom_attrs_by_type:
2253 * \param obj a reflection object handle
2254 * \returns an array with all the custom attributes defined of the
2255 * reflection handle \p obj. If \p attr_klass is non-NULL, only custom attributes
2256 * of that type are returned. The objects are fully build. Return NULL if a loading error
2260 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj_raw
, MonoClass
*attr_klass
, MonoError
*error
)
2262 HANDLE_FUNCTION_ENTER ();
2263 MONO_HANDLE_DCL (MonoObject
, obj
);
2264 MonoArrayHandle result
= mono_reflection_get_custom_attrs_by_type_handle (obj
, attr_klass
, error
);
2265 HANDLE_FUNCTION_RETURN_OBJ (result
);
2269 mono_reflection_get_custom_attrs_by_type_handle (MonoObjectHandle obj
, MonoClass
*attr_klass
, MonoError
*error
)
2271 MonoArrayHandle result
= MONO_HANDLE_NEW (MonoArray
, NULL
);
2272 MonoCustomAttrInfo
*cinfo
;
2276 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
2277 goto_if_nok (error
, leave
);
2279 MONO_HANDLE_ASSIGN (result
, mono_custom_attrs_construct_by_type (cinfo
, attr_klass
, error
));
2281 mono_custom_attrs_free (cinfo
);
2283 MONO_HANDLE_ASSIGN (result
, mono_array_new_handle (mono_domain_get (), mono_defaults
.attribute_class
, 0, error
));
2291 * mono_reflection_get_custom_attrs:
2292 * \param obj a reflection object handle
2293 * \return an array with all the custom attributes defined of the
2294 * reflection handle \p obj. The objects are fully build. Return NULL if a loading error
2298 mono_reflection_get_custom_attrs (MonoObject
*obj_raw
)
2300 HANDLE_FUNCTION_ENTER ();
2302 MONO_HANDLE_DCL (MonoObject
, obj
);
2303 MonoArrayHandle result
= mono_reflection_get_custom_attrs_by_type_handle (obj
, NULL
, error
);
2304 mono_error_cleanup (error
);
2305 HANDLE_FUNCTION_RETURN_OBJ (result
);
2309 * mono_reflection_get_custom_attrs_data:
2310 * \param obj a reflection obj handle
2311 * \returns an array of \c System.Reflection.CustomAttributeData,
2312 * which include information about attributes reflected on
2313 * types loaded using the Reflection Only methods
2316 mono_reflection_get_custom_attrs_data (MonoObject
*obj_raw
)
2318 HANDLE_FUNCTION_ENTER ();
2320 MONO_HANDLE_DCL (MonoObject
, obj
);
2321 MonoArrayHandle result
= mono_reflection_get_custom_attrs_data_checked (obj
, error
);
2322 mono_error_cleanup (error
);
2323 HANDLE_FUNCTION_RETURN_OBJ (result
);
2327 * mono_reflection_get_custom_attrs_data_checked:
2328 * @obj: a reflection obj handle
2329 * @error: set on error
2331 * Returns an array of System.Reflection.CustomAttributeData,
2332 * which include information about attributes reflected on
2333 * types loaded using the Reflection Only methods
2336 mono_reflection_get_custom_attrs_data_checked (MonoObjectHandle obj
, MonoError
*error
)
2338 MonoArrayHandle result
= MONO_HANDLE_NEW (MonoArray
, NULL
);
2339 MonoCustomAttrInfo
*cinfo
;
2341 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
2342 goto_if_nok (error
, leave
);
2344 MONO_HANDLE_ASSIGN (result
, mono_custom_attrs_data_construct (cinfo
, error
));
2346 mono_custom_attrs_free (cinfo
);
2347 goto_if_nok (error
, leave
);
2349 MonoClass
*cattr_data
= try_get_cattr_data_class (error
);
2350 goto_if_nok (error
, return_null
);
2352 MONO_HANDLE_ASSIGN (result
, mono_array_new_handle (mono_domain_get (), cattr_data
, 0, error
));
2356 result
= MONO_HANDLE_CAST (MonoArray
, mono_new_null ());
2362 custom_attr_class_name_from_methoddef (MonoImage
*image
, guint32 method_token
, const gchar
**nspace
, const gchar
**class_name
)
2364 /* mono_get_method_from_token () */
2365 g_assert (mono_metadata_token_table (method_token
) == MONO_TABLE_METHOD
);
2366 guint32 type_token
= mono_metadata_typedef_from_method (image
, method_token
);
2368 /* Bad method token (could not find corresponding typedef) */
2371 type_token
|= MONO_TOKEN_TYPE_DEF
;
2373 /* mono_class_create_from_typedef () */
2374 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2375 guint32 cols
[MONO_TYPEDEF_SIZE
];
2376 guint tidx
= mono_metadata_token_index (type_token
);
2378 if (mono_metadata_token_table (type_token
) != MONO_TABLE_TYPEDEF
|| tidx
> tt
->rows
) {
2379 /* "Invalid typedef token %x", type_token */
2383 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
2386 *class_name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2388 *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2395 * custom_attr_class_name_from_method_token:
2396 * @image: The MonoImage
2397 * @method_token: a token for a custom attr constructor in @image
2398 * @assembly_token: out argument set to the assembly ref token of the custom attr
2399 * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
2400 * @class_name: out argument set to the class name of the custom attr.
2402 * Given an @image and a @method_token (which is assumed to be a
2403 * constructor), fills in the out arguments with the assembly ref (if
2404 * a methodref) and the namespace and class name of the custom
2407 * Returns: TRUE on success, FALSE otherwise.
2409 * LOCKING: does not take locks
2412 custom_attr_class_name_from_method_token (MonoImage
*image
, guint32 method_token
, guint32
*assembly_token
, const gchar
**nspace
, const gchar
**class_name
)
2414 /* This only works with method tokens constructed from a
2415 * custom attr token, which can only be methoddef or
2417 g_assert (mono_metadata_token_table (method_token
) == MONO_TABLE_METHOD
2418 || mono_metadata_token_table (method_token
) == MONO_TABLE_MEMBERREF
);
2420 if (mono_metadata_token_table (method_token
) == MONO_TABLE_MEMBERREF
) {
2421 /* method_from_memberref () */
2423 guint32 nindex
, class_index
;
2425 int idx
= mono_metadata_token_index (method_token
);
2427 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], idx
-1, cols
, 3);
2428 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
2429 class_index
= cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
2430 if (class_index
== MONO_MEMBERREF_PARENT_TYPEREF
) {
2431 guint32 type_token
= MONO_TOKEN_TYPE_REF
| nindex
;
2432 /* mono_class_from_typeref_checked () */
2434 guint32 cols
[MONO_TYPEREF_SIZE
];
2435 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2437 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
2440 *class_name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2442 *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2444 *assembly_token
= cols
[MONO_TYPEREF_SCOPE
];
2447 } else if (class_index
== MONO_MEMBERREF_PARENT_METHODDEF
) {
2448 guint32 methoddef_token
= MONO_TOKEN_METHOD_DEF
| nindex
;
2450 *assembly_token
= 0;
2451 return custom_attr_class_name_from_methoddef (image
, methoddef_token
, nspace
, class_name
);
2453 /* Attributes can't be generic, so it won't be
2454 * a typespec, and they're always
2455 * constructors, so it won't be a moduleref */
2456 g_assert_not_reached ();
2459 /* must be MONO_TABLE_METHOD */
2461 *assembly_token
= 0;
2462 return custom_attr_class_name_from_methoddef (image
, method_token
, nspace
, class_name
);
2467 * mono_assembly_metadata_foreach_custom_attr:
2468 * \param assembly the assembly to iterate over
2469 * \param func the function to call for each custom attribute
2470 * \param user_data passed to \p func
2471 * Calls \p func for each custom attribute type on the given assembly until \p func returns TRUE.
2472 * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
2475 mono_assembly_metadata_foreach_custom_attr (MonoAssembly
*assembly
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
)
2481 * This might be called during assembly loading, so do everything using the low-level
2485 image
= assembly
->image
;
2486 /* Dynamic images would need to go through the AssemblyBuilder's
2487 * CustomAttributeBuilder array. Going through the tables below
2488 * definitely won't work. */
2489 g_assert (!image_is_dynamic (image
));
2490 idx
= 1; /* there is only one assembly */
2491 idx
<<= MONO_CUSTOM_ATTR_BITS
;
2492 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
2494 metadata_foreach_custom_attr_from_index (image
, idx
, func
, user_data
);
2498 * iterate over the custom attributes that belong to the given index and call func, passing the
2499 * assembly ref (if any) and the namespace and name of the custom attribute.
2501 * Everything is done using low-level metadata APIs, so it is safe to use
2502 * during assembly loading and class initialization.
2505 metadata_foreach_custom_attr_from_index (MonoImage
*image
, guint32 idx
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
)
2508 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
2511 /* Inlined from mono_custom_attrs_from_index_checked () */
2512 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2513 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
2517 gboolean stop_iterating
= FALSE
;
2518 while (!stop_iterating
&& i
< ca
->rows
) {
2519 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
2521 mono_metadata_decode_row (ca
, i
, cols
, MONO_CUSTOM_ATTR_SIZE
);
2523 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
2524 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
2525 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
2526 mtoken
|= MONO_TOKEN_METHOD_DEF
;
2528 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
2529 mtoken
|= MONO_TOKEN_MEMBER_REF
;
2532 g_warning ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
2536 const char *nspace
= NULL
;
2537 const char *name
= NULL
;
2538 guint32 assembly_token
= 0;
2540 if (!custom_attr_class_name_from_method_token (image
, mtoken
, &assembly_token
, &nspace
, &name
))
2543 stop_iterating
= func (image
, assembly_token
, nspace
, name
, mtoken
, user_data
);
2548 * mono_class_metadata_foreach_custom_attr:
2549 * \param klass - the class to iterate over
2550 * \param func the funciton to call for each custom attribute
2551 * \param user_data passed to \p func
2553 * Calls \p func for each custom attribute type on the given class until \p func returns TRUE.
2555 * Everything is done using low-level metadata APIs, so it is fafe to use
2556 * during assembly loading and class initialization.
2558 * The MonoClass \p klass should have the following fields initialized:
2560 * \c MonoClass:kind, \c MonoClass:image, \c MonoClassGenericInst:generic_class,
2561 * \c MonoClass:type_token, \c MonoClass:sizes.generic_param_token, MonoClass:byval_arg
2564 mono_class_metadata_foreach_custom_attr (MonoClass
*klass
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
)
2566 MonoImage
*image
= m_class_get_image (klass
);
2568 /* dynamic images don't store custom attributes in tables */
2569 g_assert (!image_is_dynamic (image
));
2571 if (mono_class_is_ginst (klass
))
2572 klass
= mono_class_get_generic_class (klass
)->container_class
;
2574 guint32 idx
= custom_attrs_idx_from_class (klass
);
2576 metadata_foreach_custom_attr_from_index (image
, idx
, func
, user_data
);
2580 * mono_method_metadata_foreach_custom_attr:
2581 * \param method - the method to iterate over
2582 * \param func the funciton to call for each custom attribute
2583 * \param user_data passed to \p func
2585 * Calls \p func for each custom attribute type on the given class until \p func returns TRUE.
2587 * Everything is done using low-level metadata APIs, so it is fafe to use
2588 * during assembly loading and class initialization.
2592 mono_method_metadata_foreach_custom_attr (MonoMethod
*method
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
)
2594 if (method
->is_inflated
)
2595 method
= ((MonoMethodInflated
*) method
)->declaring
;
2597 MonoImage
*image
= m_class_get_image (method
->klass
);
2599 g_assert (!image_is_dynamic (image
));
2604 guint32 idx
= custom_attrs_idx_from_method (method
);
2606 metadata_foreach_custom_attr_from_index (image
, idx
, func
, user_data
);
2610 init_weak_fields_inner (MonoImage
*image
, GHashTable
*indexes
)
2612 MonoTableInfo
*tdef
;
2614 MonoClass
*klass
= NULL
;
2615 guint32 memberref_index
= -1;
2616 int first_method_idx
= -1;
2617 int method_count
= -1;
2619 if (image
== mono_get_corlib ()) {
2621 klass
= mono_class_from_name_checked (image
, "System", "WeakAttribute", error
);
2622 if (!is_ok (error
)) {
2623 mono_error_cleanup (error
);
2628 first_method_idx
= mono_class_get_first_method_idx (klass
);
2629 method_count
= mono_class_get_method_count (klass
);
2631 tdef
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2632 guint32 parent
, field_idx
, col
, mtoken
, idx
;
2633 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2634 parent
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_PARENT
);
2635 if ((parent
& MONO_CUSTOM_ATTR_MASK
) != MONO_CUSTOM_ATTR_FIELDDEF
)
2638 col
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_TYPE
);
2639 mtoken
= col
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
2642 if ((col
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
2643 field_idx
= parent
>> MONO_CUSTOM_ATTR_BITS
;
2644 if (idx
>= first_method_idx
&& idx
< first_method_idx
+ method_count
)
2645 g_hash_table_insert (indexes
, GUINT_TO_POINTER (field_idx
), GUINT_TO_POINTER (1));
2649 /* Memberref pointing to a typeref */
2650 tdef
= &image
->tables
[MONO_TABLE_MEMBERREF
];
2652 /* Check whenever the assembly references the WeakAttribute type */
2653 gboolean found
= FALSE
;
2654 tdef
= &image
->tables
[MONO_TABLE_TYPEREF
];
2655 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2656 guint32 string_offset
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEREF_NAME
);
2657 const char *name
= mono_metadata_string_heap (image
, string_offset
);
2658 if (!strcmp (name
, "WeakAttribute")) {
2667 /* Find the memberref pointing to a typeref */
2668 tdef
= &image
->tables
[MONO_TABLE_MEMBERREF
];
2669 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2670 guint32 cols
[MONO_MEMBERREF_SIZE
];
2673 mono_metadata_decode_row (tdef
, i
, cols
, MONO_MEMBERREF_SIZE
);
2674 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
2675 mono_metadata_decode_blob_size (sig
, &sig
);
2677 guint32 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
2678 guint32 class_index
= cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
2679 const char *fname
= mono_metadata_string_heap (image
, cols
[MONO_MEMBERREF_NAME
]);
2681 if (!strcmp (fname
, ".ctor") && class_index
== MONO_MEMBERREF_PARENT_TYPEREF
) {
2682 MonoTableInfo
*typeref_table
= &image
->tables
[MONO_TABLE_TYPEREF
];
2683 guint32 cols
[MONO_TYPEREF_SIZE
];
2685 mono_metadata_decode_row (typeref_table
, nindex
- 1, cols
, MONO_TYPEREF_SIZE
);
2687 const char *name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2688 const char *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2690 if (!strcmp (nspace
, "System") && !strcmp (name
, "WeakAttribute")) {
2691 MonoClass
*klass
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| nindex
, error
);
2692 if (!is_ok (error
)) {
2693 mono_error_cleanup (error
);
2696 g_assert (!strcmp (m_class_get_name (klass
), "WeakAttribute"));
2697 /* Allow a testing dll as well since some profiles don't have WeakAttribute */
2698 if (klass
&& (m_class_get_image (klass
) == mono_get_corlib () || strstr (m_class_get_image (klass
)->name
, "Mono.Runtime.Testing"))) {
2699 /* Sanity check that it only has 1 ctor */
2700 gpointer iter
= NULL
;
2703 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2704 if (!strcmp (method
->name
, ".ctor"))
2708 memberref_index
= i
;
2714 if (memberref_index
== -1)
2717 tdef
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2718 guint32 parent
, field_idx
, col
, mtoken
, idx
;
2719 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2720 parent
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_PARENT
);
2721 if ((parent
& MONO_CUSTOM_ATTR_MASK
) != MONO_CUSTOM_ATTR_FIELDDEF
)
2724 col
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_TYPE
);
2725 mtoken
= col
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
2728 field_idx
= parent
>> MONO_CUSTOM_ATTR_BITS
;
2729 if ((col
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_MEMBERREF
) {
2730 if (idx
== memberref_index
)
2731 g_hash_table_insert (indexes
, GUINT_TO_POINTER (field_idx
), GUINT_TO_POINTER (1));
2738 * mono_assembly_init_weak_fields:
2740 * Initialize the image->weak_field_indexes hash.
2743 mono_assembly_init_weak_fields (MonoImage
*image
)
2745 if (image
->weak_fields_inited
)
2748 GHashTable
*indexes
= NULL
;
2750 if (mono_get_runtime_callbacks ()->get_weak_field_indexes
)
2751 indexes
= mono_get_runtime_callbacks ()->get_weak_field_indexes (image
);
2753 indexes
= g_hash_table_new (NULL
, NULL
);
2756 * To avoid lookups for every field, we scan the customattr table for entries whose
2757 * parent is a field and whose type is WeakAttribute.
2759 init_weak_fields_inner (image
, indexes
);
2762 mono_image_lock (image
);
2763 if (!image
->weak_fields_inited
) {
2764 image
->weak_field_indexes
= indexes
;
2765 mono_memory_barrier ();
2766 image
->weak_fields_inited
= TRUE
;
2768 g_hash_table_destroy (indexes
);
2770 mono_image_unlock (image
);
2774 * mono_assembly_is_weak_field:
2776 * Return whenever the FIELD table entry with the 1-based index FIELD_IDX has
2777 * a [Weak] attribute.
2780 mono_assembly_is_weak_field (MonoImage
*image
, guint32 field_idx
)
2785 mono_assembly_init_weak_fields (image
);
2787 /* The hash is not mutated, no need to lock */
2788 return g_hash_table_lookup (image
->weak_field_indexes
, GINT_TO_POINTER (field_idx
)) != NULL
;