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 * LOCKING: Acquires the loader lock.
52 static MonoCustomAttrInfo*
53 lookup_custom_attr (MonoImage *image, gpointer member)
55 MONO_REQ_GC_NEUTRAL_MODE;
57 MonoCustomAttrInfo* res;
59 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
64 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
70 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
72 MONO_REQ_GC_UNSAFE_MODE;
74 /* FIXME: Need to do more checks */
75 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
76 int visibility = mono_class_get_flags (cattr->ctor->method->klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
78 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
86 type_is_reference (MonoType *type)
89 case MONO_TYPE_BOOLEAN:
103 case MONO_TYPE_VALUETYPE:
111 free_param_data (MonoMethodSignature *sig, void **params) {
113 for (i = 0; i < sig->param_count; ++i) {
114 if (!type_is_reference (sig->params [i]))
120 * Find the field index in the metadata FieldDef table.
123 find_field_index (MonoClass *klass, MonoClassField *field) {
126 int fcount = mono_class_get_field_count (klass);
127 for (i = 0; i < fcount; ++i) {
128 if (field == &klass->fields [i])
129 return mono_class_get_first_field_idx (klass) + 1 + i;
135 * Find the property index in the metadata Property table.
138 find_property_index (MonoClass *klass, MonoProperty *property)
141 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
143 for (i = 0; i < info->count; ++i) {
144 if (property == &info->properties [i])
145 return info->first + 1 + i;
151 * Find the event index in the metadata Event table.
154 find_event_index (MonoClass *klass, MonoEvent *event)
157 MonoClassEventInfo *info = mono_class_get_event_info (klass);
159 for (i = 0; i < info->count; ++i) {
160 if (event == &info->events [i])
161 return info->first + 1 + i;
167 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
168 * The @is_enum flag only affects the error message that's displayed on failure.
171 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
173 MonoError inner_error;
174 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
176 mono_error_set_type_load_name (error, g_strdup(n), NULL,
177 "Could not load %s %s while decoding custom attribute: %s",
178 is_enum ? "enum type": "type",
180 mono_error_get_message (&inner_error));
181 mono_error_cleanup (&inner_error);
188 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
192 int slen = mono_metadata_decode_value (p, &p);
196 n = (char *)g_memdup (p, slen + 1);
198 t = cattr_type_from_name (n, image, TRUE, error);
200 return_val_if_nok (error, NULL);
203 return mono_class_from_mono_type (t);
207 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
209 int slen, type = t->type;
210 MonoClass *tklass = t->data.klass;
218 case MONO_TYPE_BOOLEAN: {
219 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
227 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
232 #if SIZEOF_VOID_P == 4
239 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
244 #if SIZEOF_VOID_P == 8
245 case MONO_TYPE_U: /* error out instead? this should probably not happen */
250 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
256 double *val = (double *)g_malloc (sizeof (double));
261 case MONO_TYPE_VALUETYPE:
262 if (t->data.klass->enumtype) {
263 type = mono_class_enum_basetype (t->data.klass)->type;
266 MonoClass *k = t->data.klass;
268 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
269 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
275 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
278 case MONO_TYPE_STRING:
279 if (*p == (char)0xFF) {
283 slen = mono_metadata_decode_value (p, &p);
285 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
286 case MONO_TYPE_CLASS: {
287 MonoReflectionType *rt;
290 if (*p == (char)0xFF) {
295 slen = mono_metadata_decode_value (p, &p);
296 n = (char *)g_memdup (p, slen + 1);
298 t = cattr_type_from_name (n, image, FALSE, error);
300 return_val_if_nok (error, NULL);
303 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
304 if (!mono_error_ok (error))
309 case MONO_TYPE_OBJECT: {
312 MonoClass *subc = NULL;
317 } else if (subt == 0x0E) {
318 type = MONO_TYPE_STRING;
320 } else if (subt == 0x1D) {
321 MonoType simple_type = {{0}};
325 type = MONO_TYPE_SZARRAY;
327 tklass = mono_defaults.systemtype_class;
328 } else if (etype == 0x55) {
329 tklass = load_cattr_enum_type (image, p, &p, error);
330 if (!mono_error_ok (error))
334 /* See Partition II, Appendix B3 */
335 etype = MONO_TYPE_OBJECT;
336 simple_type.type = (MonoTypeEnum)etype;
337 tklass = mono_class_from_mono_type (&simple_type);
340 } else if (subt == 0x55) {
343 slen = mono_metadata_decode_value (p, &p);
344 n = (char *)g_memdup (p, slen + 1);
346 t = cattr_type_from_name (n, image, FALSE, error);
348 return_val_if_nok (error, NULL);
350 subc = mono_class_from_mono_type (t);
351 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
352 MonoType simple_type = {{0}};
353 simple_type.type = (MonoTypeEnum)subt;
354 subc = mono_class_from_mono_type (&simple_type);
356 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
358 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
360 if (mono_error_ok (error)) {
361 obj = mono_object_new_checked (mono_domain_get (), subc, error);
362 g_assert (!subc->has_references);
363 if (mono_error_ok (error))
364 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
370 case MONO_TYPE_SZARRAY: {
372 guint32 i, alen, basetype;
375 if (alen == 0xffffffff) {
379 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
380 return_val_if_nok (error, NULL);
381 basetype = tklass->byval_arg.type;
382 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
383 basetype = mono_class_enum_basetype (tklass)->type;
388 case MONO_TYPE_BOOLEAN:
389 for (i = 0; i < alen; i++) {
390 MonoBoolean val = *p++;
391 mono_array_set (arr, MonoBoolean, i, val);
397 for (i = 0; i < alen; i++) {
398 guint16 val = read16 (p);
399 mono_array_set (arr, guint16, i, val);
406 for (i = 0; i < alen; i++) {
407 guint32 val = read32 (p);
408 mono_array_set (arr, guint32, i, val);
413 for (i = 0; i < alen; i++) {
416 mono_array_set (arr, double, i, val);
422 for (i = 0; i < alen; i++) {
423 guint64 val = read64 (p);
424 mono_array_set (arr, guint64, i, val);
428 case MONO_TYPE_CLASS:
429 case MONO_TYPE_OBJECT:
430 case MONO_TYPE_STRING:
431 case MONO_TYPE_SZARRAY:
432 for (i = 0; i < alen; i++) {
433 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
434 if (!mono_error_ok (error))
436 mono_array_setref (arr, i, item);
440 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
446 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
452 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
456 gboolean is_ref = type_is_reference (t);
458 void *val = load_cattr_value (image, t, p, end, error);
459 if (!is_ok (error)) {
466 return (MonoObject*)val;
468 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
474 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
476 static MonoMethod *ctor;
478 void *params [2], *unboxed;
483 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
485 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
486 return_val_if_nok (error, NULL);
489 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
490 return_val_if_nok (error, NULL);
491 unboxed = mono_object_unbox (retval);
493 mono_runtime_invoke_checked (ctor, unboxed, params, error);
494 return_val_if_nok (error, NULL);
500 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
502 static MonoMethod *ctor;
504 void *unboxed, *params [2];
509 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
512 params [1] = typedarg;
513 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
514 return_val_if_nok (error, NULL);
516 unboxed = mono_object_unbox (retval);
518 mono_runtime_invoke_checked (ctor, unboxed, params, error);
519 return_val_if_nok (error, NULL);
525 static MonoCustomAttrInfo*
526 mono_custom_attrs_from_builders_handle (MonoImage *alloc_img, MonoImage *image, MonoArrayHandle cattrs)
528 return mono_custom_attrs_from_builders (alloc_img, image, MONO_HANDLE_RAW (cattrs)); /* FIXME use coop handles for mono_custom_attrs_from_builders */
532 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
534 MONO_REQ_GC_UNSAFE_MODE;
536 int i, index, count, not_visible;
537 MonoCustomAttrInfo *ainfo;
538 MonoReflectionCustomAttr *cattr;
542 /* FIXME: check in assembly the Run flag is set */
544 count = mono_array_length (cattrs);
546 /* Skip nonpublic attributes since MS.NET seems to do the same */
547 /* FIXME: This needs to be done more globally */
549 for (i = 0; i < count; ++i) {
550 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
551 if (!custom_attr_visible (image, cattr))
555 int num_attrs = count - not_visible;
556 ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
558 ainfo->image = image;
559 ainfo->num_attrs = num_attrs;
560 ainfo->cached = alloc_img != NULL;
562 for (i = 0; i < count; ++i) {
563 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
564 if (custom_attr_visible (image, cattr)) {
565 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
566 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
567 ainfo->attrs [index].ctor = cattr->ctor->method;
568 g_assert (cattr->ctor->method);
569 ainfo->attrs [index].data = saved;
570 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
574 g_assert (index == num_attrs && count == num_attrs + not_visible);
581 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
583 const char *p = (const char*)data;
585 guint32 i, j, num_named;
587 void *params_buf [32];
588 void **params = NULL;
589 MonoMethodSignature *sig;
593 mono_class_init (method->klass);
595 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
596 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
601 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
602 if (!mono_error_ok (error)) return NULL;
604 mono_runtime_invoke_checked (method, attr, NULL, error);
605 if (!mono_error_ok (error))
611 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
614 /*g_print ("got attr %s\n", method->klass->name);*/
616 sig = mono_method_signature (method);
617 if (sig->param_count < 32) {
619 memset (params, 0, sizeof (void*) * sig->param_count);
621 /* Allocate using GC so it gets GC tracking */
622 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
627 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
628 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
629 if (!mono_error_ok (error))
634 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
635 if (!mono_error_ok (error)) goto fail;
637 MonoObject *exc = NULL;
638 mono_runtime_try_invoke (method, attr, params, &exc, error);
639 if (!mono_error_ok (error))
642 mono_error_set_exception_instance (error, (MonoException*)exc);
646 num_named = read16 (named);
648 for (j = 0; j < num_named; j++) {
650 char *name, named_type, data_type;
651 named_type = *named++;
652 data_type = *named++; /* type of data */
653 if (data_type == MONO_TYPE_SZARRAY)
654 data_type = *named++;
655 if (data_type == MONO_TYPE_ENUM) {
658 type_len = mono_metadata_decode_blob_size (named, &named);
659 type_name = (char *)g_malloc (type_len + 1);
660 memcpy (type_name, named, type_len);
661 type_name [type_len] = 0;
663 /* FIXME: lookup the type and check type consistency */
666 name_len = mono_metadata_decode_blob_size (named, &named);
667 name = (char *)g_malloc (name_len + 1);
668 memcpy (name, named, name_len);
671 if (named_type == 0x53) {
672 MonoClassField *field;
675 /* how this fail is a blackbox */
676 field = mono_class_get_field_from_name (mono_object_class (attr), name);
678 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
683 val = load_cattr_value (image, field->type, named, &named, error);
684 if (!mono_error_ok (error)) {
686 if (!type_is_reference (field->type))
691 mono_field_set_value (attr, field, val);
692 if (!type_is_reference (field->type))
694 } else if (named_type == 0x54) {
699 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
702 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
708 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
713 /* can we have more that 1 arg in a custom attr named property? */
714 prop_type = prop->get? mono_method_signature (prop->get)->ret :
715 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
717 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
718 if (!mono_error_ok (error)) {
720 if (!type_is_reference (prop_type))
721 g_free (pparams [0]);
726 mono_property_set_value_checked (prop, attr, pparams, error);
727 if (!type_is_reference (prop_type))
728 g_free (pparams [0]);
729 if (!is_ok (error)) {
737 free_param_data (method->signature, params);
738 if (params != params_buf)
739 mono_gc_free_fixed (params);
744 free_param_data (method->signature, params);
745 if (params != params_buf)
746 mono_gc_free_fixed (params);
751 * mono_reflection_create_custom_attr_data_args:
753 * Create an array of typed and named arguments from the cattr blob given by DATA.
754 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
755 * NAMED_ARG_INFO will contain information about the named arguments.
758 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)
760 MonoArray *typedargs, *namedargs;
761 MonoClass *attrklass;
763 const char *p = (const char*)data;
765 guint32 i, j, num_named;
766 CattrNamedArg *arginfo = NULL;
770 *named_arg_info = NULL;
774 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
775 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
779 mono_class_init (method->klass);
781 domain = mono_domain_get ();
783 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
786 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
787 return_if_nok (error);
791 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
794 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
795 return_if_nok (error);
796 mono_array_setref (typedargs, i, obj);
800 num_named = read16 (named);
801 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
802 return_if_nok (error);
804 attrklass = method->klass;
806 arginfo = g_new0 (CattrNamedArg, num_named);
807 *named_arg_info = arginfo;
809 for (j = 0; j < num_named; j++) {
811 char *name, named_type, data_type;
812 named_type = *named++;
813 data_type = *named++; /* type of data */
814 if (data_type == MONO_TYPE_SZARRAY)
815 data_type = *named++;
816 if (data_type == MONO_TYPE_ENUM) {
819 type_len = mono_metadata_decode_blob_size (named, &named);
820 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
823 type_name = (char *)g_malloc (type_len + 1);
824 memcpy (type_name, named, type_len);
825 type_name [type_len] = 0;
827 /* FIXME: lookup the type and check type consistency */
830 name_len = mono_metadata_decode_blob_size (named, &named);
831 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
833 name = (char *)g_malloc (name_len + 1);
834 memcpy (name, named, name_len);
837 if (named_type == 0x53) {
839 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
846 arginfo [j].type = field->type;
847 arginfo [j].field = field;
849 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
850 if (!is_ok (error)) {
854 mono_array_setref (namedargs, j, obj);
856 } else if (named_type == 0x54) {
859 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
861 if (!prop || !prop->set) {
866 prop_type = prop->get? mono_method_signature (prop->get)->ret :
867 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
869 arginfo [j].type = prop_type;
870 arginfo [j].prop = prop;
872 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
873 if (!is_ok (error)) {
877 mono_array_setref (namedargs, j, obj);
882 *typed_args = typedargs;
883 *named_args = namedargs;
886 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
888 *named_arg_info = NULL;
892 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
895 MonoArray *typedargs, *namedargs;
898 CattrNamedArg *arginfo = NULL;
909 image = assembly->assembly->image;
910 method = ref_method->method;
911 domain = mono_object_domain (ref_method);
913 if (!mono_class_init (method->klass)) {
914 mono_error_set_for_class_failure (error, method->klass);
918 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
922 if (!typedargs || !namedargs)
925 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
926 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
927 MonoObject *typedarg;
929 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
932 mono_array_setref (typedargs, i, typedarg);
935 for (i = 0; i < mono_array_length (namedargs); ++i) {
936 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
937 MonoObject *typedarg, *namedarg, *minfo;
939 if (arginfo [i].prop) {
940 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
944 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
949 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
952 namedarg = create_cattr_named_arg (minfo, typedarg, error);
956 mono_array_setref (namedargs, i, namedarg);
959 *ctor_args = typedargs;
960 *named_args = namedargs;
964 return mono_error_ok (error);
968 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
971 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
972 mono_error_set_pending_exception (&error);
975 static MonoObjectHandle
976 create_custom_attr_data_handle (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
978 static MonoMethod *ctor;
985 g_assert (image->assembly);
988 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
990 domain = mono_domain_get ();
992 MonoObjectHandle attr = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error));
996 MonoReflectionMethod *ctor_obj = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
999 MonoReflectionAssemblyHandle assm = mono_assembly_get_object_handle (domain, image->assembly, error);
1002 params [0] = ctor_obj;
1003 params [1] = MONO_HANDLE_RAW (assm);
1004 params [2] = (gpointer)&cattr->data;
1005 params [3] = &cattr->data_size;
1007 mono_runtime_invoke_checked (ctor, MONO_HANDLE_RAW (attr), params, error);
1010 return MONO_HANDLE_NEW (MonoObject, NULL);
1014 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
1016 HANDLE_FUNCTION_ENTER ();
1017 MonoObjectHandle obj = create_custom_attr_data_handle (image, cattr, error);
1018 HANDLE_FUNCTION_RETURN_OBJ (obj);
1022 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
1030 for (i = 0; i < cinfo->num_attrs; ++i) {
1031 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
1032 if (!centry->ctor) {
1033 /* The cattr type is not finished yet */
1034 /* We should include the type name but cinfo doesn't contain it */
1035 mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1042 for (i = 0; i < cinfo->num_attrs; ++i) {
1043 MonoMethod *ctor = cinfo->attrs[i].ctor;
1045 if (mono_class_is_assignable_from (attr_klass, ctor->klass))
1049 n = cinfo->num_attrs;
1052 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
1053 return_val_if_nok (error, NULL);
1055 for (i = 0; i < cinfo->num_attrs; ++i) {
1056 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
1057 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
1058 attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
1059 if (!mono_error_ok (error))
1061 mono_array_setref (result, n, attr);
1069 * mono_custom_attrs_construct:
1072 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
1075 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
1076 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1082 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
1089 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
1090 return_val_if_nok (error, NULL);
1091 for (i = 0; i < cinfo->num_attrs; ++i) {
1092 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
1093 return_val_if_nok (error, NULL);
1094 mono_array_setref (result, i, attr);
1100 * mono_custom_attrs_from_index:
1102 * Returns: NULL if no attributes are found or if a loading error occurs.
1105 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
1108 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, FALSE, &error);
1109 mono_error_cleanup (&error);
1113 * mono_custom_attrs_from_index_checked:
1114 * \returns NULL if no attributes are found. On error returns NULL and sets \p error.
1117 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error)
1119 guint32 mtoken, i, len;
1120 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1122 MonoCustomAttrInfo *ainfo;
1123 GList *tmp, *list = NULL;
1125 MonoCustomAttrEntry* attr;
1129 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1131 i = mono_metadata_custom_attrs_from_index (image, idx);
1135 while (i < ca->rows) {
1136 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1138 list = g_list_prepend (list, GUINT_TO_POINTER (i));
1141 len = g_list_length (list);
1144 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
1145 ainfo->num_attrs = len;
1146 ainfo->image = image;
1147 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
1148 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
1149 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1150 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1151 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1152 mtoken |= MONO_TOKEN_METHOD_DEF;
1154 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1155 mtoken |= MONO_TOKEN_MEMBER_REF;
1158 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1161 attr = &ainfo->attrs [i - 1];
1162 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
1164 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error));
1165 if (ignore_missing) {
1166 mono_error_cleanup (error);
1175 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
1176 /*FIXME raising an exception here doesn't make any sense*/
1177 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
1182 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
1183 attr->data_size = mono_metadata_decode_value (data, &data);
1184 attr->data = (guchar*)data;
1192 * mono_custom_attrs_from_method:
1195 mono_custom_attrs_from_method (MonoMethod *method)
1198 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
1199 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
1204 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
1211 * An instantiated method has the same cattrs as the generic method definition.
1213 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1214 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1216 if (method->is_inflated)
1217 method = ((MonoMethodInflated *) method)->declaring;
1219 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
1220 return lookup_custom_attr (method->klass->image, method);
1223 /* Synthetic methods */
1226 idx = mono_method_get_index (method);
1227 idx <<= MONO_CUSTOM_ATTR_BITS;
1228 idx |= MONO_CUSTOM_ATTR_METHODDEF;
1229 return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error);
1233 * mono_custom_attrs_from_class:
1236 mono_custom_attrs_from_class (MonoClass *klass)
1239 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
1240 mono_error_cleanup (&error);
1245 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
1251 if (mono_class_is_ginst (klass))
1252 klass = mono_class_get_generic_class (klass)->container_class;
1254 if (image_is_dynamic (klass->image))
1255 return lookup_custom_attr (klass->image, klass);
1257 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
1258 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
1259 idx <<= MONO_CUSTOM_ATTR_BITS;
1260 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
1262 idx = mono_metadata_token_index (klass->type_token);
1263 idx <<= MONO_CUSTOM_ATTR_BITS;
1264 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1266 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1270 * mono_custom_attrs_from_assembly:
1273 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
1276 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, FALSE, &error);
1277 mono_error_cleanup (&error);
1282 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error)
1288 if (image_is_dynamic (assembly->image))
1289 return lookup_custom_attr (assembly->image, assembly);
1290 idx = 1; /* there is only one assembly */
1291 idx <<= MONO_CUSTOM_ATTR_BITS;
1292 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1293 return mono_custom_attrs_from_index_checked (assembly->image, idx, ignore_missing, error);
1296 static MonoCustomAttrInfo*
1297 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
1303 if (image_is_dynamic (image))
1304 return lookup_custom_attr (image, image);
1305 idx = 1; /* there is only one module */
1306 idx <<= MONO_CUSTOM_ATTR_BITS;
1307 idx |= MONO_CUSTOM_ATTR_MODULE;
1308 return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1312 * mono_custom_attrs_from_property:
1315 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
1318 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
1319 mono_error_cleanup (&error);
1324 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
1330 if (image_is_dynamic (klass->image)) {
1331 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
1332 return lookup_custom_attr (klass->image, property);
1334 idx = find_property_index (klass, property);
1335 idx <<= MONO_CUSTOM_ATTR_BITS;
1336 idx |= MONO_CUSTOM_ATTR_PROPERTY;
1337 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1341 * mono_custom_attrs_from_event:
1344 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
1347 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
1348 mono_error_cleanup (&error);
1353 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
1359 if (image_is_dynamic (klass->image)) {
1360 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
1361 return lookup_custom_attr (klass->image, event);
1363 idx = find_event_index (klass, event);
1364 idx <<= MONO_CUSTOM_ATTR_BITS;
1365 idx |= MONO_CUSTOM_ATTR_EVENT;
1366 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1370 * mono_custom_attrs_from_field:
1373 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
1376 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
1377 mono_error_cleanup (&error);
1382 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
1387 if (image_is_dynamic (klass->image)) {
1388 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
1389 return lookup_custom_attr (klass->image, field);
1391 idx = find_field_index (klass, field);
1392 idx <<= MONO_CUSTOM_ATTR_BITS;
1393 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1394 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1398 * mono_custom_attrs_from_param:
1399 * \param method handle to the method that we want to retrieve custom parameter information from
1400 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1402 * The result must be released with mono_custom_attrs_free().
1404 * \returns the custom attribute object for the specified parameter, or NULL if there are none.
1407 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
1410 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
1411 mono_error_cleanup (&error);
1416 * mono_custom_attrs_from_param_checked:
1417 * \param method handle to the method that we want to retrieve custom parameter information from
1418 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1419 * \param error set on error
1421 * The result must be released with mono_custom_attrs_free().
1423 * \returns the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets \p error.
1426 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
1429 guint32 i, idx, method_index;
1430 guint32 param_list, param_last, param_pos, found;
1432 MonoReflectionMethodAux *aux;
1437 * An instantiated method has the same cattrs as the generic method definition.
1439 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1440 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1442 if (method->is_inflated)
1443 method = ((MonoMethodInflated *) method)->declaring;
1445 if (image_is_dynamic (method->klass->image)) {
1446 MonoCustomAttrInfo *res, *ainfo;
1449 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1450 if (!aux || !aux->param_cattr)
1453 /* Need to copy since it will be freed later */
1454 ainfo = aux->param_cattr [param];
1457 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
1458 res = (MonoCustomAttrInfo *)g_malloc0 (size);
1459 memcpy (res, ainfo, size);
1463 image = method->klass->image;
1464 method_index = mono_method_get_index (method);
1467 ca = &image->tables [MONO_TABLE_METHOD];
1469 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
1470 if (method_index == ca->rows) {
1471 ca = &image->tables [MONO_TABLE_PARAM];
1472 param_last = ca->rows + 1;
1474 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
1475 ca = &image->tables [MONO_TABLE_PARAM];
1478 for (i = param_list; i < param_last; ++i) {
1479 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
1480 if (param_pos == param) {
1488 idx <<= MONO_CUSTOM_ATTR_BITS;
1489 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1490 return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1494 * mono_custom_attrs_has_attr:
1497 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1500 for (i = 0; i < ainfo->num_attrs; ++i) {
1501 MonoCustomAttrEntry *centry = &ainfo->attrs[i];
1502 if (centry->ctor == NULL)
1504 MonoClass *klass = centry->ctor->klass;
1505 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)))
1512 * mono_custom_attrs_get_attr:
1515 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1518 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
1519 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1524 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
1527 MonoCustomAttrEntry *centry = NULL;
1529 g_assert (attr_klass != NULL);
1533 for (i = 0; i < ainfo->num_attrs; ++i) {
1534 centry = &ainfo->attrs[i];
1535 if (centry->ctor == NULL)
1537 MonoClass *klass = centry->ctor->klass;
1538 if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass))
1544 return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
1548 * mono_reflection_get_custom_attrs_info:
1549 * \param obj a reflection object handle
1551 * \returns the custom attribute info for attributes defined for the
1552 * reflection handle \p obj. The objects.
1554 * FIXME this function leaks like a sieve for SRE objects.
1557 mono_reflection_get_custom_attrs_info (MonoObject *obj_raw)
1559 HANDLE_FUNCTION_ENTER ();
1561 MONO_HANDLE_DCL (MonoObject, obj);
1562 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
1563 mono_error_assert_ok (&error);
1564 HANDLE_FUNCTION_RETURN_VAL (result);
1568 * mono_reflection_get_custom_attrs_info_checked:
1569 * \param obj a reflection object handle
1570 * \param error set on error
1572 * \returns the custom attribute info for attributes defined for the
1573 * reflection handle \p obj. The objects. On failure returns NULL and sets \p error.
1575 * FIXME this function leaks like a sieve for SRE objects.
1578 mono_reflection_get_custom_attrs_info_checked (MonoObjectHandle obj, MonoError *error)
1580 HANDLE_FUNCTION_ENTER ();
1582 MonoCustomAttrInfo *cinfo = NULL;
1586 klass = mono_handle_class (obj);
1587 if (klass == mono_defaults.runtimetype_class) {
1588 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST(MonoReflectionType, obj), error);
1591 klass = mono_class_from_mono_type (type);
1592 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1593 cinfo = mono_custom_attrs_from_class_checked (klass, error);
1596 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
1597 MonoReflectionAssemblyHandle rassembly = MONO_HANDLE_CAST (MonoReflectionAssembly, obj);
1598 cinfo = mono_custom_attrs_from_assembly_checked (MONO_HANDLE_GETVAL (rassembly, assembly), FALSE, error);
1601 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
1602 MonoReflectionModuleHandle module = MONO_HANDLE_CAST (MonoReflectionModule, obj);
1603 cinfo = mono_custom_attrs_from_module (MONO_HANDLE_GETVAL (module, image), error);
1606 } else if (strcmp ("MonoProperty", klass->name) == 0) {
1607 MonoReflectionPropertyHandle rprop = MONO_HANDLE_CAST (MonoReflectionProperty, obj);
1608 MonoProperty *property = MONO_HANDLE_GETVAL (rprop, property);
1609 cinfo = mono_custom_attrs_from_property_checked (property->parent, property, error);
1612 } else if (strcmp ("MonoEvent", klass->name) == 0) {
1613 MonoReflectionMonoEventHandle revent = MONO_HANDLE_CAST (MonoReflectionMonoEvent, obj);
1614 MonoEvent *event = MONO_HANDLE_GETVAL (revent, event);
1615 cinfo = mono_custom_attrs_from_event_checked (event->parent, event, error);
1618 } else if (strcmp ("MonoField", klass->name) == 0) {
1619 MonoReflectionFieldHandle rfield = MONO_HANDLE_CAST (MonoReflectionField, obj);
1620 MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field);
1621 cinfo = mono_custom_attrs_from_field_checked (field->parent, field, error);
1624 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
1625 MonoReflectionMethodHandle rmethod = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1626 cinfo = mono_custom_attrs_from_method_checked (MONO_HANDLE_GETVAL (rmethod, method), error);
1629 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
1630 MonoReflectionParameterHandle param = MONO_HANDLE_CAST (MonoReflectionParameter, obj);
1631 MonoObjectHandle member_impl = MONO_HANDLE_NEW_GET (MonoObject, param, MemberImpl);
1632 MonoClass *member_class = mono_handle_class (member_impl);
1633 if (mono_class_is_reflection_method_or_constructor (member_class)) {
1634 MonoReflectionMethodHandle rmethod = MONO_HANDLE_CAST (MonoReflectionMethod, member_impl);
1635 cinfo = mono_custom_attrs_from_param_checked (MONO_HANDLE_GETVAL (rmethod, method), MONO_HANDLE_GETVAL (param, PositionImpl) + 1, error);
1638 } else if (mono_is_sr_mono_property (member_class)) {
1639 MonoReflectionPropertyHandle prop = MONO_HANDLE_CAST (MonoReflectionProperty, member_impl);
1640 MonoProperty *property = MONO_HANDLE_GETVAL (prop, property);
1642 if (!(method = property->get))
1643 method = property->set;
1646 cinfo = mono_custom_attrs_from_param_checked (method, MONO_HANDLE_GETVAL (param, PositionImpl) + 1, error);
1650 #ifndef DISABLE_REFLECTION_EMIT
1651 else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
1652 // FIXME: Is this still needed ?
1653 g_assert_not_reached ();
1654 } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
1655 // FIXME: Is this still needed ?
1656 g_assert_not_reached ();
1660 char *type_name = mono_type_get_full_name (member_class);
1661 mono_error_set_not_supported (error,
1662 "Custom attributes on a ParamInfo with member %s are not supported",
1667 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
1668 MonoReflectionAssemblyBuilderHandle assemblyb = MONO_HANDLE_CAST (MonoReflectionAssemblyBuilder, obj);
1669 MonoReflectionAssemblyHandle assembly = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb);
1670 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs);
1671 cinfo = mono_custom_attrs_from_builders_handle (NULL, MONO_HANDLE_GETVAL (assembly, assembly)->image, cattrs);
1672 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
1673 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, obj);
1674 MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, tb, module);
1675 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (module, dynamic_image);
1676 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, tb, cattrs);
1677 cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
1678 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
1679 MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionModuleBuilder, obj);
1680 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
1681 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs);
1682 cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
1683 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
1684 MonoReflectionCtorBuilderHandle cb = MONO_HANDLE_CAST (MonoReflectionCtorBuilder, obj);
1685 MonoMethod *mhandle = MONO_HANDLE_GETVAL (cb, mhandle);
1686 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, cb, cattrs);
1687 cinfo = mono_custom_attrs_from_builders_handle (NULL, mhandle->klass->image, cattrs);
1688 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
1689 MonoReflectionMethodBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionMethodBuilder, obj);
1690 MonoMethod *mhandle = MONO_HANDLE_GETVAL (mb, mhandle);
1691 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs);
1692 cinfo = mono_custom_attrs_from_builders_handle (NULL, mhandle->klass->image, cattrs);
1693 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
1694 MonoReflectionFieldBuilderHandle fb = MONO_HANDLE_CAST (MonoReflectionFieldBuilder, obj);
1695 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, fb, typeb);
1696 MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, tb, module);
1697 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
1698 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, fb, cattrs);
1699 cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
1700 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
1701 MonoReflectionGenericClassHandle gclass = MONO_HANDLE_CAST (MonoReflectionGenericClass, obj);
1702 MonoReflectionTypeHandle generic_type = MONO_HANDLE_NEW_GET (MonoReflectionType, gclass, generic_type);
1703 cinfo = mono_reflection_get_custom_attrs_info_checked (MONO_HANDLE_CAST (MonoObject, generic_type), error);
1706 } else { /* handle other types here... */
1707 g_error ("get custom attrs not yet supported for %s", klass->name);
1711 HANDLE_FUNCTION_RETURN_VAL (cinfo);
1715 * mono_reflection_get_custom_attrs_by_type:
1716 * \param obj a reflection object handle
1717 * \returns an array with all the custom attributes defined of the
1718 * reflection handle \p obj. If \p attr_klass is non-NULL, only custom attributes
1719 * of that type are returned. The objects are fully build. Return NULL if a loading error
1723 mono_reflection_get_custom_attrs_by_type (MonoObject *obj_raw, MonoClass *attr_klass, MonoError *error)
1725 HANDLE_FUNCTION_ENTER ();
1726 MONO_HANDLE_DCL (MonoObject, obj);
1727 MonoArrayHandle result = mono_reflection_get_custom_attrs_by_type_handle (obj, attr_klass, error);
1728 HANDLE_FUNCTION_RETURN_OBJ (result);
1732 mono_reflection_get_custom_attrs_by_type_handle (MonoObjectHandle obj, MonoClass *attr_klass, MonoError *error)
1734 MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
1735 MonoCustomAttrInfo *cinfo;
1739 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1743 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 */
1745 mono_custom_attrs_free (cinfo);
1749 MONO_HANDLE_ASSIGN (result, mono_array_new_handle (mono_domain_get (), mono_defaults.attribute_class, 0, error));
1757 * mono_reflection_get_custom_attrs:
1758 * \param obj a reflection object handle
1759 * \return an array with all the custom attributes defined of the
1760 * reflection handle \p obj. The objects are fully build. Return NULL if a loading error
1764 mono_reflection_get_custom_attrs (MonoObject *obj_raw)
1766 HANDLE_FUNCTION_ENTER ();
1768 MONO_HANDLE_DCL (MonoObject, obj);
1769 MonoArrayHandle result = mono_reflection_get_custom_attrs_by_type_handle (obj, NULL, &error);
1770 mono_error_cleanup (&error);
1771 HANDLE_FUNCTION_RETURN_OBJ (result);
1775 * mono_reflection_get_custom_attrs_data:
1776 * \param obj a reflection obj handle
1777 * \returns an array of \c System.Reflection.CustomAttributeData,
1778 * which include information about attributes reflected on
1779 * types loaded using the Reflection Only methods
1782 mono_reflection_get_custom_attrs_data (MonoObject *obj_raw)
1784 HANDLE_FUNCTION_ENTER ();
1786 MONO_HANDLE_DCL (MonoObject, obj);
1787 MonoArrayHandle result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
1788 mono_error_cleanup (&error);
1789 HANDLE_FUNCTION_RETURN_OBJ (result);
1793 * mono_reflection_get_custom_attrs_data_checked:
1794 * @obj: a reflection obj handle
1795 * @error: set on error
1797 * Returns an array of System.Reflection.CustomAttributeData,
1798 * which include information about attributes reflected on
1799 * types loaded using the Reflection Only methods
1802 mono_reflection_get_custom_attrs_data_checked (MonoObjectHandle obj, MonoError *error)
1804 MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
1805 MonoCustomAttrInfo *cinfo;
1809 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1813 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 */
1815 mono_custom_attrs_free (cinfo);
1819 MONO_HANDLE_ASSIGN (result, mono_array_new_handle (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error));
1826 custom_attr_class_name_from_methoddef (MonoImage *image, guint32 method_token, const gchar **nspace, const gchar **class_name)
1828 /* mono_get_method_from_token () */
1829 g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD);
1830 guint32 type_token = mono_metadata_typedef_from_method (image, method_token);
1832 /* Bad method token (could not find corresponding typedef) */
1835 type_token |= MONO_TOKEN_TYPE_DEF;
1837 /* mono_class_create_from_typedef () */
1838 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
1839 guint32 cols [MONO_TYPEDEF_SIZE];
1840 guint tidx = mono_metadata_token_index (type_token);
1842 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
1843 /* "Invalid typedef token %x", type_token */
1847 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
1850 *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1852 *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1859 * custom_attr_class_name_from_method_token:
1860 * @image: The MonoImage
1861 * @method_token: a token for a custom attr constructor in @image
1862 * @assembly_token: out argment set to the assembly ref token of the custom attr
1863 * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
1864 * @class_name: out argument set to the class name of the custom attr.
1866 * Given an @image and a @method_token (which is assumed to be a
1867 * constructor), fills in the out arguments with the assembly ref (if
1868 * a methodref) and the namespace and class name of the custom
1871 * Returns: TRUE on success, FALSE otherwise.
1873 * LOCKING: does not take locks
1876 custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token, guint32 *assembly_token, const gchar **nspace, const gchar **class_name)
1878 /* This only works with method tokens constructed from a
1879 * custom attr token, which can only be methoddef or
1881 g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD
1882 || mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF);
1884 if (mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF) {
1885 /* method_from_memberref () */
1887 guint32 nindex, class_index;
1889 int idx = mono_metadata_token_index (method_token);
1891 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
1892 nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS;
1893 class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK;
1894 if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) {
1895 guint32 type_token = MONO_TOKEN_TYPE_REF | nindex;
1896 /* mono_class_from_typeref_checked () */
1898 guint32 cols [MONO_TYPEREF_SIZE];
1899 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
1901 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
1904 *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
1906 *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
1908 *assembly_token = cols [MONO_TYPEREF_SCOPE];
1911 } else if (class_index == MONO_MEMBERREF_PARENT_METHODDEF) {
1912 guint32 methoddef_token = MONO_TOKEN_METHOD_DEF | nindex;
1914 *assembly_token = 0;
1915 return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name);
1917 /* Attributes can't be generic, so it won't be
1918 * a typespec, and they're always
1919 * constructors, so it won't be a moduleref */
1920 g_assert_not_reached ();
1923 /* must be MONO_TABLE_METHOD */
1925 *assembly_token = 0;
1926 return custom_attr_class_name_from_methoddef (image, method_token, nspace, class_name);
1931 * mono_assembly_metadata_foreach_custom_attr:
1932 * \param assembly the assembly to iterate over
1933 * \param func the function to call for each custom attribute
1934 * \param user_data passed to \p func
1935 * Calls \p func for each custom attribute type on the given assembly until \p func returns TRUE.
1936 * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
1939 mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data)
1943 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1948 * This might be called during assembly loading, so do everything using the low-level
1952 image = assembly->image;
1953 g_assert (!image_is_dynamic (image));
1954 idx = 1; /* there is only one assembly */
1955 idx <<= MONO_CUSTOM_ATTR_BITS;
1956 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1958 /* Inlined from mono_custom_attrs_from_index_checked () */
1959 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1960 i = mono_metadata_custom_attrs_from_index (image, idx);
1964 gboolean stop_iterating = FALSE;
1965 while (!stop_iterating && i < ca->rows) {
1966 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1968 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
1970 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1971 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1972 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1973 mtoken |= MONO_TOKEN_METHOD_DEF;
1975 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1976 mtoken |= MONO_TOKEN_MEMBER_REF;
1979 g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1983 const char *nspace = NULL;
1984 const char *name = NULL;
1985 guint32 assembly_token = 0;
1987 if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name))
1990 stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data);