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/gc-internals.h"
18 #include "mono/metadata/mono-endian.h"
19 #include "mono/metadata/object-internals.h"
20 #include "mono/metadata/custom-attrs-internals.h"
21 #include "mono/metadata/sre-internals.h"
22 #include "mono/metadata/reflection-internals.h"
23 #include "mono/metadata/tabledefs.h"
24 #include "mono/metadata/tokentype.h"
25 #include "mono/metadata/verify-internals.h"
26 #include "mono/utils/checked-build.h"
29 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
30 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
32 #if SIZEOF_VOID_P == 4
33 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
35 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
38 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
39 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
41 static gboolean type_is_reference (MonoType *type);
43 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, "System.Reflection", "CustomAttributeTypedArgument");
44 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, "System.Reflection", "CustomAttributeNamedArgument");
46 static MonoCustomAttrInfo*
47 mono_custom_attrs_from_builders_handle (MonoImage *alloc_img, MonoImage *image, MonoArrayHandle cattrs);
50 bcheck_blob (const char *ptr, int bump, const char *endp, MonoError *error);
53 decode_blob_value_checked (const char *ptr, const char *endp, guint32 *size_out, const char **retp, MonoError *error);
56 * LOCKING: Acquires the loader lock.
58 static MonoCustomAttrInfo*
59 lookup_custom_attr (MonoImage *image, gpointer member)
61 MONO_REQ_GC_NEUTRAL_MODE;
63 MonoCustomAttrInfo* res;
65 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
70 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
76 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
78 MONO_REQ_GC_UNSAFE_MODE;
80 /* FIXME: Need to do more checks */
81 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
82 int visibility = mono_class_get_flags (cattr->ctor->method->klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
84 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
92 type_is_reference (MonoType *type)
95 case MONO_TYPE_BOOLEAN:
109 case MONO_TYPE_VALUETYPE:
117 free_param_data (MonoMethodSignature *sig, void **params) {
119 for (i = 0; i < sig->param_count; ++i) {
120 if (!type_is_reference (sig->params [i]))
126 * Find the field index in the metadata FieldDef table.
129 find_field_index (MonoClass *klass, MonoClassField *field) {
132 int fcount = mono_class_get_field_count (klass);
133 for (i = 0; i < fcount; ++i) {
134 if (field == &klass->fields [i])
135 return mono_class_get_first_field_idx (klass) + 1 + i;
141 * Find the property index in the metadata Property table.
144 find_property_index (MonoClass *klass, MonoProperty *property)
147 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
149 for (i = 0; i < info->count; ++i) {
150 if (property == &info->properties [i])
151 return info->first + 1 + i;
157 * Find the event index in the metadata Event table.
160 find_event_index (MonoClass *klass, MonoEvent *event)
163 MonoClassEventInfo *info = mono_class_get_event_info (klass);
165 for (i = 0; i < info->count; ++i) {
166 if (event == &info->events [i])
167 return info->first + 1 + i;
173 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
174 * The @is_enum flag only affects the error message that's displayed on failure.
177 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
179 MonoError inner_error;
180 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
182 mono_error_set_type_load_name (error, g_strdup(n), NULL,
183 "Could not load %s %s while decoding custom attribute: %s",
184 is_enum ? "enum type": "type",
186 mono_error_get_message (&inner_error));
187 mono_error_cleanup (&inner_error);
194 load_cattr_enum_type (MonoImage *image, const char *p, const char *boundp, const char **end, MonoError *error)
201 if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
204 if (boundp && slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
206 n = (char *)g_memdup (p, slen + 1);
208 t = cattr_type_from_name (n, image, TRUE, error);
210 return_val_if_nok (error, NULL);
213 return mono_class_from_mono_type (t);
217 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char *boundp, const char **end, MonoError *error)
221 MonoClass *tklass = t->data.klass;
230 case MONO_TYPE_BOOLEAN: {
231 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
232 if (!bcheck_blob (p, 0, boundp, error))
241 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
242 if (!bcheck_blob (p, 1, boundp, error))
248 #if SIZEOF_VOID_P == 4
255 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
256 if (!bcheck_blob (p, 3, boundp, error))
262 #if SIZEOF_VOID_P == 8
263 case MONO_TYPE_U: /* error out instead? this should probably not happen */
268 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
269 if (!bcheck_blob (p, 7, boundp, error))
276 double *val = (double *)g_malloc (sizeof (double));
277 if (!bcheck_blob (p, 7, boundp, error))
283 case MONO_TYPE_VALUETYPE:
284 if (t->data.klass->enumtype) {
285 type = mono_class_enum_basetype (t->data.klass)->type;
288 MonoClass *k = t->data.klass;
290 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
291 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
292 if (!bcheck_blob (p, 7, boundp, error))
299 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
302 case MONO_TYPE_STRING:
303 if (!bcheck_blob (p, 0, boundp, error))
305 if (*p == (char)0xFF) {
309 if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
311 if (slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
314 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
315 case MONO_TYPE_CLASS: {
316 MonoReflectionType *rt;
319 if (!bcheck_blob (p, 0, boundp, error))
321 if (*p == (char)0xFF) {
326 if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
328 if (slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
330 n = (char *)g_memdup (p, slen + 1);
332 t = cattr_type_from_name (n, image, FALSE, error);
334 return_val_if_nok (error, NULL);
337 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
338 if (!mono_error_ok (error))
343 case MONO_TYPE_OBJECT: {
344 if (!bcheck_blob (p, 0, boundp, error))
348 MonoClass *subc = NULL;
353 } else if (subt == 0x0E) {
354 type = MONO_TYPE_STRING;
356 } else if (subt == 0x1D) {
357 MonoType simple_type = {{0}};
358 if (!bcheck_blob (p, 0, boundp, error))
363 type = MONO_TYPE_SZARRAY;
365 tklass = mono_defaults.systemtype_class;
366 } else if (etype == 0x55) {
367 tklass = load_cattr_enum_type (image, p, boundp, &p, error);
372 /* See Partition II, Appendix B3 */
373 etype = MONO_TYPE_OBJECT;
374 simple_type.type = (MonoTypeEnum)etype;
375 tklass = mono_class_from_mono_type (&simple_type);
378 } else if (subt == 0x55) {
381 if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
383 if (slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
385 n = (char *)g_memdup (p, slen + 1);
387 t = cattr_type_from_name (n, image, FALSE, error);
389 return_val_if_nok (error, NULL);
391 subc = mono_class_from_mono_type (t);
392 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
393 MonoType simple_type = {{0}};
394 simple_type.type = (MonoTypeEnum)subt;
395 subc = mono_class_from_mono_type (&simple_type);
397 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
399 val = load_cattr_value (image, &subc->byval_arg, p, boundp, end, error);
402 obj = mono_object_new_checked (mono_domain_get (), subc, error);
403 g_assert (!subc->has_references);
405 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
411 case MONO_TYPE_SZARRAY: {
413 guint32 i, alen, basetype;
414 if (!bcheck_blob (p, 3, boundp, error))
418 if (alen == 0xffffffff) {
422 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
423 return_val_if_nok (error, NULL);
424 basetype = tklass->byval_arg.type;
425 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
426 basetype = mono_class_enum_basetype (tklass)->type;
431 case MONO_TYPE_BOOLEAN:
432 for (i = 0; i < alen; i++) {
433 if (!bcheck_blob (p, 0, boundp, error))
435 MonoBoolean val = *p++;
436 mono_array_set (arr, MonoBoolean, i, val);
442 for (i = 0; i < alen; i++) {
443 if (!bcheck_blob (p, 1, boundp, error))
445 guint16 val = read16 (p);
446 mono_array_set (arr, guint16, i, val);
453 for (i = 0; i < alen; i++) {
454 if (!bcheck_blob (p, 3, boundp, error))
456 guint32 val = read32 (p);
457 mono_array_set (arr, guint32, i, val);
462 for (i = 0; i < alen; i++) {
463 if (!bcheck_blob (p, 7, boundp, error))
467 mono_array_set (arr, double, i, val);
473 for (i = 0; i < alen; i++) {
474 if (!bcheck_blob (p, 7, boundp, error))
476 guint64 val = read64 (p);
477 mono_array_set (arr, guint64, i, val);
481 case MONO_TYPE_CLASS:
482 case MONO_TYPE_OBJECT:
483 case MONO_TYPE_STRING:
484 case MONO_TYPE_SZARRAY:
485 for (i = 0; i < alen; i++) {
486 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, boundp, &p, error);
489 mono_array_setref (arr, i, item);
493 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
499 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
505 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char *boundp, const char** end, MonoError *error)
509 gboolean is_ref = type_is_reference (t);
511 void *val = load_cattr_value (image, t, p, boundp, end, error);
512 if (!is_ok (error)) {
519 return (MonoObject*)val;
521 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
527 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
529 static MonoMethod *ctor;
531 void *params [2], *unboxed;
536 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
538 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
539 return_val_if_nok (error, NULL);
542 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
543 return_val_if_nok (error, NULL);
544 unboxed = mono_object_unbox (retval);
546 mono_runtime_invoke_checked (ctor, unboxed, params, error);
547 return_val_if_nok (error, NULL);
553 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
555 static MonoMethod *ctor;
557 void *unboxed, *params [2];
562 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
565 params [1] = typedarg;
566 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
567 return_val_if_nok (error, NULL);
569 unboxed = mono_object_unbox (retval);
571 mono_runtime_invoke_checked (ctor, unboxed, params, error);
572 return_val_if_nok (error, NULL);
578 static MonoCustomAttrInfo*
579 mono_custom_attrs_from_builders_handle (MonoImage *alloc_img, MonoImage *image, MonoArrayHandle cattrs)
581 return mono_custom_attrs_from_builders (alloc_img, image, MONO_HANDLE_RAW (cattrs)); /* FIXME use coop handles for mono_custom_attrs_from_builders */
585 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
587 MONO_REQ_GC_UNSAFE_MODE;
589 int i, index, count, not_visible;
590 MonoCustomAttrInfo *ainfo;
591 MonoReflectionCustomAttr *cattr;
595 /* FIXME: check in assembly the Run flag is set */
597 count = mono_array_length (cattrs);
599 /* Skip nonpublic attributes since MS.NET seems to do the same */
600 /* FIXME: This needs to be done more globally */
602 for (i = 0; i < count; ++i) {
603 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
604 if (!custom_attr_visible (image, cattr))
608 int num_attrs = count - not_visible;
609 ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
611 ainfo->image = image;
612 ainfo->num_attrs = num_attrs;
613 ainfo->cached = alloc_img != NULL;
615 for (i = 0; i < count; ++i) {
616 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
617 if (custom_attr_visible (image, cattr)) {
618 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
619 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
620 ainfo->attrs [index].ctor = cattr->ctor->method;
621 g_assert (cattr->ctor->method);
622 ainfo->attrs [index].data = saved;
623 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
627 g_assert (index == num_attrs && count == num_attrs + not_visible);
633 set_custom_attr_fmt_error (MonoError *error)
636 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
641 * \param ptr a pointer into a blob
642 * \param bump how far we plan on reading past \p ptr.
643 * \param endp upper bound for \p ptr - one past the last valid value for \p ptr.
644 * \param error set on error
646 * Check that ptr+bump is below endp. Returns TRUE on success, or FALSE on
647 * failure and sets \p error.
650 bcheck_blob (const char *ptr, int bump, const char *endp, MonoError *error)
653 if (ADDP_IS_GREATER_OR_OVF (ptr, bump, endp - 1)) {
654 set_custom_attr_fmt_error (error);
661 * decode_blob_size_checked:
662 * \param ptr a pointer into a blob
663 * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
664 * \param size_out on success set to the decoded size
665 * \param retp on success set to the next byte after the encoded size
666 * \param error set on error
668 * Decode an encoded size value which takes 1, 2, or 4 bytes and set \p
669 * size_out to the decoded size and \p retp to the next byte after the encoded
670 * size. Returns TRUE on success, or FALASE on failure and sets \p error.
673 decode_blob_size_checked (const char *ptr, const char *endp, guint32 *size_out, const char **retp, MonoError *error)
676 if (endp && !bcheck_blob (ptr, 0, endp, error))
678 if ((*ptr & 0x80) != 0) {
679 if ((*ptr & 0x40) == 0 && !bcheck_blob (ptr, 1, endp, error))
681 else if (!bcheck_blob (ptr, 3, endp, error))
684 *size_out = mono_metadata_decode_blob_size (ptr, retp);
686 return is_ok (error);
690 * decode_blob_value_checked:
691 * \param ptr a pointer into a blob
692 * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
693 * \param value_out on success set to the decoded value
694 * \param retp on success set to the next byte after the encoded size
695 * \param error set on error
697 * Decode an encoded uint32 value which takes 1, 2, or 4 bytes and set \p
698 * value_out to the decoded value and \p retp to the next byte after the
699 * encoded value. Returns TRUE on success, or FALASE on failure and sets \p
703 decode_blob_value_checked (const char *ptr, const char *endp, guint32 *value_out, const char **retp, MonoError *error)
705 /* This similar to decode_blob_size_checked, above but delegates to
706 * mono_metadata_decode_value which is semantically different. */
708 if (!bcheck_blob (ptr, 0, endp, error))
710 if ((*ptr & 0x80) != 0) {
711 if ((*ptr & 0x40) == 0 && !bcheck_blob (ptr, 1, endp, error))
713 else if (!bcheck_blob (ptr, 3, endp, error))
716 *value_out = mono_metadata_decode_value (ptr, retp);
718 return is_ok (error);
722 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
724 const char *p = (const char*)data;
725 const char *data_end = (const char*)data + len;
727 guint32 i, j, num_named;
729 void *params_buf [32];
730 void **params = NULL;
731 MonoMethodSignature *sig;
735 mono_class_init (method->klass);
737 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
738 set_custom_attr_fmt_error (error);
743 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
744 if (!mono_error_ok (error)) return NULL;
746 mono_runtime_invoke_checked (method, attr, NULL, error);
747 if (!mono_error_ok (error))
753 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
756 /*g_print ("got attr %s\n", method->klass->name);*/
758 sig = mono_method_signature (method);
759 if (sig->param_count < 32) {
761 memset (params, 0, sizeof (void*) * sig->param_count);
763 /* Allocate using GC so it gets GC tracking */
764 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
769 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
770 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, data_end, &p, error);
776 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
777 if (!mono_error_ok (error)) goto fail;
779 MonoObject *exc = NULL;
780 mono_runtime_try_invoke (method, attr, params, &exc, error);
781 if (!mono_error_ok (error))
784 mono_error_set_exception_instance (error, (MonoException*)exc);
788 if (named + 1 < data_end) {
789 num_named = read16 (named);
792 /* CoreCLR allows p == data + len */
793 if (named == data_end)
796 set_custom_attr_fmt_error (error);
800 for (j = 0; j < num_named; j++) {
802 char *name, named_type, data_type;
803 if (!bcheck_blob (named, 1, data_end, error))
805 named_type = *named++;
806 data_type = *named++; /* type of data */
807 if (data_type == MONO_TYPE_SZARRAY) {
808 if (!bcheck_blob (named, 0, data_end, error))
810 data_type = *named++;
812 if (data_type == MONO_TYPE_ENUM) {
815 if (!decode_blob_size_checked (named, data_end, &type_len, &named, error))
817 if (type_len > 0 && !bcheck_blob (named, type_len - 1, data_end, error))
819 type_name = (char *)g_malloc (type_len + 1);
820 memcpy (type_name, named, type_len);
821 type_name [type_len] = 0;
823 /* FIXME: lookup the type and check type consistency */
826 if (!decode_blob_size_checked (named, data_end, &name_len, &named, error))
828 if (name_len > 0 && !bcheck_blob (named, name_len - 1, data_end, error))
830 name = (char *)g_malloc (name_len + 1);
831 memcpy (name, named, name_len);
834 if (named_type == 0x53) {
835 MonoClassField *field;
838 /* how this fail is a blackbox */
839 field = mono_class_get_field_from_name (mono_object_class (attr), name);
841 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
846 val = load_cattr_value (image, field->type, named, data_end, &named, error);
847 if (!is_ok (error)) {
849 if (!type_is_reference (field->type))
854 mono_field_set_value (attr, field, val);
855 if (!type_is_reference (field->type))
857 } else if (named_type == 0x54) {
862 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
865 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
871 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
876 /* can we have more that 1 arg in a custom attr named property? */
877 prop_type = prop->get? mono_method_signature (prop->get)->ret :
878 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
880 pparams [0] = load_cattr_value (image, prop_type, named, data_end, &named, error);
881 if (!is_ok (error)) {
883 if (!type_is_reference (prop_type))
884 g_free (pparams [0]);
889 mono_property_set_value_checked (prop, attr, pparams, error);
890 if (!type_is_reference (prop_type))
891 g_free (pparams [0]);
892 if (!is_ok (error)) {
900 free_param_data (method->signature, params);
901 if (params != params_buf)
902 mono_gc_free_fixed (params);
907 free_param_data (method->signature, params);
908 if (params != params_buf)
909 mono_gc_free_fixed (params);
914 * mono_reflection_create_custom_attr_data_args:
916 * Create an array of typed and named arguments from the cattr blob given by DATA.
917 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
918 * NAMED_ARG_INFO will contain information about the named arguments.
921 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)
923 MonoArray *typedargs, *namedargs;
924 MonoClass *attrklass;
926 const char *p = (const char*)data;
927 const char *data_end = p + len;
929 guint32 i, j, num_named;
930 CattrNamedArg *arginfo = NULL;
934 *named_arg_info = NULL;
938 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
939 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
943 mono_class_init (method->klass);
945 domain = mono_domain_get ();
947 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
952 /* Parse each argument corresponding to the signature's parameters from
953 * the blob and store in typedargs.
955 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
956 return_if_nok (error);
958 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
961 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, data_end, &p, error);
962 return_if_nok (error);
963 mono_array_setref (typedargs, i, obj);
968 /* Parse mandatory count of named arguments (could be zero) */
969 if (!bcheck_blob (named, 1, data_end, error))
971 num_named = read16 (named);
972 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
973 return_if_nok (error);
975 attrklass = method->klass;
977 arginfo = g_new0 (CattrNamedArg, num_named);
978 *named_arg_info = arginfo;
980 /* Parse each named arg, and add to arginfo. Each named argument could
981 * be a field name or a property name followed by a value. */
982 for (j = 0; j < num_named; j++) {
984 char *name, named_type, data_type;
985 if (!bcheck_blob (named, 1, data_end, error))
987 named_type = *named++; /* field or property? */
988 data_type = *named++; /* type of data */
989 if (data_type == MONO_TYPE_SZARRAY) {
990 if (!bcheck_blob (named, 0, data_end, error))
992 data_type = *named++;
994 if (data_type == MONO_TYPE_ENUM) {
997 if (!decode_blob_size_checked (named, data_end, &type_len, &named, error))
999 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
1002 type_name = (char *)g_malloc (type_len + 1);
1003 memcpy (type_name, named, type_len);
1004 type_name [type_len] = 0;
1006 /* FIXME: lookup the type and check type consistency */
1009 /* named argument name: length, then name */
1010 if (!decode_blob_size_checked(named, data_end, &name_len, &named, error))
1012 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
1014 name = (char *)g_malloc (name_len + 1);
1015 memcpy (name, named, name_len);
1016 name [name_len] = 0;
1018 if (named_type == 0x53) {
1019 /* Named arg is a field. */
1021 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
1028 arginfo [j].type = field->type;
1029 arginfo [j].field = field;
1031 obj = load_cattr_value_boxed (domain, image, field->type, named, data_end, &named, error);
1032 if (!is_ok (error)) {
1036 mono_array_setref (namedargs, j, obj);
1038 } else if (named_type == 0x54) {
1039 /* Named arg is a property */
1041 MonoType *prop_type;
1042 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
1044 if (!prop || !prop->set) {
1049 prop_type = prop->get? mono_method_signature (prop->get)->ret :
1050 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
1052 arginfo [j].type = prop_type;
1053 arginfo [j].prop = prop;
1055 obj = load_cattr_value_boxed (domain, image, prop_type, named, data_end, &named, error);
1056 if (!is_ok (error)) {
1060 mono_array_setref (namedargs, j, obj);
1065 *typed_args = typedargs;
1066 *named_args = namedargs;
1069 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
1071 *named_arg_info = NULL;
1075 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
1078 MonoArray *typedargs, *namedargs;
1081 CattrNamedArg *arginfo = NULL;
1092 image = assembly->assembly->image;
1093 method = ref_method->method;
1094 domain = mono_object_domain (ref_method);
1096 if (!mono_class_init (method->klass)) {
1097 mono_error_set_for_class_failure (error, method->klass);
1101 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
1105 if (!typedargs || !namedargs)
1108 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
1109 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
1110 MonoObject *typedarg;
1112 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
1115 mono_array_setref (typedargs, i, typedarg);
1118 for (i = 0; i < mono_array_length (namedargs); ++i) {
1119 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
1120 MonoObject *typedarg, *namedarg, *minfo;
1122 if (arginfo [i].prop) {
1123 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
1127 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
1132 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
1135 namedarg = create_cattr_named_arg (minfo, typedarg, error);
1139 mono_array_setref (namedargs, i, namedarg);
1142 *ctor_args = typedargs;
1143 *named_args = namedargs;
1147 return mono_error_ok (error);
1151 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
1154 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
1155 mono_error_set_pending_exception (&error);
1158 static MonoObjectHandle
1159 create_custom_attr_data_handle (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
1161 static MonoMethod *ctor;
1168 g_assert (image->assembly);
1171 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
1173 domain = mono_domain_get ();
1175 MonoObjectHandle attr = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error));
1179 MonoReflectionMethod *ctor_obj = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
1182 MonoReflectionAssemblyHandle assm = mono_assembly_get_object_handle (domain, image->assembly, error);
1185 params [0] = ctor_obj;
1186 params [1] = MONO_HANDLE_RAW (assm);
1187 params [2] = (gpointer)&cattr->data;
1188 params [3] = &cattr->data_size;
1190 mono_runtime_invoke_checked (ctor, MONO_HANDLE_RAW (attr), params, error);
1193 return MONO_HANDLE_NEW (MonoObject, NULL);
1197 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
1199 HANDLE_FUNCTION_ENTER ();
1200 MonoObjectHandle obj = create_custom_attr_data_handle (image, cattr, error);
1201 HANDLE_FUNCTION_RETURN_OBJ (obj);
1205 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
1213 for (i = 0; i < cinfo->num_attrs; ++i) {
1214 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
1215 if (!centry->ctor) {
1216 /* The cattr type is not finished yet */
1217 /* We should include the type name but cinfo doesn't contain it */
1218 mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1225 for (i = 0; i < cinfo->num_attrs; ++i) {
1226 MonoMethod *ctor = cinfo->attrs[i].ctor;
1228 if (mono_class_is_assignable_from (attr_klass, ctor->klass))
1232 n = cinfo->num_attrs;
1235 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
1236 return_val_if_nok (error, NULL);
1238 for (i = 0; i < cinfo->num_attrs; ++i) {
1239 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
1240 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
1241 attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
1242 if (!mono_error_ok (error))
1244 mono_array_setref (result, n, attr);
1252 * mono_custom_attrs_construct:
1255 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
1258 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
1259 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1265 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
1272 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
1273 return_val_if_nok (error, NULL);
1274 for (i = 0; i < cinfo->num_attrs; ++i) {
1275 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
1276 return_val_if_nok (error, NULL);
1277 mono_array_setref (result, i, attr);
1283 * mono_custom_attrs_from_index:
1285 * Returns: NULL if no attributes are found or if a loading error occurs.
1288 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
1291 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, FALSE, &error);
1292 mono_error_cleanup (&error);
1296 * mono_custom_attrs_from_index_checked:
1297 * \returns NULL if no attributes are found. On error returns NULL and sets \p error.
1300 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error)
1302 guint32 mtoken, i, len;
1303 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1305 MonoCustomAttrInfo *ainfo;
1306 GList *tmp, *list = NULL;
1308 MonoCustomAttrEntry* attr;
1312 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1314 i = mono_metadata_custom_attrs_from_index (image, idx);
1318 while (i < ca->rows) {
1319 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1321 list = g_list_prepend (list, GUINT_TO_POINTER (i));
1324 len = g_list_length (list);
1327 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
1328 ainfo->num_attrs = len;
1329 ainfo->image = image;
1330 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
1331 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
1332 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1333 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1334 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1335 mtoken |= MONO_TOKEN_METHOD_DEF;
1337 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1338 mtoken |= MONO_TOKEN_MEMBER_REF;
1341 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1344 attr = &ainfo->attrs [i - 1];
1345 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
1347 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error));
1348 if (ignore_missing) {
1349 mono_error_cleanup (error);
1358 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
1359 /*FIXME raising an exception here doesn't make any sense*/
1360 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
1365 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
1366 attr->data_size = mono_metadata_decode_value (data, &data);
1367 attr->data = (guchar*)data;
1375 * mono_custom_attrs_from_method:
1378 mono_custom_attrs_from_method (MonoMethod *method)
1381 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
1382 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
1387 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
1394 * An instantiated method has the same cattrs as the generic method definition.
1396 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1397 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1399 if (method->is_inflated)
1400 method = ((MonoMethodInflated *) method)->declaring;
1402 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
1403 return lookup_custom_attr (method->klass->image, method);
1406 /* Synthetic methods */
1409 idx = mono_method_get_index (method);
1410 idx <<= MONO_CUSTOM_ATTR_BITS;
1411 idx |= MONO_CUSTOM_ATTR_METHODDEF;
1412 return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error);
1416 * mono_custom_attrs_from_class:
1419 mono_custom_attrs_from_class (MonoClass *klass)
1422 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
1423 mono_error_cleanup (&error);
1428 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
1434 if (mono_class_is_ginst (klass))
1435 klass = mono_class_get_generic_class (klass)->container_class;
1437 if (image_is_dynamic (klass->image))
1438 return lookup_custom_attr (klass->image, klass);
1440 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
1441 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
1442 idx <<= MONO_CUSTOM_ATTR_BITS;
1443 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
1445 idx = mono_metadata_token_index (klass->type_token);
1446 idx <<= MONO_CUSTOM_ATTR_BITS;
1447 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1449 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1453 * mono_custom_attrs_from_assembly:
1456 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
1459 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, FALSE, &error);
1460 mono_error_cleanup (&error);
1465 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error)
1471 if (image_is_dynamic (assembly->image))
1472 return lookup_custom_attr (assembly->image, assembly);
1473 idx = 1; /* there is only one assembly */
1474 idx <<= MONO_CUSTOM_ATTR_BITS;
1475 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1476 return mono_custom_attrs_from_index_checked (assembly->image, idx, ignore_missing, error);
1479 static MonoCustomAttrInfo*
1480 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
1486 if (image_is_dynamic (image))
1487 return lookup_custom_attr (image, image);
1488 idx = 1; /* there is only one module */
1489 idx <<= MONO_CUSTOM_ATTR_BITS;
1490 idx |= MONO_CUSTOM_ATTR_MODULE;
1491 return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1495 * mono_custom_attrs_from_property:
1498 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
1501 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
1502 mono_error_cleanup (&error);
1507 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
1513 if (image_is_dynamic (klass->image)) {
1514 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
1515 return lookup_custom_attr (klass->image, property);
1517 idx = find_property_index (klass, property);
1518 idx <<= MONO_CUSTOM_ATTR_BITS;
1519 idx |= MONO_CUSTOM_ATTR_PROPERTY;
1520 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1524 * mono_custom_attrs_from_event:
1527 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
1530 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
1531 mono_error_cleanup (&error);
1536 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
1542 if (image_is_dynamic (klass->image)) {
1543 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
1544 return lookup_custom_attr (klass->image, event);
1546 idx = find_event_index (klass, event);
1547 idx <<= MONO_CUSTOM_ATTR_BITS;
1548 idx |= MONO_CUSTOM_ATTR_EVENT;
1549 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1553 * mono_custom_attrs_from_field:
1556 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
1559 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
1560 mono_error_cleanup (&error);
1565 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
1570 if (image_is_dynamic (klass->image)) {
1571 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
1572 return lookup_custom_attr (klass->image, field);
1574 idx = find_field_index (klass, field);
1575 idx <<= MONO_CUSTOM_ATTR_BITS;
1576 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1577 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1581 * mono_custom_attrs_from_param:
1582 * \param method handle to the method that we want to retrieve custom parameter information from
1583 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1585 * The result must be released with mono_custom_attrs_free().
1587 * \returns the custom attribute object for the specified parameter, or NULL if there are none.
1590 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
1593 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
1594 mono_error_cleanup (&error);
1599 * mono_custom_attrs_from_param_checked:
1600 * \param method handle to the method that we want to retrieve custom parameter information from
1601 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1602 * \param error set on error
1604 * The result must be released with mono_custom_attrs_free().
1606 * \returns the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets \p error.
1609 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
1612 guint32 i, idx, method_index;
1613 guint32 param_list, param_last, param_pos, found;
1615 MonoReflectionMethodAux *aux;
1620 * An instantiated method has the same cattrs as the generic method definition.
1622 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1623 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1625 if (method->is_inflated)
1626 method = ((MonoMethodInflated *) method)->declaring;
1628 if (image_is_dynamic (method->klass->image)) {
1629 MonoCustomAttrInfo *res, *ainfo;
1632 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1633 if (!aux || !aux->param_cattr)
1636 /* Need to copy since it will be freed later */
1637 ainfo = aux->param_cattr [param];
1640 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
1641 res = (MonoCustomAttrInfo *)g_malloc0 (size);
1642 memcpy (res, ainfo, size);
1646 image = method->klass->image;
1647 method_index = mono_method_get_index (method);
1650 ca = &image->tables [MONO_TABLE_METHOD];
1652 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
1653 if (method_index == ca->rows) {
1654 ca = &image->tables [MONO_TABLE_PARAM];
1655 param_last = ca->rows + 1;
1657 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
1658 ca = &image->tables [MONO_TABLE_PARAM];
1661 for (i = param_list; i < param_last; ++i) {
1662 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
1663 if (param_pos == param) {
1671 idx <<= MONO_CUSTOM_ATTR_BITS;
1672 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1673 return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1677 * mono_custom_attrs_has_attr:
1680 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1683 for (i = 0; i < ainfo->num_attrs; ++i) {
1684 MonoCustomAttrEntry *centry = &ainfo->attrs[i];
1685 if (centry->ctor == NULL)
1687 MonoClass *klass = centry->ctor->klass;
1688 if (klass == attr_klass || mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
1695 * mono_custom_attrs_get_attr:
1698 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1701 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
1702 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1707 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
1710 MonoCustomAttrEntry *centry = NULL;
1712 g_assert (attr_klass != NULL);
1716 for (i = 0; i < ainfo->num_attrs; ++i) {
1717 centry = &ainfo->attrs[i];
1718 if (centry->ctor == NULL)
1720 MonoClass *klass = centry->ctor->klass;
1721 if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass))
1727 return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
1731 * mono_reflection_get_custom_attrs_info:
1732 * \param obj a reflection object handle
1734 * \returns the custom attribute info for attributes defined for the
1735 * reflection handle \p obj. The objects.
1737 * FIXME this function leaks like a sieve for SRE objects.
1740 mono_reflection_get_custom_attrs_info (MonoObject *obj_raw)
1742 HANDLE_FUNCTION_ENTER ();
1744 MONO_HANDLE_DCL (MonoObject, obj);
1745 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
1746 mono_error_assert_ok (&error);
1747 HANDLE_FUNCTION_RETURN_VAL (result);
1751 * mono_reflection_get_custom_attrs_info_checked:
1752 * \param obj a reflection object handle
1753 * \param error set on error
1755 * \returns the custom attribute info for attributes defined for the
1756 * reflection handle \p obj. The objects. On failure returns NULL and sets \p error.
1758 * FIXME this function leaks like a sieve for SRE objects.
1761 mono_reflection_get_custom_attrs_info_checked (MonoObjectHandle obj, MonoError *error)
1763 HANDLE_FUNCTION_ENTER ();
1765 MonoCustomAttrInfo *cinfo = NULL;
1769 klass = mono_handle_class (obj);
1770 if (klass == mono_defaults.runtimetype_class) {
1771 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST(MonoReflectionType, obj), error);
1774 klass = mono_class_from_mono_type (type);
1775 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1776 cinfo = mono_custom_attrs_from_class_checked (klass, error);
1779 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
1780 MonoReflectionAssemblyHandle rassembly = MONO_HANDLE_CAST (MonoReflectionAssembly, obj);
1781 cinfo = mono_custom_attrs_from_assembly_checked (MONO_HANDLE_GETVAL (rassembly, assembly), FALSE, error);
1784 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
1785 MonoReflectionModuleHandle module = MONO_HANDLE_CAST (MonoReflectionModule, obj);
1786 cinfo = mono_custom_attrs_from_module (MONO_HANDLE_GETVAL (module, image), error);
1789 } else if (strcmp ("MonoProperty", klass->name) == 0) {
1790 MonoReflectionPropertyHandle rprop = MONO_HANDLE_CAST (MonoReflectionProperty, obj);
1791 MonoProperty *property = MONO_HANDLE_GETVAL (rprop, property);
1792 cinfo = mono_custom_attrs_from_property_checked (property->parent, property, error);
1795 } else if (strcmp ("MonoEvent", klass->name) == 0) {
1796 MonoReflectionMonoEventHandle revent = MONO_HANDLE_CAST (MonoReflectionMonoEvent, obj);
1797 MonoEvent *event = MONO_HANDLE_GETVAL (revent, event);
1798 cinfo = mono_custom_attrs_from_event_checked (event->parent, event, error);
1801 } else if (strcmp ("MonoField", klass->name) == 0) {
1802 MonoReflectionFieldHandle rfield = MONO_HANDLE_CAST (MonoReflectionField, obj);
1803 MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field);
1804 cinfo = mono_custom_attrs_from_field_checked (field->parent, field, error);
1807 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
1808 MonoReflectionMethodHandle rmethod = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1809 cinfo = mono_custom_attrs_from_method_checked (MONO_HANDLE_GETVAL (rmethod, method), error);
1812 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
1813 MonoReflectionParameterHandle param = MONO_HANDLE_CAST (MonoReflectionParameter, obj);
1814 MonoObjectHandle member_impl = MONO_HANDLE_NEW_GET (MonoObject, param, MemberImpl);
1815 MonoClass *member_class = mono_handle_class (member_impl);
1816 if (mono_class_is_reflection_method_or_constructor (member_class)) {
1817 MonoReflectionMethodHandle rmethod = MONO_HANDLE_CAST (MonoReflectionMethod, member_impl);
1818 cinfo = mono_custom_attrs_from_param_checked (MONO_HANDLE_GETVAL (rmethod, method), MONO_HANDLE_GETVAL (param, PositionImpl) + 1, error);
1821 } else if (mono_is_sr_mono_property (member_class)) {
1822 MonoReflectionPropertyHandle prop = MONO_HANDLE_CAST (MonoReflectionProperty, member_impl);
1823 MonoProperty *property = MONO_HANDLE_GETVAL (prop, property);
1825 if (!(method = property->get))
1826 method = property->set;
1829 cinfo = mono_custom_attrs_from_param_checked (method, MONO_HANDLE_GETVAL (param, PositionImpl) + 1, error);
1833 #ifndef DISABLE_REFLECTION_EMIT
1834 else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
1835 // FIXME: Is this still needed ?
1836 g_assert_not_reached ();
1837 } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
1838 // FIXME: Is this still needed ?
1839 g_assert_not_reached ();
1843 char *type_name = mono_type_get_full_name (member_class);
1844 mono_error_set_not_supported (error,
1845 "Custom attributes on a ParamInfo with member %s are not supported",
1850 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
1851 MonoReflectionAssemblyBuilderHandle assemblyb = MONO_HANDLE_CAST (MonoReflectionAssemblyBuilder, obj);
1852 MonoReflectionAssemblyHandle assembly = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb);
1853 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs);
1854 MonoImage * image = MONO_HANDLE_GETVAL (assembly, assembly)->image;
1856 cinfo = mono_custom_attrs_from_builders_handle (NULL, image, cattrs);
1857 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
1858 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, obj);
1859 MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, tb, module);
1860 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (module, dynamic_image);
1861 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, tb, cattrs);
1862 cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
1863 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
1864 MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionModuleBuilder, obj);
1865 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
1866 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs);
1867 cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
1868 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
1869 MonoReflectionCtorBuilderHandle cb = MONO_HANDLE_CAST (MonoReflectionCtorBuilder, obj);
1870 MonoMethod *mhandle = MONO_HANDLE_GETVAL (cb, mhandle);
1871 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, cb, cattrs);
1872 cinfo = mono_custom_attrs_from_builders_handle (NULL, mhandle->klass->image, cattrs);
1873 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
1874 MonoReflectionMethodBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionMethodBuilder, obj);
1875 MonoMethod *mhandle = MONO_HANDLE_GETVAL (mb, mhandle);
1876 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs);
1877 cinfo = mono_custom_attrs_from_builders_handle (NULL, mhandle->klass->image, cattrs);
1878 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
1879 MonoReflectionFieldBuilderHandle fb = MONO_HANDLE_CAST (MonoReflectionFieldBuilder, obj);
1880 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, fb, typeb);
1881 MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, tb, module);
1882 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
1883 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, fb, cattrs);
1884 cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
1885 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
1886 MonoReflectionGenericClassHandle gclass = MONO_HANDLE_CAST (MonoReflectionGenericClass, obj);
1887 MonoReflectionTypeHandle generic_type = MONO_HANDLE_NEW_GET (MonoReflectionType, gclass, generic_type);
1888 cinfo = mono_reflection_get_custom_attrs_info_checked (MONO_HANDLE_CAST (MonoObject, generic_type), error);
1891 } else { /* handle other types here... */
1892 g_error ("get custom attrs not yet supported for %s", klass->name);
1896 HANDLE_FUNCTION_RETURN_VAL (cinfo);
1900 * mono_reflection_get_custom_attrs_by_type:
1901 * \param obj a reflection object handle
1902 * \returns an array with all the custom attributes defined of the
1903 * reflection handle \p obj. If \p attr_klass is non-NULL, only custom attributes
1904 * of that type are returned. The objects are fully build. Return NULL if a loading error
1908 mono_reflection_get_custom_attrs_by_type (MonoObject *obj_raw, MonoClass *attr_klass, MonoError *error)
1910 HANDLE_FUNCTION_ENTER ();
1911 MONO_HANDLE_DCL (MonoObject, obj);
1912 MonoArrayHandle result = mono_reflection_get_custom_attrs_by_type_handle (obj, attr_klass, error);
1913 HANDLE_FUNCTION_RETURN_OBJ (result);
1917 mono_reflection_get_custom_attrs_by_type_handle (MonoObjectHandle obj, MonoClass *attr_klass, MonoError *error)
1919 MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
1920 MonoCustomAttrInfo *cinfo;
1924 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1928 MONO_HANDLE_ASSIGN (result, MONO_HANDLE_NEW (MonoArray, mono_custom_attrs_construct_by_type (cinfo, attr_klass, error))); /* FIXME use coop handles for mono_custom_attrs_construct_by_type */
1930 mono_custom_attrs_free (cinfo);
1934 MONO_HANDLE_ASSIGN (result, mono_array_new_handle (mono_domain_get (), mono_defaults.attribute_class, 0, error));
1942 * mono_reflection_get_custom_attrs:
1943 * \param obj a reflection object handle
1944 * \return an array with all the custom attributes defined of the
1945 * reflection handle \p obj. The objects are fully build. Return NULL if a loading error
1949 mono_reflection_get_custom_attrs (MonoObject *obj_raw)
1951 HANDLE_FUNCTION_ENTER ();
1953 MONO_HANDLE_DCL (MonoObject, obj);
1954 MonoArrayHandle result = mono_reflection_get_custom_attrs_by_type_handle (obj, NULL, &error);
1955 mono_error_cleanup (&error);
1956 HANDLE_FUNCTION_RETURN_OBJ (result);
1960 * mono_reflection_get_custom_attrs_data:
1961 * \param obj a reflection obj handle
1962 * \returns an array of \c System.Reflection.CustomAttributeData,
1963 * which include information about attributes reflected on
1964 * types loaded using the Reflection Only methods
1967 mono_reflection_get_custom_attrs_data (MonoObject *obj_raw)
1969 HANDLE_FUNCTION_ENTER ();
1971 MONO_HANDLE_DCL (MonoObject, obj);
1972 MonoArrayHandle result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
1973 mono_error_cleanup (&error);
1974 HANDLE_FUNCTION_RETURN_OBJ (result);
1978 * mono_reflection_get_custom_attrs_data_checked:
1979 * @obj: a reflection obj handle
1980 * @error: set on error
1982 * Returns an array of System.Reflection.CustomAttributeData,
1983 * which include information about attributes reflected on
1984 * types loaded using the Reflection Only methods
1987 mono_reflection_get_custom_attrs_data_checked (MonoObjectHandle obj, MonoError *error)
1989 MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
1990 MonoCustomAttrInfo *cinfo;
1994 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1998 MONO_HANDLE_ASSIGN (result, MONO_HANDLE_NEW (MonoArray, mono_custom_attrs_data_construct (cinfo, error))); /* FIXME use coop handles in mono_custom_attrs_data_construct */
2000 mono_custom_attrs_free (cinfo);
2004 MONO_HANDLE_ASSIGN (result, mono_array_new_handle (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error));
2011 custom_attr_class_name_from_methoddef (MonoImage *image, guint32 method_token, const gchar **nspace, const gchar **class_name)
2013 /* mono_get_method_from_token () */
2014 g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD);
2015 guint32 type_token = mono_metadata_typedef_from_method (image, method_token);
2017 /* Bad method token (could not find corresponding typedef) */
2020 type_token |= MONO_TOKEN_TYPE_DEF;
2022 /* mono_class_create_from_typedef () */
2023 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
2024 guint32 cols [MONO_TYPEDEF_SIZE];
2025 guint tidx = mono_metadata_token_index (type_token);
2027 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
2028 /* "Invalid typedef token %x", type_token */
2032 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
2035 *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2037 *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2044 * custom_attr_class_name_from_method_token:
2045 * @image: The MonoImage
2046 * @method_token: a token for a custom attr constructor in @image
2047 * @assembly_token: out argment set to the assembly ref token of the custom attr
2048 * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
2049 * @class_name: out argument set to the class name of the custom attr.
2051 * Given an @image and a @method_token (which is assumed to be a
2052 * constructor), fills in the out arguments with the assembly ref (if
2053 * a methodref) and the namespace and class name of the custom
2056 * Returns: TRUE on success, FALSE otherwise.
2058 * LOCKING: does not take locks
2061 custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token, guint32 *assembly_token, const gchar **nspace, const gchar **class_name)
2063 /* This only works with method tokens constructed from a
2064 * custom attr token, which can only be methoddef or
2066 g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD
2067 || mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF);
2069 if (mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF) {
2070 /* method_from_memberref () */
2072 guint32 nindex, class_index;
2074 int idx = mono_metadata_token_index (method_token);
2076 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
2077 nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS;
2078 class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK;
2079 if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) {
2080 guint32 type_token = MONO_TOKEN_TYPE_REF | nindex;
2081 /* mono_class_from_typeref_checked () */
2083 guint32 cols [MONO_TYPEREF_SIZE];
2084 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
2086 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
2089 *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
2091 *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
2093 *assembly_token = cols [MONO_TYPEREF_SCOPE];
2096 } else if (class_index == MONO_MEMBERREF_PARENT_METHODDEF) {
2097 guint32 methoddef_token = MONO_TOKEN_METHOD_DEF | nindex;
2099 *assembly_token = 0;
2100 return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name);
2102 /* Attributes can't be generic, so it won't be
2103 * a typespec, and they're always
2104 * constructors, so it won't be a moduleref */
2105 g_assert_not_reached ();
2108 /* must be MONO_TABLE_METHOD */
2110 *assembly_token = 0;
2111 return custom_attr_class_name_from_methoddef (image, method_token, nspace, class_name);
2116 * mono_assembly_metadata_foreach_custom_attr:
2117 * \param assembly the assembly to iterate over
2118 * \param func the function to call for each custom attribute
2119 * \param user_data passed to \p func
2120 * Calls \p func for each custom attribute type on the given assembly until \p func returns TRUE.
2121 * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
2124 mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data)
2128 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2133 * This might be called during assembly loading, so do everything using the low-level
2137 image = assembly->image;
2138 /* Dynamic images would need to go through the AssemblyBuilder's
2139 * CustomAttributeBuilder array. Going through the tables below
2140 * definitely won't work. */
2141 g_assert (!image_is_dynamic (image));
2142 idx = 1; /* there is only one assembly */
2143 idx <<= MONO_CUSTOM_ATTR_BITS;
2144 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
2146 /* Inlined from mono_custom_attrs_from_index_checked () */
2147 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2148 i = mono_metadata_custom_attrs_from_index (image, idx);
2152 gboolean stop_iterating = FALSE;
2153 while (!stop_iterating && i < ca->rows) {
2154 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
2156 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2158 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
2159 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
2160 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
2161 mtoken |= MONO_TOKEN_METHOD_DEF;
2163 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
2164 mtoken |= MONO_TOKEN_MEMBER_REF;
2167 g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2171 const char *nspace = NULL;
2172 const char *name = NULL;
2173 guint32 assembly_token = 0;
2175 if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name))
2178 stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data);