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/gc-internals.h"
16 #include "mono/metadata/mono-endian.h"
17 #include "mono/metadata/object-internals.h"
18 #include "mono/metadata/reflection-cache.h"
19 #include "mono/metadata/custom-attrs-internals.h"
20 #include "mono/metadata/sre-internals.h"
21 #include "mono/metadata/reflection-internals.h"
22 #include "mono/metadata/tabledefs.h"
23 #include "mono/metadata/tokentype.h"
24 #include "mono/metadata/verify-internals.h"
25 #include "mono/utils/checked-build.h"
28 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
29 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
31 #if SIZEOF_VOID_P == 4
32 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
34 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
37 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
38 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
40 static gboolean type_is_reference (MonoType *type);
42 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
43 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
46 * LOCKING: Acquires the loader lock.
48 static MonoCustomAttrInfo*
49 lookup_custom_attr (MonoImage *image, gpointer member)
51 MONO_REQ_GC_NEUTRAL_MODE;
53 MonoCustomAttrInfo* res;
55 res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
60 res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
66 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
68 MONO_REQ_GC_UNSAFE_MODE;
70 /* FIXME: Need to do more checks */
71 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
72 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
74 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
82 type_is_reference (MonoType *type)
85 case MONO_TYPE_BOOLEAN:
99 case MONO_TYPE_VALUETYPE:
107 free_param_data (MonoMethodSignature *sig, void **params) {
109 for (i = 0; i < sig->param_count; ++i) {
110 if (!type_is_reference (sig->params [i]))
116 * Find the field index in the metadata FieldDef table.
119 find_field_index (MonoClass *klass, MonoClassField *field) {
122 for (i = 0; i < klass->field.count; ++i) {
123 if (field == &klass->fields [i])
124 return klass->field.first + 1 + i;
130 * Find the property index in the metadata Property table.
133 find_property_index (MonoClass *klass, MonoProperty *property) {
136 for (i = 0; i < klass->ext->property.count; ++i) {
137 if (property == &klass->ext->properties [i])
138 return klass->ext->property.first + 1 + i;
144 * Find the event index in the metadata Event table.
147 find_event_index (MonoClass *klass, MonoEvent *event) {
150 for (i = 0; i < klass->ext->event.count; ++i) {
151 if (event == &klass->ext->events [i])
152 return klass->ext->event.first + 1 + i;
158 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
159 * The @is_enum flag only affects the error message that's displayed on failure.
162 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
164 MonoError inner_error;
165 MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
167 mono_error_set_type_load_name (error, g_strdup(n), NULL,
168 "Could not load %s %s while decoding custom attribute: %s",
169 is_enum ? "enum type": "type",
171 mono_error_get_message (&inner_error));
172 mono_error_cleanup (&inner_error);
179 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
183 int slen = mono_metadata_decode_value (p, &p);
185 mono_error_init (error);
187 n = (char *)g_memdup (p, slen + 1);
189 t = cattr_type_from_name (n, image, TRUE, error);
191 return_val_if_nok (error, NULL);
194 return mono_class_from_mono_type (t);
198 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
200 int slen, type = t->type;
201 MonoClass *tklass = t->data.klass;
203 mono_error_init (error);
209 case MONO_TYPE_BOOLEAN: {
210 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
218 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
223 #if SIZEOF_VOID_P == 4
230 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
235 #if SIZEOF_VOID_P == 8
236 case MONO_TYPE_U: /* error out instead? this should probably not happen */
241 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
247 double *val = (double *)g_malloc (sizeof (double));
252 case MONO_TYPE_VALUETYPE:
253 if (t->data.klass->enumtype) {
254 type = mono_class_enum_basetype (t->data.klass)->type;
257 MonoClass *k = t->data.klass;
259 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
260 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
266 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
269 case MONO_TYPE_STRING:
270 if (*p == (char)0xFF) {
274 slen = mono_metadata_decode_value (p, &p);
276 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
277 case MONO_TYPE_CLASS: {
278 MonoReflectionType *rt;
281 if (*p == (char)0xFF) {
286 slen = mono_metadata_decode_value (p, &p);
287 n = (char *)g_memdup (p, slen + 1);
289 t = cattr_type_from_name (n, image, FALSE, error);
291 return_val_if_nok (error, NULL);
294 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
295 if (!mono_error_ok (error))
300 case MONO_TYPE_OBJECT: {
303 MonoClass *subc = NULL;
308 } else if (subt == 0x0E) {
309 type = MONO_TYPE_STRING;
311 } else if (subt == 0x1D) {
312 MonoType simple_type = {{0}};
316 type = MONO_TYPE_SZARRAY;
318 tklass = mono_defaults.systemtype_class;
319 } else if (etype == 0x55) {
320 tklass = load_cattr_enum_type (image, p, &p, error);
321 if (!mono_error_ok (error))
325 /* See Partition II, Appendix B3 */
326 etype = MONO_TYPE_OBJECT;
327 simple_type.type = (MonoTypeEnum)etype;
328 tklass = mono_class_from_mono_type (&simple_type);
331 } else if (subt == 0x55) {
334 slen = mono_metadata_decode_value (p, &p);
335 n = (char *)g_memdup (p, slen + 1);
337 t = cattr_type_from_name (n, image, FALSE, error);
339 return_val_if_nok (error, NULL);
341 subc = mono_class_from_mono_type (t);
342 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
343 MonoType simple_type = {{0}};
344 simple_type.type = (MonoTypeEnum)subt;
345 subc = mono_class_from_mono_type (&simple_type);
347 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
349 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
351 if (mono_error_ok (error)) {
352 obj = mono_object_new_checked (mono_domain_get (), subc, error);
353 g_assert (!subc->has_references);
354 if (mono_error_ok (error))
355 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
361 case MONO_TYPE_SZARRAY: {
363 guint32 i, alen, basetype;
366 if (alen == 0xffffffff) {
370 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
371 return_val_if_nok (error, NULL);
372 basetype = tklass->byval_arg.type;
373 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
374 basetype = mono_class_enum_basetype (tklass)->type;
379 case MONO_TYPE_BOOLEAN:
380 for (i = 0; i < alen; i++) {
381 MonoBoolean val = *p++;
382 mono_array_set (arr, MonoBoolean, i, val);
388 for (i = 0; i < alen; i++) {
389 guint16 val = read16 (p);
390 mono_array_set (arr, guint16, i, val);
397 for (i = 0; i < alen; i++) {
398 guint32 val = read32 (p);
399 mono_array_set (arr, guint32, i, val);
404 for (i = 0; i < alen; i++) {
407 mono_array_set (arr, double, i, val);
413 for (i = 0; i < alen; i++) {
414 guint64 val = read64 (p);
415 mono_array_set (arr, guint64, i, val);
419 case MONO_TYPE_CLASS:
420 case MONO_TYPE_OBJECT:
421 case MONO_TYPE_STRING:
422 case MONO_TYPE_SZARRAY:
423 for (i = 0; i < alen; i++) {
424 MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
425 if (!mono_error_ok (error))
427 mono_array_setref (arr, i, item);
431 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
437 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
443 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
445 mono_error_init (error);
447 gboolean is_ref = type_is_reference (t);
449 void *val = load_cattr_value (image, t, p, end, error);
450 if (!is_ok (error)) {
457 return (MonoObject*)val;
459 MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
465 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
467 static MonoMethod *ctor;
469 void *params [2], *unboxed;
471 mono_error_init (error);
474 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
476 params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
477 return_val_if_nok (error, NULL);
480 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
481 return_val_if_nok (error, NULL);
482 unboxed = mono_object_unbox (retval);
484 mono_runtime_invoke_checked (ctor, unboxed, params, error);
485 return_val_if_nok (error, NULL);
491 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
493 static MonoMethod *ctor;
495 void *unboxed, *params [2];
497 mono_error_init (error);
500 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
503 params [1] = typedarg;
504 retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
505 return_val_if_nok (error, NULL);
507 unboxed = mono_object_unbox (retval);
509 mono_runtime_invoke_checked (ctor, unboxed, params, error);
510 return_val_if_nok (error, NULL);
517 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
519 MONO_REQ_GC_UNSAFE_MODE;
521 int i, index, count, not_visible;
522 MonoCustomAttrInfo *ainfo;
523 MonoReflectionCustomAttr *cattr;
527 /* FIXME: check in assembly the Run flag is set */
529 count = mono_array_length (cattrs);
531 /* Skip nonpublic attributes since MS.NET seems to do the same */
532 /* FIXME: This needs to be done more globally */
534 for (i = 0; i < count; ++i) {
535 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
536 if (!custom_attr_visible (image, cattr))
540 int num_attrs = count - not_visible;
541 ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
543 ainfo->image = image;
544 ainfo->num_attrs = num_attrs;
545 ainfo->cached = alloc_img != NULL;
547 for (i = 0; i < count; ++i) {
548 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
549 if (custom_attr_visible (image, cattr)) {
550 unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
551 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
552 ainfo->attrs [index].ctor = cattr->ctor->method;
553 g_assert (cattr->ctor->method);
554 ainfo->attrs [index].data = saved;
555 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
559 g_assert (index == num_attrs && count == num_attrs + not_visible);
566 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
568 const char *p = (const char*)data;
570 guint32 i, j, num_named;
572 void *params_buf [32];
573 void **params = NULL;
574 MonoMethodSignature *sig;
576 mono_error_init (error);
578 mono_class_init (method->klass);
580 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
581 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
586 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
587 if (!mono_error_ok (error)) return NULL;
589 mono_runtime_invoke_checked (method, attr, NULL, error);
590 if (!mono_error_ok (error))
596 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
599 /*g_print ("got attr %s\n", method->klass->name);*/
601 sig = mono_method_signature (method);
602 if (sig->param_count < 32) {
604 memset (params, 0, sizeof (void*) * sig->param_count);
606 /* Allocate using GC so it gets GC tracking */
607 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
612 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
613 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
614 if (!mono_error_ok (error))
619 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
620 if (!mono_error_ok (error)) goto fail;
622 MonoObject *exc = NULL;
623 mono_runtime_try_invoke (method, attr, params, &exc, error);
624 if (!mono_error_ok (error))
627 mono_error_set_exception_instance (error, (MonoException*)exc);
631 num_named = read16 (named);
633 for (j = 0; j < num_named; j++) {
635 char *name, named_type, data_type;
636 named_type = *named++;
637 data_type = *named++; /* type of data */
638 if (data_type == MONO_TYPE_SZARRAY)
639 data_type = *named++;
640 if (data_type == MONO_TYPE_ENUM) {
643 type_len = mono_metadata_decode_blob_size (named, &named);
644 type_name = (char *)g_malloc (type_len + 1);
645 memcpy (type_name, named, type_len);
646 type_name [type_len] = 0;
648 /* FIXME: lookup the type and check type consistency */
651 name_len = mono_metadata_decode_blob_size (named, &named);
652 name = (char *)g_malloc (name_len + 1);
653 memcpy (name, named, name_len);
656 if (named_type == 0x53) {
657 MonoClassField *field;
660 /* how this fail is a blackbox */
661 field = mono_class_get_field_from_name (mono_object_class (attr), name);
663 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
668 val = load_cattr_value (image, field->type, named, &named, error);
669 if (!mono_error_ok (error)) {
671 if (!type_is_reference (field->type))
676 mono_field_set_value (attr, field, val);
677 if (!type_is_reference (field->type))
679 } else if (named_type == 0x54) {
684 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
687 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
693 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
698 /* can we have more that 1 arg in a custom attr named property? */
699 prop_type = prop->get? mono_method_signature (prop->get)->ret :
700 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
702 pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
703 if (!mono_error_ok (error)) {
705 if (!type_is_reference (prop_type))
706 g_free (pparams [0]);
711 mono_property_set_value_checked (prop, attr, pparams, error);
712 if (!type_is_reference (prop_type))
713 g_free (pparams [0]);
714 if (!is_ok (error)) {
722 free_param_data (method->signature, params);
723 if (params != params_buf)
724 mono_gc_free_fixed (params);
729 free_param_data (method->signature, params);
730 if (params != params_buf)
731 mono_gc_free_fixed (params);
736 * mono_reflection_create_custom_attr_data_args:
738 * Create an array of typed and named arguments from the cattr blob given by DATA.
739 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
740 * NAMED_ARG_INFO will contain information about the named arguments.
743 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)
745 MonoArray *typedargs, *namedargs;
746 MonoClass *attrklass;
748 const char *p = (const char*)data;
750 guint32 i, j, num_named;
751 CattrNamedArg *arginfo = NULL;
755 *named_arg_info = NULL;
757 mono_error_init (error);
759 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
760 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
764 mono_class_init (method->klass);
766 domain = mono_domain_get ();
768 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
771 typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
772 return_if_nok (error);
776 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
779 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
780 return_if_nok (error);
781 mono_array_setref (typedargs, i, obj);
785 num_named = read16 (named);
786 namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
787 return_if_nok (error);
789 attrklass = method->klass;
791 arginfo = g_new0 (CattrNamedArg, num_named);
792 *named_arg_info = arginfo;
794 for (j = 0; j < num_named; j++) {
796 char *name, named_type, data_type;
797 named_type = *named++;
798 data_type = *named++; /* type of data */
799 if (data_type == MONO_TYPE_SZARRAY)
800 data_type = *named++;
801 if (data_type == MONO_TYPE_ENUM) {
804 type_len = mono_metadata_decode_blob_size (named, &named);
805 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
808 type_name = (char *)g_malloc (type_len + 1);
809 memcpy (type_name, named, type_len);
810 type_name [type_len] = 0;
812 /* FIXME: lookup the type and check type consistency */
815 name_len = mono_metadata_decode_blob_size (named, &named);
816 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
818 name = (char *)g_malloc (name_len + 1);
819 memcpy (name, named, name_len);
822 if (named_type == 0x53) {
824 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
831 arginfo [j].type = field->type;
832 arginfo [j].field = field;
834 obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
835 if (!is_ok (error)) {
839 mono_array_setref (namedargs, j, obj);
841 } else if (named_type == 0x54) {
844 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
846 if (!prop || !prop->set) {
851 prop_type = prop->get? mono_method_signature (prop->get)->ret :
852 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
854 arginfo [j].type = prop_type;
855 arginfo [j].prop = prop;
857 obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
858 if (!is_ok (error)) {
862 mono_array_setref (namedargs, j, obj);
867 *typed_args = typedargs;
868 *named_args = namedargs;
871 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
873 *named_arg_info = NULL;
877 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
880 MonoArray *typedargs, *namedargs;
883 CattrNamedArg *arginfo = NULL;
886 mono_error_init (error);
894 image = assembly->assembly->image;
895 method = ref_method->method;
896 domain = mono_object_domain (ref_method);
898 if (!mono_class_init (method->klass)) {
899 mono_error_set_for_class_failure (error, method->klass);
903 mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
907 if (!typedargs || !namedargs)
910 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
911 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
912 MonoObject *typedarg;
914 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
917 mono_array_setref (typedargs, i, typedarg);
920 for (i = 0; i < mono_array_length (namedargs); ++i) {
921 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
922 MonoObject *typedarg, *namedarg, *minfo;
924 if (arginfo [i].prop) {
925 minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
929 minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
934 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
937 namedarg = create_cattr_named_arg (minfo, typedarg, error);
941 mono_array_setref (namedargs, i, namedarg);
944 *ctor_args = typedargs;
945 *named_args = namedargs;
949 return mono_error_ok (error);
953 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
956 (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
957 mono_error_set_pending_exception (&error);
961 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
963 static MonoMethod *ctor;
969 mono_error_init (error);
971 g_assert (image->assembly);
974 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
976 domain = mono_domain_get ();
977 attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
978 return_val_if_nok (error, NULL);
979 params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
980 return_val_if_nok (error, NULL);
981 params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
982 return_val_if_nok (error, NULL);
983 params [2] = (gpointer)&cattr->data;
984 params [3] = &cattr->data_size;
986 mono_runtime_invoke_checked (ctor, attr, params, error);
987 return_val_if_nok (error, NULL);
992 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
998 mono_error_init (error);
1000 for (i = 0; i < cinfo->num_attrs; ++i) {
1001 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
1002 if (!centry->ctor) {
1003 /* The cattr type is not finished yet */
1004 /* We should include the type name but cinfo doesn't contain it */
1005 mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1012 for (i = 0; i < cinfo->num_attrs; ++i) {
1013 MonoMethod *ctor = cinfo->attrs[i].ctor;
1015 if (mono_class_is_assignable_from (attr_klass, ctor->klass))
1019 n = cinfo->num_attrs;
1022 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
1023 return_val_if_nok (error, NULL);
1025 for (i = 0; i < cinfo->num_attrs; ++i) {
1026 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
1027 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
1028 attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
1029 if (!mono_error_ok (error))
1031 mono_array_setref (result, n, attr);
1039 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
1042 MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
1043 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1049 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
1055 mono_error_init (error);
1056 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
1057 return_val_if_nok (error, NULL);
1058 for (i = 0; i < cinfo->num_attrs; ++i) {
1059 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
1060 return_val_if_nok (error, NULL);
1061 mono_array_setref (result, i, attr);
1067 * mono_custom_attrs_from_index:
1069 * Returns: NULL if no attributes are found or if a loading error occurs.
1072 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
1075 MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
1076 mono_error_cleanup (&error);
1080 * mono_custom_attrs_from_index_checked:
1082 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
1085 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
1087 guint32 mtoken, i, len;
1088 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1090 MonoCustomAttrInfo *ainfo;
1091 GList *tmp, *list = NULL;
1093 MonoCustomAttrEntry* attr;
1095 mono_error_init (error);
1097 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1099 i = mono_metadata_custom_attrs_from_index (image, idx);
1103 while (i < ca->rows) {
1104 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1106 list = g_list_prepend (list, GUINT_TO_POINTER (i));
1109 len = g_list_length (list);
1112 ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
1113 ainfo->num_attrs = len;
1114 ainfo->image = image;
1115 for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
1116 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
1117 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1118 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1119 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1120 mtoken |= MONO_TOKEN_METHOD_DEF;
1122 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1123 mtoken |= MONO_TOKEN_MEMBER_REF;
1126 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1129 attr = &ainfo->attrs [i - 1];
1130 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
1132 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
1138 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
1139 /*FIXME raising an exception here doesn't make any sense*/
1140 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
1145 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
1146 attr->data_size = mono_metadata_decode_value (data, &data);
1147 attr->data = (guchar*)data;
1155 mono_custom_attrs_from_method (MonoMethod *method)
1158 MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked (method, &error);
1159 mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
1164 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
1168 mono_error_init (error);
1171 * An instantiated method has the same cattrs as the generic method definition.
1173 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1174 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1176 if (method->is_inflated)
1177 method = ((MonoMethodInflated *) method)->declaring;
1179 if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
1180 return lookup_custom_attr (method->klass->image, method);
1183 /* Synthetic methods */
1186 idx = mono_method_get_index (method);
1187 idx <<= MONO_CUSTOM_ATTR_BITS;
1188 idx |= MONO_CUSTOM_ATTR_METHODDEF;
1189 return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
1193 mono_custom_attrs_from_class (MonoClass *klass)
1196 MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
1197 mono_error_cleanup (&error);
1202 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
1206 mono_error_init (error);
1208 if (klass->generic_class)
1209 klass = klass->generic_class->container_class;
1211 if (image_is_dynamic (klass->image))
1212 return lookup_custom_attr (klass->image, klass);
1214 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
1215 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
1216 idx <<= MONO_CUSTOM_ATTR_BITS;
1217 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
1219 idx = mono_metadata_token_index (klass->type_token);
1220 idx <<= MONO_CUSTOM_ATTR_BITS;
1221 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1223 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1227 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
1230 MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
1231 mono_error_cleanup (&error);
1236 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
1240 mono_error_init (error);
1242 if (image_is_dynamic (assembly->image))
1243 return lookup_custom_attr (assembly->image, assembly);
1244 idx = 1; /* there is only one assembly */
1245 idx <<= MONO_CUSTOM_ATTR_BITS;
1246 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1247 return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
1250 static MonoCustomAttrInfo*
1251 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
1255 if (image_is_dynamic (image))
1256 return lookup_custom_attr (image, image);
1257 idx = 1; /* there is only one module */
1258 idx <<= MONO_CUSTOM_ATTR_BITS;
1259 idx |= MONO_CUSTOM_ATTR_MODULE;
1260 return mono_custom_attrs_from_index_checked (image, idx, error);
1264 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
1267 MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
1268 mono_error_cleanup (&error);
1273 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
1277 if (image_is_dynamic (klass->image)) {
1278 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
1279 return lookup_custom_attr (klass->image, property);
1281 idx = find_property_index (klass, property);
1282 idx <<= MONO_CUSTOM_ATTR_BITS;
1283 idx |= MONO_CUSTOM_ATTR_PROPERTY;
1284 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1288 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
1291 MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
1292 mono_error_cleanup (&error);
1297 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
1301 if (image_is_dynamic (klass->image)) {
1302 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
1303 return lookup_custom_attr (klass->image, event);
1305 idx = find_event_index (klass, event);
1306 idx <<= MONO_CUSTOM_ATTR_BITS;
1307 idx |= MONO_CUSTOM_ATTR_EVENT;
1308 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1312 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
1315 MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
1316 mono_error_cleanup (&error);
1321 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
1324 mono_error_init (error);
1326 if (image_is_dynamic (klass->image)) {
1327 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
1328 return lookup_custom_attr (klass->image, field);
1330 idx = find_field_index (klass, field);
1331 idx <<= MONO_CUSTOM_ATTR_BITS;
1332 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1333 return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1337 * mono_custom_attrs_from_param:
1338 * @method: handle to the method that we want to retrieve custom parameter information from
1339 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1341 * The result must be released with mono_custom_attrs_free().
1343 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
1346 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
1349 MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
1350 mono_error_cleanup (&error);
1355 * mono_custom_attrs_from_param_checked:
1356 * @method: handle to the method that we want to retrieve custom parameter information from
1357 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1358 * @error: set on error
1360 * The result must be released with mono_custom_attrs_free().
1362 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
1365 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
1368 guint32 i, idx, method_index;
1369 guint32 param_list, param_last, param_pos, found;
1371 MonoReflectionMethodAux *aux;
1373 mono_error_init (error);
1376 * An instantiated method has the same cattrs as the generic method definition.
1378 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1379 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1381 if (method->is_inflated)
1382 method = ((MonoMethodInflated *) method)->declaring;
1384 if (image_is_dynamic (method->klass->image)) {
1385 MonoCustomAttrInfo *res, *ainfo;
1388 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1389 if (!aux || !aux->param_cattr)
1392 /* Need to copy since it will be freed later */
1393 ainfo = aux->param_cattr [param];
1396 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
1397 res = (MonoCustomAttrInfo *)g_malloc0 (size);
1398 memcpy (res, ainfo, size);
1402 image = method->klass->image;
1403 method_index = mono_method_get_index (method);
1406 ca = &image->tables [MONO_TABLE_METHOD];
1408 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
1409 if (method_index == ca->rows) {
1410 ca = &image->tables [MONO_TABLE_PARAM];
1411 param_last = ca->rows + 1;
1413 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
1414 ca = &image->tables [MONO_TABLE_PARAM];
1417 for (i = param_list; i < param_last; ++i) {
1418 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
1419 if (param_pos == param) {
1427 idx <<= MONO_CUSTOM_ATTR_BITS;
1428 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1429 return mono_custom_attrs_from_index_checked (image, idx, error);
1433 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1436 for (i = 0; i < ainfo->num_attrs; ++i) {
1437 MonoClass *klass = ainfo->attrs [i].ctor->klass;
1438 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
1445 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1448 MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
1449 mono_error_assert_ok (&error); /*FIXME proper error handling*/
1454 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
1457 MonoCustomAttrEntry *centry = NULL;
1459 g_assert (attr_klass != NULL);
1461 mono_error_init (error);
1463 for (i = 0; i < ainfo->num_attrs; ++i) {
1464 centry = &ainfo->attrs[i];
1465 if (centry->ctor == NULL)
1467 MonoClass *klass = centry->ctor->klass;
1468 if (mono_class_is_assignable_from (attr_klass, klass))
1474 return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
1478 * mono_reflection_get_custom_attrs_info:
1479 * @obj: a reflection object handle
1481 * Return the custom attribute info for attributes defined for the
1482 * reflection handle @obj. The objects.
1484 * FIXME this function leaks like a sieve for SRE objects.
1487 mono_reflection_get_custom_attrs_info (MonoObject *obj)
1490 MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
1491 mono_error_assert_ok (&error);
1496 * mono_reflection_get_custom_attrs_info_checked:
1497 * @obj: a reflection object handle
1498 * @error: set on error
1500 * Return the custom attribute info for attributes defined for the
1501 * reflection handle @obj. The objects.
1503 * On failure returns NULL and sets @error.
1505 * FIXME this function leaks like a sieve for SRE objects.
1508 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
1511 MonoCustomAttrInfo *cinfo = NULL;
1513 mono_error_init (error);
1515 klass = obj->vtable->klass;
1516 if (klass == mono_defaults.runtimetype_class) {
1517 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1518 return_val_if_nok (error, NULL);
1519 klass = mono_class_from_mono_type (type);
1520 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1521 cinfo = mono_custom_attrs_from_class_checked (klass, error);
1522 return_val_if_nok (error, NULL);
1523 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
1524 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
1525 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
1526 return_val_if_nok (error, NULL);
1527 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
1528 MonoReflectionModule *module = (MonoReflectionModule*)obj;
1529 cinfo = mono_custom_attrs_from_module (module->image, error);
1530 return_val_if_nok (error, NULL);
1531 } else if (strcmp ("MonoProperty", klass->name) == 0) {
1532 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
1533 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
1534 return_val_if_nok (error, NULL);
1535 } else if (strcmp ("MonoEvent", klass->name) == 0) {
1536 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
1537 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
1538 return_val_if_nok (error, NULL);
1539 } else if (strcmp ("MonoField", klass->name) == 0) {
1540 MonoReflectionField *rfield = (MonoReflectionField*)obj;
1541 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
1542 return_val_if_nok (error, NULL);
1543 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
1544 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
1545 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
1546 return_val_if_nok (error, NULL);
1547 } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
1548 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
1549 MonoClass *member_class = mono_object_class (param->MemberImpl);
1550 if (mono_class_is_reflection_method_or_constructor (member_class)) {
1551 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
1552 cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
1553 return_val_if_nok (error, NULL);
1554 } else if (mono_is_sr_mono_property (member_class)) {
1555 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
1557 if (!(method = prop->property->get))
1558 method = prop->property->set;
1561 cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
1562 return_val_if_nok (error, NULL);
1564 #ifndef DISABLE_REFLECTION_EMIT
1565 else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
1566 // FIXME: Is this still needed ?
1567 g_assert_not_reached ();
1568 } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
1569 // FIXME: Is this still needed ?
1570 g_assert_not_reached ();
1574 char *type_name = mono_type_get_full_name (member_class);
1575 mono_error_set_not_supported (error,
1576 "Custom attributes on a ParamInfo with member %s are not supported",
1581 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
1582 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
1583 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
1584 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
1585 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
1586 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
1587 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
1588 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
1589 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
1590 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
1591 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
1592 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
1593 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
1594 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
1595 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
1596 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
1597 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
1598 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
1599 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
1600 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
1601 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
1602 return_val_if_nok (error, NULL);
1603 } else { /* handle other types here... */
1604 g_error ("get custom attrs not yet supported for %s", klass->name);
1611 * mono_reflection_get_custom_attrs_by_type:
1612 * @obj: a reflection object handle
1614 * Return an array with all the custom attributes defined of the
1615 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
1616 * of that type are returned. The objects are fully build. Return NULL if a loading error
1620 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
1623 MonoCustomAttrInfo *cinfo;
1625 mono_error_init (error);
1627 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1628 return_val_if_nok (error, NULL);
1630 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
1632 mono_custom_attrs_free (cinfo);
1636 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
1643 * mono_reflection_get_custom_attrs:
1644 * @obj: a reflection object handle
1646 * Return an array with all the custom attributes defined of the
1647 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
1651 mono_reflection_get_custom_attrs (MonoObject *obj)
1655 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
1659 * mono_reflection_get_custom_attrs_data:
1660 * @obj: a reflection obj handle
1662 * Returns an array of System.Reflection.CustomAttributeData,
1663 * which include information about attributes reflected on
1664 * types loaded using the Reflection Only methods
1667 mono_reflection_get_custom_attrs_data (MonoObject *obj)
1671 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
1672 mono_error_cleanup (&error);
1677 * mono_reflection_get_custom_attrs_data_checked:
1678 * @obj: a reflection obj handle
1679 * @error: set on error
1681 * Returns an array of System.Reflection.CustomAttributeData,
1682 * which include information about attributes reflected on
1683 * types loaded using the Reflection Only methods
1686 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
1689 MonoCustomAttrInfo *cinfo;
1691 mono_error_init (error);
1693 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1694 return_val_if_nok (error, NULL);
1696 result = mono_custom_attrs_data_construct (cinfo, error);
1698 mono_custom_attrs_free (cinfo);
1699 return_val_if_nok (error, NULL);
1701 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);