[runtime] Move MonoClass::generic_class to MonoClassGenericInst.
[mono.git] / mono / metadata / custom-attrs.c
1 /*
2  * custom-attrs.c: Custom attributes.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
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
11  *
12  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13  */
14 #include <config.h>
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"
26
27
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))
30
31 #if SIZEOF_VOID_P == 4
32 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
33 #else
34 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
35 #endif
36
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))
39
40 static gboolean type_is_reference (MonoType *type);
41
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);
44
45 /*
46  * LOCKING: Acquires the loader lock. 
47  */
48 static MonoCustomAttrInfo*
49 lookup_custom_attr (MonoImage *image, gpointer member)
50 {
51         MONO_REQ_GC_NEUTRAL_MODE;
52
53         MonoCustomAttrInfo* res;
54
55         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
56
57         if (!res)
58                 return NULL;
59
60         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
61         res->cached = 0;
62         return res;
63 }
64
65 static gboolean
66 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
67 {
68         MONO_REQ_GC_UNSAFE_MODE;
69
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;
73
74                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
75                         return FALSE;
76         }
77
78         return TRUE;
79 }
80
81 static gboolean
82 type_is_reference (MonoType *type)
83 {
84         switch (type->type) {
85         case MONO_TYPE_BOOLEAN:
86         case MONO_TYPE_CHAR:
87         case MONO_TYPE_U:
88         case MONO_TYPE_I:
89         case MONO_TYPE_U1:
90         case MONO_TYPE_I1:
91         case MONO_TYPE_U2:
92         case MONO_TYPE_I2:
93         case MONO_TYPE_U4:
94         case MONO_TYPE_I4:
95         case MONO_TYPE_U8:
96         case MONO_TYPE_I8:
97         case MONO_TYPE_R8:
98         case MONO_TYPE_R4:
99         case MONO_TYPE_VALUETYPE:
100                 return FALSE;
101         default:
102                 return TRUE;
103         }
104 }
105
106 static void
107 free_param_data (MonoMethodSignature *sig, void **params) {
108         int i;
109         for (i = 0; i < sig->param_count; ++i) {
110                 if (!type_is_reference (sig->params [i]))
111                         g_free (params [i]);
112         }
113 }
114
115 /*
116  * Find the field index in the metadata FieldDef table.
117  */
118 static guint32
119 find_field_index (MonoClass *klass, MonoClassField *field) {
120         int i;
121
122         for (i = 0; i < klass->field.count; ++i) {
123                 if (field == &klass->fields [i])
124                         return klass->field.first + 1 + i;
125         }
126         return 0;
127 }
128
129 /*
130  * Find the property index in the metadata Property table.
131  */
132 static guint32
133 find_property_index (MonoClass *klass, MonoProperty *property) {
134         int i;
135
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;
139         }
140         return 0;
141 }
142
143 /*
144  * Find the event index in the metadata Event table.
145  */
146 static guint32
147 find_event_index (MonoClass *klass, MonoEvent *event) {
148         int i;
149
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;
153         }
154         return 0;
155 }
156
157 /*
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.
160  */
161 static MonoType*
162 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
163 {
164         MonoError inner_error;
165         MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
166         if (!t) {
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",
170                                                n,
171                                                mono_error_get_message (&inner_error));
172                 mono_error_cleanup (&inner_error);
173                 return NULL;
174         }
175         return t;
176 }
177
178 static MonoClass*
179 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
180 {
181         char *n;
182         MonoType *t;
183         int slen = mono_metadata_decode_value (p, &p);
184
185         mono_error_init (error);
186
187         n = (char *)g_memdup (p, slen + 1);
188         n [slen] = 0;
189         t = cattr_type_from_name (n, image, TRUE, error);
190         g_free (n);
191         return_val_if_nok (error, NULL);
192         p += slen;
193         *end = p;
194         return mono_class_from_mono_type (t);
195 }
196
197 static void*
198 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
199 {
200         int slen, type = t->type;
201         MonoClass *tklass = t->data.klass;
202
203         mono_error_init (error);
204
205 handle_enum:
206         switch (type) {
207         case MONO_TYPE_U1:
208         case MONO_TYPE_I1:
209         case MONO_TYPE_BOOLEAN: {
210                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
211                 *bval = *p;
212                 *end = p + 1;
213                 return bval;
214         }
215         case MONO_TYPE_CHAR:
216         case MONO_TYPE_U2:
217         case MONO_TYPE_I2: {
218                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
219                 *val = read16 (p);
220                 *end = p + 2;
221                 return val;
222         }
223 #if SIZEOF_VOID_P == 4
224         case MONO_TYPE_U:
225         case MONO_TYPE_I:
226 #endif
227         case MONO_TYPE_R4:
228         case MONO_TYPE_U4:
229         case MONO_TYPE_I4: {
230                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
231                 *val = read32 (p);
232                 *end = p + 4;
233                 return val;
234         }
235 #if SIZEOF_VOID_P == 8
236         case MONO_TYPE_U: /* error out instead? this should probably not happen */
237         case MONO_TYPE_I:
238 #endif
239         case MONO_TYPE_U8:
240         case MONO_TYPE_I8: {
241                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
242                 *val = read64 (p);
243                 *end = p + 8;
244                 return val;
245         }
246         case MONO_TYPE_R8: {
247                 double *val = (double *)g_malloc (sizeof (double));
248                 readr8 (p, val);
249                 *end = p + 8;
250                 return val;
251         }
252         case MONO_TYPE_VALUETYPE:
253                 if (t->data.klass->enumtype) {
254                         type = mono_class_enum_basetype (t->data.klass)->type;
255                         goto handle_enum;
256                 } else {
257                         MonoClass *k =  t->data.klass;
258                         
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));
261                                 *val = read64 (p);
262                                 *end = p + 8;
263                                 return val;
264                         }
265                 }
266                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
267                 break;
268                 
269         case MONO_TYPE_STRING:
270                 if (*p == (char)0xFF) {
271                         *end = p + 1;
272                         return NULL;
273                 }
274                 slen = mono_metadata_decode_value (p, &p);
275                 *end = p + slen;
276                 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
277         case MONO_TYPE_CLASS: {
278                 MonoReflectionType *rt;
279                 char *n;
280                 MonoType *t;
281                 if (*p == (char)0xFF) {
282                         *end = p + 1;
283                         return NULL;
284                 }
285 handle_type:
286                 slen = mono_metadata_decode_value (p, &p);
287                 n = (char *)g_memdup (p, slen + 1);
288                 n [slen] = 0;
289                 t = cattr_type_from_name (n, image, FALSE, error);
290                 g_free (n);
291                 return_val_if_nok (error, NULL);
292                 *end = p + slen;
293
294                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
295                 if (!mono_error_ok (error))
296                         return NULL;
297
298                 return rt;
299         }
300         case MONO_TYPE_OBJECT: {
301                 char subt = *p++;
302                 MonoObject *obj;
303                 MonoClass *subc = NULL;
304                 void *val;
305
306                 if (subt == 0x50) {
307                         goto handle_type;
308                 } else if (subt == 0x0E) {
309                         type = MONO_TYPE_STRING;
310                         goto handle_enum;
311                 } else if (subt == 0x1D) {
312                         MonoType simple_type = {{0}};
313                         int etype = *p;
314                         p ++;
315
316                         type = MONO_TYPE_SZARRAY;
317                         if (etype == 0x50) {
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))
322                                         return NULL;
323                         } else {
324                                 if (etype == 0x51)
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);
329                         }
330                         goto handle_enum;
331                 } else if (subt == 0x55) {
332                         char *n;
333                         MonoType *t;
334                         slen = mono_metadata_decode_value (p, &p);
335                         n = (char *)g_memdup (p, slen + 1);
336                         n [slen] = 0;
337                         t = cattr_type_from_name (n, image, FALSE, error);
338                         g_free (n);
339                         return_val_if_nok (error, NULL);
340                         p += slen;
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);
346                 } else {
347                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
348                 }
349                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
350                 obj = NULL;
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));
356                 }
357
358                 g_free (val);
359                 return obj;
360         }
361         case MONO_TYPE_SZARRAY: {
362                 MonoArray *arr;
363                 guint32 i, alen, basetype;
364                 alen = read32 (p);
365                 p += 4;
366                 if (alen == 0xffffffff) {
367                         *end = p;
368                         return NULL;
369                 }
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;
375                 switch (basetype)
376                 {
377                         case MONO_TYPE_U1:
378                         case MONO_TYPE_I1:
379                         case MONO_TYPE_BOOLEAN:
380                                 for (i = 0; i < alen; i++) {
381                                         MonoBoolean val = *p++;
382                                         mono_array_set (arr, MonoBoolean, i, val);
383                                 }
384                                 break;
385                         case MONO_TYPE_CHAR:
386                         case MONO_TYPE_U2:
387                         case MONO_TYPE_I2:
388                                 for (i = 0; i < alen; i++) {
389                                         guint16 val = read16 (p);
390                                         mono_array_set (arr, guint16, i, val);
391                                         p += 2;
392                                 }
393                                 break;
394                         case MONO_TYPE_R4:
395                         case MONO_TYPE_U4:
396                         case MONO_TYPE_I4:
397                                 for (i = 0; i < alen; i++) {
398                                         guint32 val = read32 (p);
399                                         mono_array_set (arr, guint32, i, val);
400                                         p += 4;
401                                 }
402                                 break;
403                         case MONO_TYPE_R8:
404                                 for (i = 0; i < alen; i++) {
405                                         double val;
406                                         readr8 (p, &val);
407                                         mono_array_set (arr, double, i, val);
408                                         p += 8;
409                                 }
410                                 break;
411                         case MONO_TYPE_U8:
412                         case MONO_TYPE_I8:
413                                 for (i = 0; i < alen; i++) {
414                                         guint64 val = read64 (p);
415                                         mono_array_set (arr, guint64, i, val);
416                                         p += 8;
417                                 }
418                                 break;
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))
426                                                 return NULL;
427                                         mono_array_setref (arr, i, item);
428                                 }
429                                 break;
430                         default:
431                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
432                 }
433                 *end=p;
434                 return arr;
435         }
436         default:
437                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
438         }
439         return NULL;
440 }
441
442 static MonoObject*
443 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
444 {
445         mono_error_init (error);
446
447         gboolean is_ref = type_is_reference (t);
448
449         void *val = load_cattr_value (image, t, p, end, error);
450         if (!is_ok (error)) {
451                 if (is_ref)
452                         g_free (val);
453                 return NULL;
454         }
455
456         if (is_ref)
457                 return (MonoObject*)val;
458
459         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
460         g_free (val);
461         return boxed;
462 }
463
464 static MonoObject*
465 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
466 {
467         static MonoMethod *ctor;
468         MonoObject *retval;
469         void *params [2], *unboxed;
470
471         mono_error_init (error);
472
473         if (!ctor)
474                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
475         
476         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
477         return_val_if_nok (error, NULL);
478
479         params [1] = val;
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);
483
484         mono_runtime_invoke_checked (ctor, unboxed, params, error);
485         return_val_if_nok (error, NULL);
486
487         return retval;
488 }
489
490 static MonoObject*
491 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
492 {
493         static MonoMethod *ctor;
494         MonoObject *retval;
495         void *unboxed, *params [2];
496
497         mono_error_init (error);
498
499         if (!ctor)
500                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
501
502         params [0] = minfo;
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);
506
507         unboxed = mono_object_unbox (retval);
508
509         mono_runtime_invoke_checked (ctor, unboxed, params, error);
510         return_val_if_nok (error, NULL);
511
512         return retval;
513 }
514
515
516 MonoCustomAttrInfo*
517 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
518 {
519         MONO_REQ_GC_UNSAFE_MODE;
520
521         int i, index, count, not_visible;
522         MonoCustomAttrInfo *ainfo;
523         MonoReflectionCustomAttr *cattr;
524
525         if (!cattrs)
526                 return NULL;
527         /* FIXME: check in assembly the Run flag is set */
528
529         count = mono_array_length (cattrs);
530
531         /* Skip nonpublic attributes since MS.NET seems to do the same */
532         /* FIXME: This needs to be done more globally */
533         not_visible = 0;
534         for (i = 0; i < count; ++i) {
535                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
536                 if (!custom_attr_visible (image, cattr))
537                         not_visible ++;
538         }
539
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);
542
543         ainfo->image = image;
544         ainfo->num_attrs = num_attrs;
545         ainfo->cached = alloc_img != NULL;
546         index = 0;
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);
556                         index ++;
557                 }
558         }
559         g_assert (index == num_attrs && count == num_attrs + not_visible);
560
561         return ainfo;
562 }
563
564
565 static MonoObject*
566 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
567 {
568         const char *p = (const char*)data;
569         const char *named;
570         guint32 i, j, num_named;
571         MonoObject *attr;
572         void *params_buf [32];
573         void **params = NULL;
574         MonoMethodSignature *sig;
575
576         mono_error_init (error);
577
578         mono_class_init (method->klass);
579
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.");
582                 return NULL;
583         }
584
585         if (len == 0) {
586                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
587                 if (!mono_error_ok (error)) return NULL;
588
589                 mono_runtime_invoke_checked (method, attr, NULL, error);
590                 if (!mono_error_ok (error))
591                         return NULL;
592
593                 return attr;
594         }
595
596         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
597                 return NULL;
598
599         /*g_print ("got attr %s\n", method->klass->name);*/
600
601         sig = mono_method_signature (method);
602         if (sig->param_count < 32) {
603                 params = params_buf;
604                 memset (params, 0, sizeof (void*) * sig->param_count);
605         } else {
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");
608         }
609
610         /* skip prolog */
611         p += 2;
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))
615                         goto fail;
616         }
617
618         named = p;
619         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
620         if (!mono_error_ok (error)) goto fail;
621
622         MonoObject *exc = NULL;
623         mono_runtime_try_invoke (method, attr, params, &exc, error);
624         if (!mono_error_ok (error))
625                 goto fail;
626         if (exc) {
627                 mono_error_set_exception_instance (error, (MonoException*)exc);
628                 goto fail;
629         }
630
631         num_named = read16 (named);
632         named += 2;
633         for (j = 0; j < num_named; j++) {
634                 gint name_len;
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) {
641                         gint type_len;
642                         char *type_name;
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;
647                         named += type_len;
648                         /* FIXME: lookup the type and check type consistency */
649                         g_free (type_name);
650                 }
651                 name_len = mono_metadata_decode_blob_size (named, &named);
652                 name = (char *)g_malloc (name_len + 1);
653                 memcpy (name, named, name_len);
654                 name [name_len] = 0;
655                 named += name_len;
656                 if (named_type == 0x53) {
657                         MonoClassField *field;
658                         void *val;
659
660                         /* how this fail is a blackbox */
661                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
662                         if (!field) {
663                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
664                                 g_free (name);
665                                 goto fail;
666                         }
667
668                         val = load_cattr_value (image, field->type, named, &named, error);
669                         if (!mono_error_ok (error)) {
670                                 g_free (name);
671                                 if (!type_is_reference (field->type))
672                                         g_free (val);
673                                 goto fail;
674                         }
675
676                         mono_field_set_value (attr, field, val);
677                         if (!type_is_reference (field->type))
678                                 g_free (val);
679                 } else if (named_type == 0x54) {
680                         MonoProperty *prop;
681                         void *pparams [1];
682                         MonoType *prop_type;
683
684                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
685
686                         if (!prop) {
687                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
688                                 g_free (name);
689                                 goto fail;
690                         }
691
692                         if (!prop->set) {
693                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
694                                 g_free (name);
695                                 goto fail;
696                         }
697
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];
701
702                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
703                         if (!mono_error_ok (error)) {
704                                 g_free (name);
705                                 if (!type_is_reference (prop_type))
706                                         g_free (pparams [0]);
707                                 goto fail;
708                         }
709
710
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)) {
715                                 g_free (name);
716                                 goto fail;
717                         }
718                 }
719                 g_free (name);
720         }
721
722         free_param_data (method->signature, params);
723         if (params != params_buf)
724                 mono_gc_free_fixed (params);
725
726         return attr;
727
728 fail:
729         free_param_data (method->signature, params);
730         if (params != params_buf)
731                 mono_gc_free_fixed (params);
732         return NULL;
733 }
734         
735 /*
736  * mono_reflection_create_custom_attr_data_args:
737  *
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.
741  */
742 void
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)
744 {
745         MonoArray *typedargs, *namedargs;
746         MonoClass *attrklass;
747         MonoDomain *domain;
748         const char *p = (const char*)data;
749         const char *named;
750         guint32 i, j, num_named;
751         CattrNamedArg *arginfo = NULL;
752
753         *typed_args = NULL;
754         *named_args = NULL;
755         *named_arg_info = NULL;
756
757         mono_error_init (error);
758
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.");
761                 return;
762         }
763
764         mono_class_init (method->klass);
765         
766         domain = mono_domain_get ();
767
768         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
769                 return;
770
771         typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
772         return_if_nok (error);
773
774         /* skip prolog */
775         p += 2;
776         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
777                 MonoObject *obj;
778
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);
782         }
783
784         named = p;
785         num_named = read16 (named);
786         namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
787         return_if_nok (error);
788         named += 2;
789         attrklass = method->klass;
790
791         arginfo = g_new0 (CattrNamedArg, num_named);
792         *named_arg_info = arginfo;
793
794         for (j = 0; j < num_named; j++) {
795                 gint name_len;
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) {
802                         gint type_len;
803                         char *type_name;
804                         type_len = mono_metadata_decode_blob_size (named, &named);
805                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
806                                 goto fail;
807
808                         type_name = (char *)g_malloc (type_len + 1);
809                         memcpy (type_name, named, type_len);
810                         type_name [type_len] = 0;
811                         named += type_len;
812                         /* FIXME: lookup the type and check type consistency */
813                         g_free (type_name);
814                 }
815                 name_len = mono_metadata_decode_blob_size (named, &named);
816                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
817                         goto fail;
818                 name = (char *)g_malloc (name_len + 1);
819                 memcpy (name, named, name_len);
820                 name [name_len] = 0;
821                 named += name_len;
822                 if (named_type == 0x53) {
823                         MonoObject *obj;
824                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
825
826                         if (!field) {
827                                 g_free (name);
828                                 goto fail;
829                         }
830
831                         arginfo [j].type = field->type;
832                         arginfo [j].field = field;
833
834                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
835                         if (!is_ok (error)) {
836                                 g_free (name);
837                                 return;
838                         }
839                         mono_array_setref (namedargs, j, obj);
840
841                 } else if (named_type == 0x54) {
842                         MonoObject *obj;
843                         MonoType *prop_type;
844                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
845
846                         if (!prop || !prop->set) {
847                                 g_free (name);
848                                 goto fail;
849                         }
850
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];
853
854                         arginfo [j].type = prop_type;
855                         arginfo [j].prop = prop;
856
857                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
858                         if (!is_ok (error)) {
859                                 g_free (name);
860                                 return;
861                         }
862                         mono_array_setref (namedargs, j, obj);
863                 }
864                 g_free (name);
865         }
866
867         *typed_args = typedargs;
868         *named_args = namedargs;
869         return;
870 fail:
871         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
872         g_free (arginfo);
873         *named_arg_info = NULL;
874 }
875
876 static gboolean
877 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
878 {
879         MonoDomain *domain;
880         MonoArray *typedargs, *namedargs;
881         MonoImage *image;
882         MonoMethod *method;
883         CattrNamedArg *arginfo = NULL;
884         int i;
885
886         mono_error_init (error);
887
888         *ctor_args = NULL;
889         *named_args = NULL;
890
891         if (len == 0)
892                 return TRUE;
893
894         image = assembly->assembly->image;
895         method = ref_method->method;
896         domain = mono_object_domain (ref_method);
897
898         if (!mono_class_init (method->klass)) {
899                 mono_error_set_for_class_failure (error, method->klass);
900                 goto leave;
901         }
902
903         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
904         if (!is_ok (error))
905                 goto leave;
906
907         if (!typedargs || !namedargs)
908                 goto leave;
909
910         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
911                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
912                 MonoObject *typedarg;
913
914                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
915                 if (!is_ok (error))
916                         goto leave;
917                 mono_array_setref (typedargs, i, typedarg);
918         }
919
920         for (i = 0; i < mono_array_length (namedargs); ++i) {
921                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
922                 MonoObject *typedarg, *namedarg, *minfo;
923
924                 if (arginfo [i].prop) {
925                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
926                         if (!minfo)
927                                 goto leave;
928                 } else {
929                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
930                         if (!is_ok (error))
931                                 goto leave;
932                 }
933
934                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
935                 if (!is_ok (error))
936                         goto leave;
937                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
938                 if (!is_ok (error))
939                         goto leave;
940
941                 mono_array_setref (namedargs, i, namedarg);
942         }
943
944         *ctor_args = typedargs;
945         *named_args = namedargs;
946
947 leave:
948         g_free (arginfo);
949         return mono_error_ok (error);
950 }
951
952 void
953 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
954 {
955         MonoError error;
956         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
957         mono_error_set_pending_exception (&error);
958 }
959
960 static MonoObject*
961 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
962 {
963         static MonoMethod *ctor;
964
965         MonoDomain *domain;
966         MonoObject *attr;
967         void *params [4];
968
969         mono_error_init (error);
970
971         g_assert (image->assembly);
972
973         if (!ctor)
974                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
975
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;
985
986         mono_runtime_invoke_checked (ctor, attr, params, error);
987         return_val_if_nok (error, NULL);
988         return attr;
989 }
990
991 static MonoArray*
992 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
993 {
994         MonoArray *result;
995         MonoObject *attr;
996         int i, n;
997
998         mono_error_init (error);
999
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.");
1006                         return NULL;
1007                 }
1008         }
1009
1010         n = 0;
1011         if (attr_klass) {
1012                 for (i = 0; i < cinfo->num_attrs; ++i) {
1013                         MonoMethod *ctor = cinfo->attrs[i].ctor;
1014                         g_assert (ctor);
1015                         if (mono_class_is_assignable_from (attr_klass, ctor->klass))
1016                                 n++;
1017                 }
1018         } else {
1019                 n = cinfo->num_attrs;
1020         }
1021
1022         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
1023         return_val_if_nok (error, NULL);
1024         n = 0;
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))
1030                                 return result;
1031                         mono_array_setref (result, n, attr);
1032                         n ++;
1033                 }
1034         }
1035         return result;
1036 }
1037
1038 MonoArray*
1039 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
1040 {
1041         MonoError error;
1042         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
1043         mono_error_assert_ok (&error); /*FIXME proper error handling*/
1044
1045         return result;
1046 }
1047
1048 static MonoArray*
1049 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
1050 {
1051         MonoArray *result;
1052         MonoObject *attr;
1053         int i;
1054         
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);
1062         }
1063         return result;
1064 }
1065
1066 /**
1067  * mono_custom_attrs_from_index:
1068  *
1069  * Returns: NULL if no attributes are found or if a loading error occurs.
1070  */
1071 MonoCustomAttrInfo*
1072 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
1073 {
1074         MonoError error;
1075         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, FALSE, &error);
1076         mono_error_cleanup (&error);
1077         return result;
1078 }
1079 /**
1080  * mono_custom_attrs_from_index_checked:
1081  *
1082  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
1083  */
1084 MonoCustomAttrInfo*
1085 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error)
1086 {
1087         guint32 mtoken, i, len;
1088         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1089         MonoTableInfo *ca;
1090         MonoCustomAttrInfo *ainfo;
1091         GList *tmp, *list = NULL;
1092         const char *data;
1093         MonoCustomAttrEntry* attr;
1094
1095         mono_error_init (error);
1096
1097         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1098
1099         i = mono_metadata_custom_attrs_from_index (image, idx);
1100         if (!i)
1101                 return NULL;
1102         i --;
1103         while (i < ca->rows) {
1104                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1105                         break;
1106                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
1107                 ++i;
1108         }
1109         len = g_list_length (list);
1110         if (!len)
1111                 return NULL;
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;
1121                         break;
1122                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1123                         mtoken |= MONO_TOKEN_MEMBER_REF;
1124                         break;
1125                 default:
1126                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1127                         break;
1128                 }
1129                 attr = &ainfo->attrs [i - 1];
1130                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
1131                 if (!attr->ctor) {
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));
1133                         if (ignore_missing) {
1134                                 mono_error_cleanup (error);
1135                                 mono_error_init (error);
1136                         } else {
1137                                 g_list_free (list);
1138                                 g_free (ainfo);
1139                                 return NULL;
1140                         }
1141                 }
1142
1143                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
1144                         /*FIXME raising an exception here doesn't make any sense*/
1145                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
1146                         g_list_free (list);
1147                         g_free (ainfo);
1148                         return NULL;
1149                 }
1150                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
1151                 attr->data_size = mono_metadata_decode_value (data, &data);
1152                 attr->data = (guchar*)data;
1153         }
1154         g_list_free (list);
1155
1156         return ainfo;
1157 }
1158
1159 MonoCustomAttrInfo*
1160 mono_custom_attrs_from_method (MonoMethod *method)
1161 {
1162         MonoError error;
1163         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
1164         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
1165         return result;
1166 }
1167
1168 MonoCustomAttrInfo*
1169 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
1170 {
1171         guint32 idx;
1172
1173         mono_error_init (error);
1174
1175         /*
1176          * An instantiated method has the same cattrs as the generic method definition.
1177          *
1178          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1179          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1180          */
1181         if (method->is_inflated)
1182                 method = ((MonoMethodInflated *) method)->declaring;
1183         
1184         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
1185                 return lookup_custom_attr (method->klass->image, method);
1186
1187         if (!method->token)
1188                 /* Synthetic methods */
1189                 return NULL;
1190
1191         idx = mono_method_get_index (method);
1192         idx <<= MONO_CUSTOM_ATTR_BITS;
1193         idx |= MONO_CUSTOM_ATTR_METHODDEF;
1194         return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error);
1195 }
1196
1197 MonoCustomAttrInfo*
1198 mono_custom_attrs_from_class (MonoClass *klass)
1199 {
1200         MonoError error;
1201         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
1202         mono_error_cleanup (&error);
1203         return result;
1204 }
1205
1206 MonoCustomAttrInfo*
1207 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
1208 {
1209         guint32 idx;
1210
1211         mono_error_init (error);
1212
1213         if (mono_class_is_ginst (klass))
1214                 klass = mono_class_get_generic_class (klass)->container_class;
1215
1216         if (image_is_dynamic (klass->image))
1217                 return lookup_custom_attr (klass->image, klass);
1218
1219         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
1220                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
1221                 idx <<= MONO_CUSTOM_ATTR_BITS;
1222                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
1223         } else {
1224                 idx = mono_metadata_token_index (klass->type_token);
1225                 idx <<= MONO_CUSTOM_ATTR_BITS;
1226                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1227         }
1228         return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1229 }
1230
1231 MonoCustomAttrInfo*
1232 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
1233 {
1234         MonoError error;
1235         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, FALSE, &error);
1236         mono_error_cleanup (&error);
1237         return result;
1238 }
1239
1240 MonoCustomAttrInfo*
1241 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore_missing, MonoError *error)
1242 {
1243         guint32 idx;
1244         
1245         mono_error_init (error);
1246
1247         if (image_is_dynamic (assembly->image))
1248                 return lookup_custom_attr (assembly->image, assembly);
1249         idx = 1; /* there is only one assembly */
1250         idx <<= MONO_CUSTOM_ATTR_BITS;
1251         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1252         return mono_custom_attrs_from_index_checked (assembly->image, idx, ignore_missing, error);
1253 }
1254
1255 static MonoCustomAttrInfo*
1256 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
1257 {
1258         guint32 idx;
1259         
1260         if (image_is_dynamic (image))
1261                 return lookup_custom_attr (image, image);
1262         idx = 1; /* there is only one module */
1263         idx <<= MONO_CUSTOM_ATTR_BITS;
1264         idx |= MONO_CUSTOM_ATTR_MODULE;
1265         return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1266 }
1267
1268 MonoCustomAttrInfo*
1269 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
1270 {
1271         MonoError error;
1272         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
1273         mono_error_cleanup (&error);
1274         return result;
1275 }
1276
1277 MonoCustomAttrInfo*
1278 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
1279 {
1280         guint32 idx;
1281         
1282         if (image_is_dynamic (klass->image)) {
1283                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
1284                 return lookup_custom_attr (klass->image, property);
1285         }
1286         idx = find_property_index (klass, property);
1287         idx <<= MONO_CUSTOM_ATTR_BITS;
1288         idx |= MONO_CUSTOM_ATTR_PROPERTY;
1289         return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1290 }
1291
1292 MonoCustomAttrInfo*
1293 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
1294 {
1295         MonoError error;
1296         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
1297         mono_error_cleanup (&error);
1298         return result;
1299 }
1300
1301 MonoCustomAttrInfo*
1302 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
1303 {
1304         guint32 idx;
1305         
1306         if (image_is_dynamic (klass->image)) {
1307                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
1308                 return lookup_custom_attr (klass->image, event);
1309         }
1310         idx = find_event_index (klass, event);
1311         idx <<= MONO_CUSTOM_ATTR_BITS;
1312         idx |= MONO_CUSTOM_ATTR_EVENT;
1313         return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1314 }
1315
1316 MonoCustomAttrInfo*
1317 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
1318 {
1319         MonoError error;
1320         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
1321         mono_error_cleanup (&error);
1322         return result;
1323 }
1324
1325 MonoCustomAttrInfo*
1326 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
1327 {
1328         guint32 idx;
1329         mono_error_init (error);
1330
1331         if (image_is_dynamic (klass->image)) {
1332                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
1333                 return lookup_custom_attr (klass->image, field);
1334         }
1335         idx = find_field_index (klass, field);
1336         idx <<= MONO_CUSTOM_ATTR_BITS;
1337         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1338         return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
1339 }
1340
1341 /**
1342  * mono_custom_attrs_from_param:
1343  * @method: handle to the method that we want to retrieve custom parameter information from
1344  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1345  *
1346  * The result must be released with mono_custom_attrs_free().
1347  *
1348  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
1349  */
1350 MonoCustomAttrInfo*
1351 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
1352 {
1353         MonoError error;
1354         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
1355         mono_error_cleanup (&error);
1356         return result;
1357 }
1358
1359 /**
1360  * mono_custom_attrs_from_param_checked:
1361  * @method: handle to the method that we want to retrieve custom parameter information from
1362  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1363  * @error: set on error
1364  *
1365  * The result must be released with mono_custom_attrs_free().
1366  *
1367  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
1368  */
1369 MonoCustomAttrInfo*
1370 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
1371 {
1372         MonoTableInfo *ca;
1373         guint32 i, idx, method_index;
1374         guint32 param_list, param_last, param_pos, found;
1375         MonoImage *image;
1376         MonoReflectionMethodAux *aux;
1377
1378         mono_error_init (error);
1379
1380         /*
1381          * An instantiated method has the same cattrs as the generic method definition.
1382          *
1383          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1384          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1385          */
1386         if (method->is_inflated)
1387                 method = ((MonoMethodInflated *) method)->declaring;
1388
1389         if (image_is_dynamic (method->klass->image)) {
1390                 MonoCustomAttrInfo *res, *ainfo;
1391                 int size;
1392
1393                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1394                 if (!aux || !aux->param_cattr)
1395                         return NULL;
1396
1397                 /* Need to copy since it will be freed later */
1398                 ainfo = aux->param_cattr [param];
1399                 if (!ainfo)
1400                         return NULL;
1401                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
1402                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
1403                 memcpy (res, ainfo, size);
1404                 return res;
1405         }
1406
1407         image = method->klass->image;
1408         method_index = mono_method_get_index (method);
1409         if (!method_index)
1410                 return NULL;
1411         ca = &image->tables [MONO_TABLE_METHOD];
1412
1413         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
1414         if (method_index == ca->rows) {
1415                 ca = &image->tables [MONO_TABLE_PARAM];
1416                 param_last = ca->rows + 1;
1417         } else {
1418                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
1419                 ca = &image->tables [MONO_TABLE_PARAM];
1420         }
1421         found = FALSE;
1422         for (i = param_list; i < param_last; ++i) {
1423                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
1424                 if (param_pos == param) {
1425                         found = TRUE;
1426                         break;
1427                 }
1428         }
1429         if (!found)
1430                 return NULL;
1431         idx = i;
1432         idx <<= MONO_CUSTOM_ATTR_BITS;
1433         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1434         return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
1435 }
1436
1437 gboolean
1438 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1439 {
1440         int i;
1441         for (i = 0; i < ainfo->num_attrs; ++i) {
1442                 MonoCustomAttrEntry *centry = &ainfo->attrs[i];
1443                 if (centry->ctor == NULL)
1444                         continue;
1445                 MonoClass *klass = centry->ctor->klass;
1446                 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)))
1447                         return TRUE;
1448         }
1449         return FALSE;
1450 }
1451
1452 MonoObject*
1453 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1454 {
1455         MonoError error;
1456         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
1457         mono_error_assert_ok (&error); /*FIXME proper error handling*/
1458         return res;
1459 }
1460
1461 MonoObject*
1462 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
1463 {
1464         int i;
1465         MonoCustomAttrEntry *centry = NULL;
1466
1467         g_assert (attr_klass != NULL);
1468
1469         mono_error_init (error);
1470
1471         for (i = 0; i < ainfo->num_attrs; ++i) {
1472                 centry = &ainfo->attrs[i];
1473                 if (centry->ctor == NULL)
1474                         continue;
1475                 MonoClass *klass = centry->ctor->klass;
1476                 if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass))
1477                         break;
1478         }
1479         if (centry == NULL)
1480                 return NULL;
1481
1482         return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
1483 }
1484
1485 /*
1486  * mono_reflection_get_custom_attrs_info:
1487  * @obj: a reflection object handle
1488  *
1489  * Return the custom attribute info for attributes defined for the
1490  * reflection handle @obj. The objects.
1491  *
1492  * FIXME this function leaks like a sieve for SRE objects.
1493  */
1494 MonoCustomAttrInfo*
1495 mono_reflection_get_custom_attrs_info (MonoObject *obj)
1496 {
1497         MonoError error;
1498         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
1499         mono_error_assert_ok (&error);
1500         return result;
1501 }
1502
1503 /**
1504  * mono_reflection_get_custom_attrs_info_checked:
1505  * @obj: a reflection object handle
1506  * @error: set on error
1507  *
1508  * Return the custom attribute info for attributes defined for the
1509  * reflection handle @obj. The objects.
1510  *
1511  * On failure returns NULL and sets @error.
1512  *
1513  * FIXME this function leaks like a sieve for SRE objects.
1514  */
1515 MonoCustomAttrInfo*
1516 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
1517 {
1518         MonoClass *klass;
1519         MonoCustomAttrInfo *cinfo = NULL;
1520         
1521         mono_error_init (error);
1522
1523         klass = obj->vtable->klass;
1524         if (klass == mono_defaults.runtimetype_class) {
1525                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1526                 return_val_if_nok (error, NULL);
1527                 klass = mono_class_from_mono_type (type);
1528                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1529                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
1530                 return_val_if_nok (error, NULL);
1531         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
1532                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
1533                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, FALSE, error);
1534                 return_val_if_nok (error, NULL);
1535         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
1536                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
1537                 cinfo = mono_custom_attrs_from_module (module->image, error);
1538                 return_val_if_nok (error, NULL);
1539         } else if (strcmp ("MonoProperty", klass->name) == 0) {
1540                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
1541                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
1542                 return_val_if_nok (error, NULL);
1543         } else if (strcmp ("MonoEvent", klass->name) == 0) {
1544                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
1545                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
1546                 return_val_if_nok (error, NULL);
1547         } else if (strcmp ("MonoField", klass->name) == 0) {
1548                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
1549                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
1550                 return_val_if_nok (error, NULL);
1551         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
1552                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
1553                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
1554                 return_val_if_nok (error, NULL);
1555         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
1556                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
1557                 MonoClass *member_class = mono_object_class (param->MemberImpl);
1558                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
1559                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
1560                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
1561                         return_val_if_nok (error, NULL);
1562                 } else if (mono_is_sr_mono_property (member_class)) {
1563                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
1564                         MonoMethod *method;
1565                         if (!(method = prop->property->get))
1566                                 method = prop->property->set;
1567                         g_assert (method);
1568
1569                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
1570                         return_val_if_nok (error, NULL);
1571                 } 
1572 #ifndef DISABLE_REFLECTION_EMIT
1573                 else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
1574                         // FIXME: Is this still needed ?
1575                         g_assert_not_reached ();
1576                 } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
1577                         // FIXME: Is this still needed ?
1578                         g_assert_not_reached ();
1579                 } 
1580 #endif
1581                 else {
1582                         char *type_name = mono_type_get_full_name (member_class);
1583                         mono_error_set_not_supported (error,
1584                                                       "Custom attributes on a ParamInfo with member %s are not supported",
1585                                                       type_name);
1586                         g_free (type_name);
1587                         return NULL;
1588                 }
1589         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
1590                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
1591                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
1592         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
1593                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
1594                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
1595         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
1596                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
1597                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
1598         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
1599                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
1600                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
1601         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
1602                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
1603                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
1604         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
1605                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
1606                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
1607         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
1608                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
1609                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
1610                 return_val_if_nok (error, NULL);
1611         } else { /* handle other types here... */
1612                 g_error ("get custom attrs not yet supported for %s", klass->name);
1613         }
1614
1615         return cinfo;
1616 }
1617
1618 /*
1619  * mono_reflection_get_custom_attrs_by_type:
1620  * @obj: a reflection object handle
1621  *
1622  * Return an array with all the custom attributes defined of the
1623  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
1624  * of that type are returned. The objects are fully build. Return NULL if a loading error
1625  * occurs.
1626  */
1627 MonoArray*
1628 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
1629 {
1630         MonoArray *result;
1631         MonoCustomAttrInfo *cinfo;
1632
1633         mono_error_init (error);
1634
1635         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1636         return_val_if_nok (error, NULL);
1637         if (cinfo) {
1638                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
1639                 if (!cinfo->cached)
1640                         mono_custom_attrs_free (cinfo);
1641                 if (!result)
1642                         return NULL;
1643         } else {
1644                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
1645         }
1646
1647         return result;
1648 }
1649
1650 /*
1651  * mono_reflection_get_custom_attrs:
1652  * @obj: a reflection object handle
1653  *
1654  * Return an array with all the custom attributes defined of the
1655  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
1656  * occurs.
1657  */
1658 MonoArray*
1659 mono_reflection_get_custom_attrs (MonoObject *obj)
1660 {
1661         MonoError error;
1662
1663         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
1664 }
1665
1666 /*
1667  * mono_reflection_get_custom_attrs_data:
1668  * @obj: a reflection obj handle
1669  *
1670  * Returns an array of System.Reflection.CustomAttributeData,
1671  * which include information about attributes reflected on
1672  * types loaded using the Reflection Only methods
1673  */
1674 MonoArray*
1675 mono_reflection_get_custom_attrs_data (MonoObject *obj)
1676 {
1677         MonoError error;
1678         MonoArray* result;
1679         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
1680         mono_error_cleanup (&error);
1681         return result;
1682 }
1683
1684 /*
1685  * mono_reflection_get_custom_attrs_data_checked:
1686  * @obj: a reflection obj handle
1687  * @error: set on error
1688  *
1689  * Returns an array of System.Reflection.CustomAttributeData,
1690  * which include information about attributes reflected on
1691  * types loaded using the Reflection Only methods
1692  */
1693 MonoArray*
1694 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
1695 {
1696         MonoArray *result;
1697         MonoCustomAttrInfo *cinfo;
1698
1699         mono_error_init (error);
1700
1701         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1702         return_val_if_nok (error, NULL);
1703         if (cinfo) {
1704                 result = mono_custom_attrs_data_construct (cinfo, error);
1705                 if (!cinfo->cached)
1706                         mono_custom_attrs_free (cinfo);
1707                 return_val_if_nok (error, NULL);
1708         } else 
1709                 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
1710
1711         return result;
1712 }