2 * custom-attrs.c: Custom attributes.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
10 * Copyright 2016 Microsoft
12 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #include "mono/metadata/assembly.h"
16 #include "mono/metadata/gc-internals.h"
17 #include "mono/metadata/mono-endian.h"
18 #include "mono/metadata/object-internals.h"
19 #include "mono/metadata/reflection-cache.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);
47 * LOCKING: Acquires the loader lock.
49 static MonoCustomAttrInfo*
50 lookup_custom_attr (MonoImage *image, gpointer member)
52 MONO_REQ_GC_NEUTRAL_MODE;
54 MonoCustomAttrInfo* res;
56 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
61 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
67 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
69 MONO_REQ_GC_UNSAFE_MODE;
71 /* FIXME: Need to do more checks */
72 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
73 int visibility = mono_class_get_flags (cattr->ctor->method->klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
75 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
83 type_is_reference (MonoType *type)
86 case MONO_TYPE_BOOLEAN:
100 case MONO_TYPE_VALUETYPE:
108 free_param_data (MonoMethodSignature *sig, void **params) {
110 for (i = 0; i < sig->param_count; ++i) {
111 if (!type_is_reference (sig->params [i]))
117 * Find the field index in the metadata FieldDef table.
120 find_field_index (MonoClass *klass, MonoClassField *field) {
123 int fcount = mono_class_get_field_count (klass);
124 for (i = 0; i < fcount; ++i) {
125 if (field == &klass->fields [i])
126 return mono_class_get_first_field_idx (klass) + 1 + i;
132 * Find the property index in the metadata Property table.
135 find_property_index (MonoClass *klass, MonoProperty *property)
138 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
140 for (i = 0; i < info->count; ++i) {
141 if (property == &info->properties [i])
142 return info->first + 1 + i;
148 * Find the event index in the metadata Event table.
151 find_event_index (MonoClass *klass, MonoEvent *event)
154 MonoClassEventInfo *info = mono_class_get_event_info (klass);
156 for (i = 0; i < info->count; ++i) {
157 if (event == &info->events [i])
158 return info->first + 1 + i;
164 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
165 * The @is_enum flag only affects the error message that's displayed on failure.
168 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
170 MonoError inner_error;
171 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
173 mono_error_set_type_load_name (error, g_strdup(n), NULL,
174 "Could not load %s %s while decoding custom attribute: %s",
175 is_enum ? "enum type": "type",
177 mono_error_get_message (&inner_error));
178 mono_error_cleanup (&inner_error);
185 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
189 int slen = mono_metadata_decode_value (p, &p);
191 mono_error_init (error);
193 n = (char *)g_memdup (p, slen + 1);
195 t = cattr_type_from_name (n, image, TRUE, error);
197 return_val_if_nok (error, NULL);
200 return mono_class_from_mono_type (t);
204 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
206 int slen, type = t->type;
207 MonoClass *tklass = t->data.klass;
209 mono_error_init (error);
215 case MONO_TYPE_BOOLEAN: {
216 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
224 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
229 #if SIZEOF_VOID_P == 4
236 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
241 #if SIZEOF_VOID_P == 8
242 case MONO_TYPE_U: /* error out instead? this should probably not happen */
247 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
253 double *val = (double *)g_malloc (sizeof (double));
258 case MONO_TYPE_VALUETYPE:
259 if (t->data.klass->enumtype) {
260 type = mono_class_enum_basetype (t->data.klass)->type;
263 MonoClass *k = t->data.klass;
265 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
266 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
272 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
275 case MONO_TYPE_STRING:
276 if (*p == (char)0xFF) {
280 slen = mono_metadata_decode_value (p, &p);
282 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
283 case MONO_TYPE_CLASS: {
284 MonoReflectionType *rt;
287 if (*p == (char)0xFF) {
292 slen = mono_metadata_decode_value (p, &p);
293 n = (char *)g_memdup (p, slen + 1);
295 t = cattr_type_from_name (n, image, FALSE, error);
297 return_val_if_nok (error, NULL);
300 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
301 if (!mono_error_ok (error))
306 case MONO_TYPE_OBJECT: {
309 MonoClass *subc = NULL;
314 } else if (subt == 0x0E) {
315 type = MONO_TYPE_STRING;
317 } else if (subt == 0x1D) {
318 MonoType simple_type = {{0}};
322 type = MONO_TYPE_SZARRAY;
324 tklass = mono_defaults.systemtype_class;
325 } else if (etype == 0x55) {
326 tklass = load_cattr_enum_type (image, p, &p, error);
327 if (!mono_error_ok (error))
331 /* See Partition II, Appendix B3 */
332 etype = MONO_TYPE_OBJECT;
333 simple_type.type = (MonoTypeEnum)etype;
334 tklass = mono_class_from_mono_type (&simple_type);
337 } else if (subt == 0x55) {
340 slen = mono_metadata_decode_value (p, &p);
341 n = (char *)g_memdup (p, slen + 1);
343 t = cattr_type_from_name (n, image, FALSE, error);
345 return_val_if_nok (error, NULL);
347 subc = mono_class_from_mono_type (t);
348 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
349 MonoType simple_type = {{0}};
350 simple_type.type = (MonoTypeEnum)subt;
351 subc = mono_class_from_mono_type (&simple_type);
353 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
355 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
357 if (mono_error_ok (error)) {
358 obj = mono_object_new_checked (mono_domain_get (), subc, error);
359 g_assert (!subc->has_references);
360 if (mono_error_ok (error))
361 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
367 case MONO_TYPE_SZARRAY: {
369 guint32 i, alen, basetype;
372 if (alen == 0xffffffff) {
376 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
377 return_val_if_nok (error, NULL);
378 basetype = tklass->byval_arg.type;
379 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
380 basetype = mono_class_enum_basetype (tklass)->type;
385 case MONO_TYPE_BOOLEAN:
386 for (i = 0; i < alen; i++) {
387 MonoBoolean val = *p++;
388 mono_array_set (arr, MonoBoolean, i, val);
394 for (i = 0; i < alen; i++) {
395 guint16 val = read16 (p);
396 mono_array_set (arr, guint16, i, val);
403 for (i = 0; i < alen; i++) {
404 guint32 val = read32 (p);
405 mono_array_set (arr, guint32, i, val);
410 for (i = 0; i < alen; i++) {
413 mono_array_set (arr, double, i, val);
419 for (i = 0; i < alen; i++) {
420 guint64 val = read64 (p);
421 mono_array_set (arr, guint64, i, val);
425 case MONO_TYPE_CLASS:
426 case MONO_TYPE_OBJECT:
427 case MONO_TYPE_STRING:
428 case MONO_TYPE_SZARRAY:
429 for (i = 0; i < alen; i++) {
430 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
431 if (!mono_error_ok (error))
433 mono_array_setref (arr, i, item);
437 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
443 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
449 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
451 mono_error_init (error);
453 gboolean is_ref = type_is_reference (t);
455 void *val = load_cattr_value (image, t, p, end, error);
456 if (!is_ok (error)) {
463 return (MonoObject*)val;
465 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
471 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
473 static MonoMethod *ctor;
475 void *params [2], *unboxed;
477 mono_error_init (error);
480 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
482 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
483 return_val_if_nok (error, NULL);
486 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
487 return_val_if_nok (error, NULL);
488 unboxed = mono_object_unbox (retval);
490 mono_runtime_invoke_checked (ctor, unboxed, params, error);
491 return_val_if_nok (error, NULL);
497 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
499 static MonoMethod *ctor;
501 void *unboxed, *params [2];
503 mono_error_init (error);
506 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
509 params [1] = typedarg;
510 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
511 return_val_if_nok (error, NULL);
513 unboxed = mono_object_unbox (retval);
515 mono_runtime_invoke_checked (ctor, unboxed, params, error);
516 return_val_if_nok (error, NULL);
523 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
525 MONO_REQ_GC_UNSAFE_MODE;
527 int i, index, count, not_visible;
528 MonoCustomAttrInfo *ainfo;
529 MonoReflectionCustomAttr *cattr;
533 /* FIXME: check in assembly the Run flag is set */
535 count = mono_array_length (cattrs);
537 /* Skip nonpublic attributes since MS.NET seems to do the same */
538 /* FIXME: This needs to be done more globally */
540 for (i = 0; i < count; ++i) {
541 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
542 if (!custom_attr_visible (image, cattr))
546 int num_attrs = count - not_visible;
547 ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
549 ainfo->image = image;
550 ainfo->num_attrs = num_attrs;
551 ainfo->cached = alloc_img != NULL;
553 for (i = 0; i < count; ++i) {
554 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
555 if (custom_attr_visible (image, cattr)) {
556 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
557 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
558 ainfo->attrs [index].ctor = cattr->ctor->method;
559 g_assert (cattr->ctor->method);
560 ainfo->attrs [index].data = saved;
561 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
565 g_assert (index == num_attrs && count == num_attrs + not_visible);
572 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
574 const char *p = (const char*)data;
576 guint32 i, j, num_named;
578 void *params_buf [32];
579 void **params = NULL;
580 MonoMethodSignature *sig;
582 mono_error_init (error);
584 mono_class_init (method->klass);
586 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
587 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
592 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
593 if (!mono_error_ok (error)) return NULL;
595 mono_runtime_invoke_checked (method, attr, NULL, error);
596 if (!mono_error_ok (error))
602 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
605 /*g_print ("got attr %s\n", method->klass->name);*/
607 sig = mono_method_signature (method);
608 if (sig->param_count < 32) {
610 memset (params, 0, sizeof (void*) * sig->param_count);
612 /* Allocate using GC so it gets GC tracking */
613 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
618 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
619 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
620 if (!mono_error_ok (error))
625 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
626 if (!mono_error_ok (error)) goto fail;
628 MonoObject *exc = NULL;
629 mono_runtime_try_invoke (method, attr, params, &exc, error);
630 if (!mono_error_ok (error))
633 mono_error_set_exception_instance (error, (MonoException*)exc);
637 num_named = read16 (named);
639 for (j = 0; j < num_named; j++) {
641 char *name, named_type, data_type;
642 named_type = *named++;
643 data_type = *named++; /* type of data */
644 if (data_type == MONO_TYPE_SZARRAY)
645 data_type = *named++;
646 if (data_type == MONO_TYPE_ENUM) {
649 type_len = mono_metadata_decode_blob_size (named, &named);
650 type_name = (char *)g_malloc (type_len + 1);
651 memcpy (type_name, named, type_len);
652 type_name [type_len] = 0;
654 /* FIXME: lookup the type and check type consistency */
657 name_len = mono_metadata_decode_blob_size (named, &named);
658 name = (char *)g_malloc (name_len + 1);
659 memcpy (name, named, name_len);
662 if (named_type == 0x53) {
663 MonoClassField *field;
666 /* how this fail is a blackbox */
667 field = mono_class_get_field_from_name (mono_object_class (attr), name);
669 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
674 val = load_cattr_value (image, field->type, named, &named, error);
675 if (!mono_error_ok (error)) {
677 if (!type_is_reference (field->type))
682 mono_field_set_value (attr, field, val);
683 if (!type_is_reference (field->type))
685 } else if (named_type == 0x54) {
690 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
693 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
699 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
704 /* can we have more that 1 arg in a custom attr named property? */
705 prop_type = prop->get? mono_method_signature (prop->get)->ret :
706 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
708 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
709 if (!mono_error_ok (error)) {
711 if (!type_is_reference (prop_type))
712 g_free (pparams [0]);
717 mono_property_set_value_checked (prop, attr, pparams, error);
718 if (!type_is_reference (prop_type))
719 g_free (pparams [0]);
720 if (!is_ok (error)) {
728 free_param_data (method->signature, params);
729 if (params != params_buf)
730 mono_gc_free_fixed (params);
735 free_param_data (method->signature, params);
736 if (params != params_buf)
737 mono_gc_free_fixed (params);
742 * mono_reflection_create_custom_attr_data_args:
744 * Create an array of typed and named arguments from the cattr blob given by DATA.
745 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
746 * NAMED_ARG_INFO will contain information about the named arguments.
749 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)
751 MonoArray *typedargs, *namedargs;
752 MonoClass *attrklass;
754 const char *p = (const char*)data;
756 guint32 i, j, num_named;
757 CattrNamedArg *arginfo = NULL;
761 *named_arg_info = NULL;
763 mono_error_init (error);
765 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
766 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
770 mono_class_init (method->klass);
772 domain = mono_domain_get ();
774 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
777 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
778 return_if_nok (error);
782 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
785 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
786 return_if_nok (error);
787 mono_array_setref (typedargs, i, obj);
791 num_named = read16 (named);
792 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
793 return_if_nok (error);
795 attrklass = method->klass;
797 arginfo = g_new0 (CattrNamedArg, num_named);
798 *named_arg_info = arginfo;
800 for (j = 0; j < num_named; j++) {
802 char *name, named_type, data_type;
803 named_type = *named++;
804 data_type = *named++; /* type of data */
805 if (data_type == MONO_TYPE_SZARRAY)
806 data_type = *named++;
807 if (data_type == MONO_TYPE_ENUM) {
810 type_len = mono_metadata_decode_blob_size (named, &named);
811 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
814 type_name = (char *)g_malloc (type_len + 1);
815 memcpy (type_name, named, type_len);
816 type_name [type_len] = 0;
818 /* FIXME: lookup the type and check type consistency */
821 name_len = mono_metadata_decode_blob_size (named, &named);
822 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
824 name = (char *)g_malloc (name_len + 1);
825 memcpy (name, named, name_len);
828 if (named_type == 0x53) {
830 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
837 arginfo [j].type = field->type;
838 arginfo [j].field = field;
840 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
841 if (!is_ok (error)) {
845 mono_array_setref (namedargs, j, obj);
847 } else if (named_type == 0x54) {
850 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
852 if (!prop || !prop->set) {
857 prop_type = prop->get? mono_method_signature (prop->get)->ret :
858 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
860 arginfo [j].type = prop_type;
861 arginfo [j].prop = prop;
863 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
864 if (!is_ok (error)) {
868 mono_array_setref (namedargs, j, obj);
873 *typed_args = typedargs;
874 *named_args = namedargs;
877 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
879 *named_arg_info = NULL;
883 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
886 MonoArray *typedargs, *namedargs;
889 CattrNamedArg *arginfo = NULL;
892 mono_error_init (error);
900 image = assembly->assembly->image;
901 method = ref_method->method;
902 domain = mono_object_domain (ref_method);
904 if (!mono_class_init (method->klass)) {
905 mono_error_set_for_class_failure (error, method->klass);
909 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
913 if (!typedargs || !namedargs)
916 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
917 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
918 MonoObject *typedarg;
920 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
923 mono_array_setref (typedargs, i, typedarg);
926 for (i = 0; i < mono_array_length (namedargs); ++i) {
927 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
928 MonoObject *typedarg, *namedarg, *minfo;
930 if (arginfo [i].prop) {
931 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
935 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
940 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
943 namedarg = create_cattr_named_arg (minfo, typedarg, error);
947 mono_array_setref (namedargs, i, namedarg);
950 *ctor_args = typedargs;
951 *named_args = namedargs;
955 return mono_error_ok (error);
959 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
962 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
963 mono_error_set_pending_exception (&error);
967 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
969 static MonoMethod *ctor;
975 mono_error_init (error);
977 g_assert (image->assembly);
980 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
982 domain = mono_domain_get ();
983 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
984 return_val_if_nok (error, NULL);
985 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
986 return_val_if_nok (error, NULL);
987 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
988 return_val_if_nok (error, NULL);
989 params [2] = (gpointer)&cattr->data;
990 params [3] = &cattr->data_size;
992 mono_runtime_invoke_checked (ctor, attr, params, error);
993 return_val_if_nok (error, NULL);
998 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
1004 mono_error_init (error);
1006 for (i = 0; i < cinfo->num_attrs; ++i) {
1007 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
1008 if (!centry->ctor) {
1009 /* The cattr type is not finished yet */
1010 /* We should include the type name but cinfo doesn't contain it */
1011 mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1018 for (i = 0; i < cinfo->num_attrs; ++i) {
1019 MonoMethod *ctor = cinfo->attrs[i].ctor;
1021 if (mono_class_is_assignable_from (attr_klass, ctor->klass))
1025 n = cinfo->num_attrs;
1028 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
1029 return_val_if_nok (error, NULL);
1031 for (i = 0; i < cinfo->num_attrs; ++i) {
1032 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
1033 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
1034 attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
1035 if (!mono_error_ok (error))
1037 mono_array_setref (result, n, attr);
1045 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
1048 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
1049 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1055 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
1061 mono_error_init (error);
1062 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
1063 return_val_if_nok (error, NULL);
1064 for (i = 0; i < cinfo->num_attrs; ++i) {
1065 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
1066 return_val_if_nok (error, NULL);
1067 mono_array_setref (result, i, attr);
1073 * mono_custom_attrs_from_index:
1075 * Returns: NULL if no attributes are found or if a loading error occurs.
1078 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
1081 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, FALSE, &error);
1082 mono_error_cleanup (&error);
1086 * mono_custom_attrs_from_index_checked:
1088 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
1091 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error)
1093 guint32 mtoken, i, len;
1094 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1096 MonoCustomAttrInfo *ainfo;
1097 GList *tmp, *list = NULL;
1099 MonoCustomAttrEntry* attr;
1101 mono_error_init (error);
1103 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1105 i = mono_metadata_custom_attrs_from_index (image, idx);
1109 while (i < ca->rows) {
1110 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1112 list = g_list_prepend (list, GUINT_TO_POINTER (i));
1115 len = g_list_length (list);
1118 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
1119 ainfo->num_attrs = len;
1120 ainfo->image = image;
1121 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
1122 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
1123 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1124 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1125 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1126 mtoken |= MONO_TOKEN_METHOD_DEF;
1128 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1129 mtoken |= MONO_TOKEN_MEMBER_REF;
1132 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1135 attr = &ainfo->attrs [i - 1];
1136 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
1138 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error));
1139 if (ignore_missing) {
1140 mono_error_cleanup (error);
1141 mono_error_init (error);
1149 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
1150 /*FIXME raising an exception here doesn't make any sense*/
1151 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
1156 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
1157 attr->data_size = mono_metadata_decode_value (data, &data);
1158 attr->data = (guchar*)data;
1166 mono_custom_attrs_from_method (MonoMethod *method)
1169 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
1170 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
1175 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
1179 mono_error_init (error);
1182 * An instantiated method has the same cattrs as the generic method definition.
1184 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1185 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1187 if (method->is_inflated)
1188 method = ((MonoMethodInflated *) method)->declaring;
1190 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
1191 return lookup_custom_attr (method->klass->image, method);
1194 /* Synthetic methods */
1197 idx = mono_method_get_index (method);
1198 idx <<= MONO_CUSTOM_ATTR_BITS;
1199 idx |= MONO_CUSTOM_ATTR_METHODDEF;
1200 return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error);
1204 mono_custom_attrs_from_class (MonoClass *klass)
1207 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
1208 mono_error_cleanup (&error);
1213 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
1217 mono_error_init (error);
1219 if (mono_class_is_ginst (klass))
1220 klass = mono_class_get_generic_class (klass)->container_class;
1222 if (image_is_dynamic (klass->image))
1223 return lookup_custom_attr (klass->image, klass);
1225 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
1226 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
1227 idx <<= MONO_CUSTOM_ATTR_BITS;
1228 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
1230 idx = mono_metadata_token_index (klass->type_token);
1231 idx <<= MONO_CUSTOM_ATTR_BITS;
1232 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1234 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1238 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
1241 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, FALSE, &error);
1242 mono_error_cleanup (&error);
1247 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error)
1251 mono_error_init (error);
1253 if (image_is_dynamic (assembly->image))
1254 return lookup_custom_attr (assembly->image, assembly);
1255 idx = 1; /* there is only one assembly */
1256 idx <<= MONO_CUSTOM_ATTR_BITS;
1257 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1258 return mono_custom_attrs_from_index_checked (assembly->image, idx, ignore_missing, error);
1261 static MonoCustomAttrInfo*
1262 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
1266 if (image_is_dynamic (image))
1267 return lookup_custom_attr (image, image);
1268 idx = 1; /* there is only one module */
1269 idx <<= MONO_CUSTOM_ATTR_BITS;
1270 idx |= MONO_CUSTOM_ATTR_MODULE;
1271 return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1275 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
1278 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
1279 mono_error_cleanup (&error);
1284 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
1288 if (image_is_dynamic (klass->image)) {
1289 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
1290 return lookup_custom_attr (klass->image, property);
1292 idx = find_property_index (klass, property);
1293 idx <<= MONO_CUSTOM_ATTR_BITS;
1294 idx |= MONO_CUSTOM_ATTR_PROPERTY;
1295 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1299 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
1302 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
1303 mono_error_cleanup (&error);
1308 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
1312 if (image_is_dynamic (klass->image)) {
1313 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
1314 return lookup_custom_attr (klass->image, event);
1316 idx = find_event_index (klass, event);
1317 idx <<= MONO_CUSTOM_ATTR_BITS;
1318 idx |= MONO_CUSTOM_ATTR_EVENT;
1319 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1323 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
1326 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
1327 mono_error_cleanup (&error);
1332 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
1335 mono_error_init (error);
1337 if (image_is_dynamic (klass->image)) {
1338 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
1339 return lookup_custom_attr (klass->image, field);
1341 idx = find_field_index (klass, field);
1342 idx <<= MONO_CUSTOM_ATTR_BITS;
1343 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1344 return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1348 * mono_custom_attrs_from_param:
1349 * @method: handle to the method that we want to retrieve custom parameter information from
1350 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1352 * The result must be released with mono_custom_attrs_free().
1354 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
1357 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
1360 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
1361 mono_error_cleanup (&error);
1366 * mono_custom_attrs_from_param_checked:
1367 * @method: handle to the method that we want to retrieve custom parameter information from
1368 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1369 * @error: set on error
1371 * The result must be released with mono_custom_attrs_free().
1373 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
1376 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
1379 guint32 i, idx, method_index;
1380 guint32 param_list, param_last, param_pos, found;
1382 MonoReflectionMethodAux *aux;
1384 mono_error_init (error);
1387 * An instantiated method has the same cattrs as the generic method definition.
1389 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1390 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1392 if (method->is_inflated)
1393 method = ((MonoMethodInflated *) method)->declaring;
1395 if (image_is_dynamic (method->klass->image)) {
1396 MonoCustomAttrInfo *res, *ainfo;
1399 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1400 if (!aux || !aux->param_cattr)
1403 /* Need to copy since it will be freed later */
1404 ainfo = aux->param_cattr [param];
1407 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
1408 res = (MonoCustomAttrInfo *)g_malloc0 (size);
1409 memcpy (res, ainfo, size);
1413 image = method->klass->image;
1414 method_index = mono_method_get_index (method);
1417 ca = &image->tables [MONO_TABLE_METHOD];
1419 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
1420 if (method_index == ca->rows) {
1421 ca = &image->tables [MONO_TABLE_PARAM];
1422 param_last = ca->rows + 1;
1424 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
1425 ca = &image->tables [MONO_TABLE_PARAM];
1428 for (i = param_list; i < param_last; ++i) {
1429 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
1430 if (param_pos == param) {
1438 idx <<= MONO_CUSTOM_ATTR_BITS;
1439 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1440 return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1444 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1447 for (i = 0; i < ainfo->num_attrs; ++i) {
1448 MonoCustomAttrEntry *centry = &ainfo->attrs[i];
1449 if (centry->ctor == NULL)
1451 MonoClass *klass = centry->ctor->klass;
1452 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)))
1459 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1462 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
1463 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1468 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
1471 MonoCustomAttrEntry *centry = NULL;
1473 g_assert (attr_klass != NULL);
1475 mono_error_init (error);
1477 for (i = 0; i < ainfo->num_attrs; ++i) {
1478 centry = &ainfo->attrs[i];
1479 if (centry->ctor == NULL)
1481 MonoClass *klass = centry->ctor->klass;
1482 if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass))
1488 return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
1492 * mono_reflection_get_custom_attrs_info:
1493 * @obj: a reflection object handle
1495 * Return the custom attribute info for attributes defined for the
1496 * reflection handle @obj. The objects.
1498 * FIXME this function leaks like a sieve for SRE objects.
1501 mono_reflection_get_custom_attrs_info (MonoObject *obj)
1504 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
1505 mono_error_assert_ok (&error);
1510 * mono_reflection_get_custom_attrs_info_checked:
1511 * @obj: a reflection object handle
1512 * @error: set on error
1514 * Return the custom attribute info for attributes defined for the
1515 * reflection handle @obj. The objects.
1517 * On failure returns NULL and sets @error.
1519 * FIXME this function leaks like a sieve for SRE objects.
1522 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
1525 MonoCustomAttrInfo *cinfo = NULL;
1527 mono_error_init (error);
1529 klass = obj->vtable->klass;
1530 if (klass == mono_defaults.runtimetype_class) {
1531 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1532 return_val_if_nok (error, NULL);
1533 klass = mono_class_from_mono_type (type);
1534 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1535 cinfo = mono_custom_attrs_from_class_checked (klass, error);
1536 return_val_if_nok (error, NULL);
1537 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
1538 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
1539 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, FALSE, error);
1540 return_val_if_nok (error, NULL);
1541 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
1542 MonoReflectionModule *module = (MonoReflectionModule*)obj;
1543 cinfo = mono_custom_attrs_from_module (module->image, error);
1544 return_val_if_nok (error, NULL);
1545 } else if (strcmp ("MonoProperty", klass->name) == 0) {
1546 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
1547 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
1548 return_val_if_nok (error, NULL);
1549 } else if (strcmp ("MonoEvent", klass->name) == 0) {
1550 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
1551 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
1552 return_val_if_nok (error, NULL);
1553 } else if (strcmp ("MonoField", klass->name) == 0) {
1554 MonoReflectionField *rfield = (MonoReflectionField*)obj;
1555 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
1556 return_val_if_nok (error, NULL);
1557 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
1558 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
1559 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
1560 return_val_if_nok (error, NULL);
1561 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
1562 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
1563 MonoClass *member_class = mono_object_class (param->MemberImpl);
1564 if (mono_class_is_reflection_method_or_constructor (member_class)) {
1565 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
1566 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
1567 return_val_if_nok (error, NULL);
1568 } else if (mono_is_sr_mono_property (member_class)) {
1569 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
1571 if (!(method = prop->property->get))
1572 method = prop->property->set;
1575 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
1576 return_val_if_nok (error, NULL);
1578 #ifndef DISABLE_REFLECTION_EMIT
1579 else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
1580 // FIXME: Is this still needed ?
1581 g_assert_not_reached ();
1582 } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
1583 // FIXME: Is this still needed ?
1584 g_assert_not_reached ();
1588 char *type_name = mono_type_get_full_name (member_class);
1589 mono_error_set_not_supported (error,
1590 "Custom attributes on a ParamInfo with member %s are not supported",
1595 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
1596 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
1597 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
1598 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
1599 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
1600 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
1601 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
1602 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
1603 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
1604 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
1605 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
1606 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
1607 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
1608 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
1609 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
1610 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
1611 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
1612 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
1613 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
1614 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
1615 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
1616 return_val_if_nok (error, NULL);
1617 } else { /* handle other types here... */
1618 g_error ("get custom attrs not yet supported for %s", klass->name);
1625 * mono_reflection_get_custom_attrs_by_type:
1626 * @obj: a reflection object handle
1628 * Return an array with all the custom attributes defined of the
1629 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
1630 * of that type are returned. The objects are fully build. Return NULL if a loading error
1634 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
1637 MonoCustomAttrInfo *cinfo;
1639 mono_error_init (error);
1641 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1642 return_val_if_nok (error, NULL);
1644 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
1646 mono_custom_attrs_free (cinfo);
1650 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
1657 * mono_reflection_get_custom_attrs:
1658 * @obj: a reflection object handle
1660 * Return an array with all the custom attributes defined of the
1661 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
1665 mono_reflection_get_custom_attrs (MonoObject *obj)
1669 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
1673 * mono_reflection_get_custom_attrs_data:
1674 * @obj: a reflection obj handle
1676 * Returns an array of System.Reflection.CustomAttributeData,
1677 * which include information about attributes reflected on
1678 * types loaded using the Reflection Only methods
1681 mono_reflection_get_custom_attrs_data (MonoObject *obj)
1685 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
1686 mono_error_cleanup (&error);
1691 * mono_reflection_get_custom_attrs_data_checked:
1692 * @obj: a reflection obj handle
1693 * @error: set on error
1695 * Returns an array of System.Reflection.CustomAttributeData,
1696 * which include information about attributes reflected on
1697 * types loaded using the Reflection Only methods
1700 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
1703 MonoCustomAttrInfo *cinfo;
1705 mono_error_init (error);
1707 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1708 return_val_if_nok (error, NULL);
1710 result = mono_custom_attrs_data_construct (cinfo, error);
1712 mono_custom_attrs_free (cinfo);
1713 return_val_if_nok (error, NULL);
1715 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
1721 custom_attr_class_name_from_methoddef (MonoImage *image, guint32 method_token, const gchar **nspace, const gchar **class_name)
1723 /* mono_get_method_from_token () */
1724 g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD);
1725 guint32 type_token = mono_metadata_typedef_from_method (image, method_token);
1727 /* Bad method token (could not find corresponding typedef) */
1730 type_token |= MONO_TOKEN_TYPE_DEF;
1732 /* mono_class_create_from_typedef () */
1733 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
1734 guint32 cols [MONO_TYPEDEF_SIZE];
1735 guint tidx = mono_metadata_token_index (type_token);
1737 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
1738 /* "Invalid typedef token %x", type_token */
1742 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
1745 *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1747 *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1754 * custom_attr_class_name_from_method_token:
1755 * @image: The MonoImage
1756 * @method_token: a token for a custom attr constructor in @image
1757 * @assembly_token: out argment set to the assembly ref token of the custom attr
1758 * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
1759 * @class_name: out argument set to the class name of the custom attr.
1761 * Given an @image and a @method_token (which is assumed to be a
1762 * constructor), fills in the out arguments with the assembly ref (if
1763 * a methodref) and the namespace and class name of the custom
1766 * Returns: TRUE on success, FALSE otherwise.
1768 * LOCKING: does not take locks
1771 custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token, guint32 *assembly_token, const gchar **nspace, const gchar **class_name)
1773 /* This only works with method tokens constructed from a
1774 * custom attr token, which can only be methoddef or
1776 g_assert (mono_metadata_token_table (method_token) == MONO_TABLE_METHOD
1777 || mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF);
1779 if (mono_metadata_token_table (method_token) == MONO_TABLE_MEMBERREF) {
1780 /* method_from_memberref () */
1782 guint32 nindex, class_index;
1784 int idx = mono_metadata_token_index (method_token);
1786 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
1787 nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS;
1788 class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK;
1789 if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) {
1790 guint32 type_token = MONO_TOKEN_TYPE_REF | nindex;
1791 /* mono_class_from_typeref_checked () */
1793 guint32 cols [MONO_TYPEREF_SIZE];
1794 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
1796 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
1799 *class_name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
1801 *nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
1803 *assembly_token = cols [MONO_TYPEREF_SCOPE];
1806 } else if (class_index == MONO_MEMBERREF_PARENT_METHODDEF) {
1807 guint32 methoddef_token = MONO_TOKEN_METHOD_DEF | nindex;
1809 *assembly_token = 0;
1810 return custom_attr_class_name_from_methoddef (image, methoddef_token, nspace, class_name);
1812 /* Attributes can't be generic, so it won't be
1813 * a typespec, and they're always
1814 * constructors, so it won't be a moduleref */
1815 g_assert_not_reached ();
1818 /* must be MONO_TABLE_METHOD */
1820 *assembly_token = 0;
1821 return custom_attr_class_name_from_methoddef (image, method_token, nspace, class_name);
1826 * mono_assembly_metadata_foreach_custom_attr:
1827 * @assembly: the assembly to iterate over
1828 * @func: the function to call for each custom attribute
1829 * @user_data: passed to @func
1831 * Calls @func for each custom attribute type on the given assembly until @func returns TRUE.
1832 * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
1836 mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data)
1840 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1845 * This might be called during assembly loading, so do everything using the low-level
1849 image = assembly->image;
1850 g_assert (!image_is_dynamic (image));
1851 idx = 1; /* there is only one assembly */
1852 idx <<= MONO_CUSTOM_ATTR_BITS;
1853 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1855 /* Inlined from mono_custom_attrs_from_index_checked () */
1856 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1857 i = mono_metadata_custom_attrs_from_index (image, idx);
1861 gboolean stop_iterating = FALSE;
1862 while (!stop_iterating && i < ca->rows) {
1863 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1865 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
1867 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1868 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1869 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1870 mtoken |= MONO_TOKEN_METHOD_DEF;
1872 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1873 mtoken |= MONO_TOKEN_MEMBER_REF;
1876 g_warning ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1880 const char *nspace = NULL;
1881 const char *name = NULL;
1882 guint32 assembly_token = 0;
1884 if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name))
1887 stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data);