Revert "Modify fixup_cattrs () to handle a corner case where a cattr is created using...
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
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  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45
46 static gboolean is_usertype (MonoReflectionType *ref);
47 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
48
49 typedef struct {
50         char *p;
51         char *buf;
52         char *end;
53 } SigBuffer;
54
55 #define TEXT_OFFSET 512
56 #define CLI_H_SIZE 136
57 #define FILE_ALIGN 512
58 #define VIRT_ALIGN 8192
59 #define START_TEXT_RVA  0x00002000
60
61 typedef struct {
62         MonoReflectionILGen *ilgen;
63         MonoReflectionType *rtype;
64         MonoArray *parameters;
65         MonoArray *generic_params;
66         MonoGenericContainer *generic_container;
67         MonoArray *pinfo;
68         MonoArray *opt_types;
69         guint32 attrs;
70         guint32 iattrs;
71         guint32 call_conv;
72         guint32 *table_idx; /* note: it's a pointer */
73         MonoArray *code;
74         MonoObject *type;
75         MonoString *name;
76         MonoBoolean init_locals;
77         MonoBoolean skip_visibility;
78         MonoArray *return_modreq;
79         MonoArray *return_modopt;
80         MonoArray *param_modreq;
81         MonoArray *param_modopt;
82         MonoArray *permissions;
83         MonoMethod *mhandle;
84         guint32 nrefs;
85         gpointer *refs;
86         /* for PInvoke */
87         int charset, extra_flags, native_cc;
88         MonoString *dll, *dllentry;
89 } ReflectionMethodBuilder;
90
91 typedef struct {
92         guint32 owner;
93         MonoReflectionGenericParam *gparam;
94 } GenericParamTableEntry;
95
96 const unsigned char table_sizes [MONO_TABLE_NUM] = {
97         MONO_MODULE_SIZE,
98         MONO_TYPEREF_SIZE,
99         MONO_TYPEDEF_SIZE,
100         0,
101         MONO_FIELD_SIZE,
102         0,
103         MONO_METHOD_SIZE,
104         0,
105         MONO_PARAM_SIZE,
106         MONO_INTERFACEIMPL_SIZE,
107         MONO_MEMBERREF_SIZE,    /* 0x0A */
108         MONO_CONSTANT_SIZE,
109         MONO_CUSTOM_ATTR_SIZE,
110         MONO_FIELD_MARSHAL_SIZE,
111         MONO_DECL_SECURITY_SIZE,
112         MONO_CLASS_LAYOUT_SIZE,
113         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
114         MONO_STAND_ALONE_SIGNATURE_SIZE,
115         MONO_EVENT_MAP_SIZE,
116         0,
117         MONO_EVENT_SIZE,
118         MONO_PROPERTY_MAP_SIZE,
119         0,
120         MONO_PROPERTY_SIZE,
121         MONO_METHOD_SEMA_SIZE,
122         MONO_METHODIMPL_SIZE,
123         MONO_MODULEREF_SIZE,    /* 0x1A */
124         MONO_TYPESPEC_SIZE,
125         MONO_IMPLMAP_SIZE,      
126         MONO_FIELD_RVA_SIZE,
127         0,
128         0,
129         MONO_ASSEMBLY_SIZE,     /* 0x20 */
130         MONO_ASSEMBLY_PROCESSOR_SIZE,
131         MONO_ASSEMBLYOS_SIZE,
132         MONO_ASSEMBLYREF_SIZE,
133         MONO_ASSEMBLYREFPROC_SIZE,
134         MONO_ASSEMBLYREFOS_SIZE,
135         MONO_FILE_SIZE,
136         MONO_EXP_TYPE_SIZE,
137         MONO_MANIFEST_SIZE,
138         MONO_NESTED_CLASS_SIZE,
139
140         MONO_GENERICPARAM_SIZE, /* 0x2A */
141         MONO_METHODSPEC_SIZE,
142         MONO_GENPARCONSTRAINT_SIZE
143
144 };
145
146 #ifndef DISABLE_REFLECTION_EMIT
147 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
148 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
149 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
150 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
151 static void    ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
153 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
154 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
155 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
156 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
157 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
158 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
159 #endif
160
161 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
162 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
163 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
164 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
165 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
166 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
167 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
170 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
171 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
172 static gboolean is_sre_array (MonoClass *class);
173 static gboolean is_sre_byref (MonoClass *class);
174 static gboolean is_sre_pointer (MonoClass *class);
175 static gboolean is_sre_type_builder (MonoClass *class);
176 static gboolean is_sre_method_builder (MonoClass *class);
177 static gboolean is_sre_ctor_builder (MonoClass *class);
178 static gboolean is_sre_field_builder (MonoClass *class);
179 static gboolean is_sr_mono_method (MonoClass *class);
180 static gboolean is_sr_mono_cmethod (MonoClass *class);
181 static gboolean is_sr_mono_generic_method (MonoClass *class);
182 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_field (MonoClass *class);
184 static gboolean is_sr_mono_property (MonoClass *class);
185 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
186 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
187
188 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
189 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
190 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
191
192 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
193 static void init_type_builder_generics (MonoObject *type);
194
195 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
196 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
197         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
198         __type = mono_reflection_type_resolve_user_types (__type);      \
199         mono_array_set (arr, MonoReflectionType*, index, __type);       \
200 } while (0)
201
202 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
203
204 void
205 mono_reflection_init (void)
206 {
207 }
208
209 static void
210 sigbuffer_init (SigBuffer *buf, int size)
211 {
212         buf->buf = g_malloc (size);
213         buf->p = buf->buf;
214         buf->end = buf->buf + size;
215 }
216
217 static void
218 sigbuffer_make_room (SigBuffer *buf, int size)
219 {
220         if (buf->end - buf->p < size) {
221                 int new_size = buf->end - buf->buf + size + 32;
222                 char *p = g_realloc (buf->buf, new_size);
223                 size = buf->p - buf->buf;
224                 buf->buf = p;
225                 buf->p = p + size;
226                 buf->end = buf->buf + new_size;
227         }
228 }
229
230 static void
231 sigbuffer_add_value (SigBuffer *buf, guint32 val)
232 {
233         sigbuffer_make_room (buf, 6);
234         mono_metadata_encode_value (val, buf->p, &buf->p);
235 }
236
237 static void
238 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
239 {
240         sigbuffer_make_room (buf, 1);
241         buf->p [0] = val;
242         buf->p++;
243 }
244
245 static void
246 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
247 {
248         sigbuffer_make_room (buf, size);
249         memcpy (buf->p, p, size);
250         buf->p += size;
251 }
252
253 static void
254 sigbuffer_free (SigBuffer *buf)
255 {
256         g_free (buf->buf);
257 }
258
259 #ifndef DISABLE_REFLECTION_EMIT
260 /**
261  * mp_g_alloc:
262  *
263  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
264  * from the C heap.
265  */
266 static gpointer
267 image_g_malloc (MonoImage *image, guint size)
268 {
269         if (image)
270                 return mono_image_alloc (image, size);
271         else
272                 return g_malloc (size);
273 }
274 #endif /* !DISABLE_REFLECTION_EMIT */
275
276 /**
277  * image_g_alloc0:
278  *
279  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
280  * from the C heap.
281  */
282 static gpointer
283 image_g_malloc0 (MonoImage *image, guint size)
284 {
285         if (image)
286                 return mono_image_alloc0 (image, size);
287         else
288                 return g_malloc0 (size);
289 }
290
291 #ifndef DISABLE_REFLECTION_EMIT
292 static char*
293 image_strdup (MonoImage *image, const char *s)
294 {
295         if (image)
296                 return mono_image_strdup (image, s);
297         else
298                 return g_strdup (s);
299 }
300 #endif
301
302 #define image_g_new(image,struct_type, n_structs)               \
303     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
304
305 #define image_g_new0(image,struct_type, n_structs)              \
306     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
307
308
309 static void
310 alloc_table (MonoDynamicTable *table, guint nrows)
311 {
312         table->rows = nrows;
313         g_assert (table->columns);
314         if (nrows + 1 >= table->alloc_rows) {
315                 while (nrows + 1 >= table->alloc_rows) {
316                         if (table->alloc_rows == 0)
317                                 table->alloc_rows = 16;
318                         else
319                                 table->alloc_rows *= 2;
320                 }
321
322                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
323         }
324 }
325
326 static void
327 make_room_in_stream (MonoDynamicStream *stream, int size)
328 {
329         if (size <= stream->alloc_size)
330                 return;
331         
332         while (stream->alloc_size <= size) {
333                 if (stream->alloc_size < 4096)
334                         stream->alloc_size = 4096;
335                 else
336                         stream->alloc_size *= 2;
337         }
338         
339         stream->data = g_realloc (stream->data, stream->alloc_size);
340 }
341
342 static guint32
343 string_heap_insert (MonoDynamicStream *sh, const char *str)
344 {
345         guint32 idx;
346         guint32 len;
347         gpointer oldkey, oldval;
348
349         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
350                 return GPOINTER_TO_UINT (oldval);
351
352         len = strlen (str) + 1;
353         idx = sh->index;
354         
355         make_room_in_stream (sh, idx + len);
356
357         /*
358          * We strdup the string even if we already copy them in sh->data
359          * so that the string pointers in the hash remain valid even if
360          * we need to realloc sh->data. We may want to avoid that later.
361          */
362         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
363         memcpy (sh->data + idx, str, len);
364         sh->index += len;
365         return idx;
366 }
367
368 static guint32
369 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
370 {
371         char *name = mono_string_to_utf8 (str);
372         guint32 idx;
373         idx = string_heap_insert (sh, name);
374         g_free (name);
375         return idx;
376 }
377
378 #ifndef DISABLE_REFLECTION_EMIT
379 static void
380 string_heap_init (MonoDynamicStream *sh)
381 {
382         sh->index = 0;
383         sh->alloc_size = 4096;
384         sh->data = g_malloc (4096);
385         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
386         string_heap_insert (sh, "");
387 }
388 #endif
389
390 static guint32
391 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
392 {
393         guint32 idx;
394         
395         make_room_in_stream (stream, stream->index + len);
396         memcpy (stream->data + stream->index, data, len);
397         idx = stream->index;
398         stream->index += len;
399         /* 
400          * align index? Not without adding an additional param that controls it since
401          * we may store a blob value in pieces.
402          */
403         return idx;
404 }
405
406 static guint32
407 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
408 {
409         guint32 idx;
410         
411         make_room_in_stream (stream, stream->index + len);
412         memset (stream->data + stream->index, 0, len);
413         idx = stream->index;
414         stream->index += len;
415         return idx;
416 }
417
418 static void
419 stream_data_align (MonoDynamicStream *stream)
420 {
421         char buf [4] = {0};
422         guint32 count = stream->index % 4;
423
424         /* we assume the stream data will be aligned */
425         if (count)
426                 mono_image_add_stream_data (stream, buf, 4 - count);
427 }
428
429 #ifndef DISABLE_REFLECTION_EMIT
430 static int
431 mono_blob_entry_hash (const char* str)
432 {
433         guint len, h;
434         const char *end;
435         len = mono_metadata_decode_blob_size (str, &str);
436         if (len > 0) {
437                 end = str + len;
438                 h = *str;
439                 for (str += 1; str < end; str++)
440                         h = (h << 5) - h + *str;
441                 return h;
442         } else {
443                 return 0;
444         }
445 }
446
447 static gboolean
448 mono_blob_entry_equal (const char *str1, const char *str2) {
449         int len, len2;
450         const char *end1;
451         const char *end2;
452         len = mono_metadata_decode_blob_size (str1, &end1);
453         len2 = mono_metadata_decode_blob_size (str2, &end2);
454         if (len != len2)
455                 return 0;
456         return memcmp (end1, end2, len) == 0;
457 }
458 #endif
459 static guint32
460 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
461 {
462         guint32 idx;
463         char *copy;
464         gpointer oldkey, oldval;
465
466         copy = g_malloc (s1+s2);
467         memcpy (copy, b1, s1);
468         memcpy (copy + s1, b2, s2);
469         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
470                 g_free (copy);
471                 idx = GPOINTER_TO_UINT (oldval);
472         } else {
473                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
474                 mono_image_add_stream_data (&assembly->blob, b2, s2);
475                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
476         }
477         return idx;
478 }
479
480 static guint32
481 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
482 {
483         char blob_size [8];
484         char *b = blob_size;
485         guint32 size = buf->p - buf->buf;
486         /* store length */
487         g_assert (size <= (buf->end - buf->buf));
488         mono_metadata_encode_value (size, b, &b);
489         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
490 }
491
492 /*
493  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
494  * dest may be misaligned.
495  */
496 static void
497 swap_with_size (char *dest, const char* val, int len, int nelem) {
498 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
499         int elem;
500
501         for (elem = 0; elem < nelem; ++elem) {
502                 switch (len) {
503                 case 1:
504                         *dest = *val;
505                         break;
506                 case 2:
507                         dest [0] = val [1];
508                         dest [1] = val [0];
509                         break;
510                 case 4:
511                         dest [0] = val [3];
512                         dest [1] = val [2];
513                         dest [2] = val [1];
514                         dest [3] = val [0];
515                         break;
516                 case 8:
517                         dest [0] = val [7];
518                         dest [1] = val [6];
519                         dest [2] = val [5];
520                         dest [3] = val [4];
521                         dest [4] = val [3];
522                         dest [5] = val [2];
523                         dest [6] = val [1];
524                         dest [7] = val [0];
525                         break;
526                 default:
527                         g_assert_not_reached ();
528                 }
529                 dest += len;
530                 val += len;
531         }
532 #else
533         memcpy (dest, val, len * nelem);
534 #endif
535 }
536
537 static guint32
538 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
539 {
540         char blob_size [64];
541         char *b = blob_size;
542         guint32 idx = 0, len;
543
544         len = str->length * 2;
545         mono_metadata_encode_value (len, b, &b);
546 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
547         {
548                 char *swapped = g_malloc (2 * mono_string_length (str));
549                 const char *p = (const char*)mono_string_chars (str);
550
551                 swap_with_size (swapped, p, 2, mono_string_length (str));
552                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
553                 g_free (swapped);
554         }
555 #else
556         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
557 #endif
558         return idx;
559 }
560
561 #ifndef DISABLE_REFLECTION_EMIT
562 static MonoClass *
563 default_class_from_mono_type (MonoType *type)
564 {
565         switch (type->type) {
566         case MONO_TYPE_OBJECT:
567                 return mono_defaults.object_class;
568         case MONO_TYPE_VOID:
569                 return mono_defaults.void_class;
570         case MONO_TYPE_BOOLEAN:
571                 return mono_defaults.boolean_class;
572         case MONO_TYPE_CHAR:
573                 return mono_defaults.char_class;
574         case MONO_TYPE_I1:
575                 return mono_defaults.sbyte_class;
576         case MONO_TYPE_U1:
577                 return mono_defaults.byte_class;
578         case MONO_TYPE_I2:
579                 return mono_defaults.int16_class;
580         case MONO_TYPE_U2:
581                 return mono_defaults.uint16_class;
582         case MONO_TYPE_I4:
583                 return mono_defaults.int32_class;
584         case MONO_TYPE_U4:
585                 return mono_defaults.uint32_class;
586         case MONO_TYPE_I:
587                 return mono_defaults.int_class;
588         case MONO_TYPE_U:
589                 return mono_defaults.uint_class;
590         case MONO_TYPE_I8:
591                 return mono_defaults.int64_class;
592         case MONO_TYPE_U8:
593                 return mono_defaults.uint64_class;
594         case MONO_TYPE_R4:
595                 return mono_defaults.single_class;
596         case MONO_TYPE_R8:
597                 return mono_defaults.double_class;
598         case MONO_TYPE_STRING:
599                 return mono_defaults.string_class;
600         default:
601                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
602                 g_assert_not_reached ();
603         }
604         
605         return NULL;
606 }
607 #endif
608
609 /*
610  * mono_class_get_ref_info:
611  *
612  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
613  */
614 gpointer
615 mono_class_get_ref_info (MonoClass *klass)
616 {
617         if (klass->ref_info_handle == 0)
618                 return NULL;
619         else
620                 return mono_gchandle_get_target (klass->ref_info_handle);
621 }
622
623 void
624 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
625 {
626         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
627         g_assert (klass->ref_info_handle != 0);
628 }
629
630 void
631 mono_class_free_ref_info (MonoClass *klass)
632 {
633         if (klass->ref_info_handle) {
634                 mono_gchandle_free (klass->ref_info_handle);
635                 klass->ref_info_handle = 0;
636         }
637 }
638
639 static void
640 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
641 {
642         int i;
643         MonoGenericInst *class_inst;
644         MonoClass *klass;
645
646         g_assert (gclass);
647
648         class_inst = gclass->context.class_inst;
649
650         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
651         klass = gclass->container_class;
652         sigbuffer_add_value (buf, klass->byval_arg.type);
653         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
654
655         sigbuffer_add_value (buf, class_inst->type_argc);
656         for (i = 0; i < class_inst->type_argc; ++i)
657                 encode_type (assembly, class_inst->type_argv [i], buf);
658
659 }
660
661 static void
662 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
663 {
664         if (!type) {
665                 g_assert_not_reached ();
666                 return;
667         }
668                 
669         if (type->byref)
670                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
671
672         switch (type->type){
673         case MONO_TYPE_VOID:
674         case MONO_TYPE_BOOLEAN:
675         case MONO_TYPE_CHAR:
676         case MONO_TYPE_I1:
677         case MONO_TYPE_U1:
678         case MONO_TYPE_I2:
679         case MONO_TYPE_U2:
680         case MONO_TYPE_I4:
681         case MONO_TYPE_U4:
682         case MONO_TYPE_I8:
683         case MONO_TYPE_U8:
684         case MONO_TYPE_R4:
685         case MONO_TYPE_R8:
686         case MONO_TYPE_I:
687         case MONO_TYPE_U:
688         case MONO_TYPE_STRING:
689         case MONO_TYPE_OBJECT:
690         case MONO_TYPE_TYPEDBYREF:
691                 sigbuffer_add_value (buf, type->type);
692                 break;
693         case MONO_TYPE_PTR:
694                 sigbuffer_add_value (buf, type->type);
695                 encode_type (assembly, type->data.type, buf);
696                 break;
697         case MONO_TYPE_SZARRAY:
698                 sigbuffer_add_value (buf, type->type);
699                 encode_type (assembly, &type->data.klass->byval_arg, buf);
700                 break;
701         case MONO_TYPE_VALUETYPE:
702         case MONO_TYPE_CLASS: {
703                 MonoClass *k = mono_class_from_mono_type (type);
704
705                 if (k->generic_container) {
706                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
707                         encode_generic_class (assembly, gclass, buf);
708                 } else {
709                         /*
710                          * Make sure we use the correct type.
711                          */
712                         sigbuffer_add_value (buf, k->byval_arg.type);
713                         /*
714                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
715                          * otherwise two typerefs could point to the same type, leading to
716                          * verification errors.
717                          */
718                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
719                 }
720                 break;
721         }
722         case MONO_TYPE_ARRAY:
723                 sigbuffer_add_value (buf, type->type);
724                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
725                 sigbuffer_add_value (buf, type->data.array->rank);
726                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
727                 sigbuffer_add_value (buf, 0);
728                 break;
729         case MONO_TYPE_GENERICINST:
730                 encode_generic_class (assembly, type->data.generic_class, buf);
731                 break;
732         case MONO_TYPE_VAR:
733         case MONO_TYPE_MVAR:
734                 sigbuffer_add_value (buf, type->type);
735                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
736                 break;
737         default:
738                 g_error ("need to encode type %x", type->type);
739         }
740 }
741
742 static void
743 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
744 {
745         if (!type) {
746                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
747                 return;
748         }
749
750         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
751 }
752
753 static void
754 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
755 {
756         int i;
757
758         if (modreq) {
759                 for (i = 0; i < mono_array_length (modreq); ++i) {
760                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
761                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
762                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
763                 }
764         }
765         if (modopt) {
766                 for (i = 0; i < mono_array_length (modopt); ++i) {
767                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
768                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
769                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
770                 }
771         }
772 }
773
774 #ifndef DISABLE_REFLECTION_EMIT
775 static guint32
776 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
777 {
778         SigBuffer buf;
779         int i;
780         guint32 nparams =  sig->param_count;
781         guint32 idx;
782
783         if (!assembly->save)
784                 return 0;
785
786         sigbuffer_init (&buf, 32);
787         /*
788          * FIXME: vararg, explicit_this, differenc call_conv values...
789          */
790         idx = sig->call_convention;
791         if (sig->hasthis)
792                 idx |= 0x20; /* hasthis */
793         if (sig->generic_param_count)
794                 idx |= 0x10; /* generic */
795         sigbuffer_add_byte (&buf, idx);
796         if (sig->generic_param_count)
797                 sigbuffer_add_value (&buf, sig->generic_param_count);
798         sigbuffer_add_value (&buf, nparams);
799         encode_type (assembly, sig->ret, &buf);
800         for (i = 0; i < nparams; ++i) {
801                 if (i == sig->sentinelpos)
802                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
803                 encode_type (assembly, sig->params [i], &buf);
804         }
805         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
806         sigbuffer_free (&buf);
807         return idx;
808 }
809 #endif
810
811 static guint32
812 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
813 {
814         /*
815          * FIXME: reuse code from method_encode_signature().
816          */
817         SigBuffer buf;
818         int i;
819         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
820         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
821         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
822         guint32 idx;
823
824         sigbuffer_init (&buf, 32);
825         /* LAMESPEC: all the call conv spec is foobared */
826         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
827         if (mb->call_conv & 2)
828                 idx |= 0x5; /* vararg */
829         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
830                 idx |= 0x20; /* hasthis */
831         if (ngparams)
832                 idx |= 0x10; /* generic */
833         sigbuffer_add_byte (&buf, idx);
834         if (ngparams)
835                 sigbuffer_add_value (&buf, ngparams);
836         sigbuffer_add_value (&buf, nparams + notypes);
837         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
838         encode_reflection_type (assembly, mb->rtype, &buf);
839         for (i = 0; i < nparams; ++i) {
840                 MonoArray *modreq = NULL;
841                 MonoArray *modopt = NULL;
842                 MonoReflectionType *pt;
843
844                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
845                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
846                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
847                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
848                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
849                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
850                 encode_reflection_type (assembly, pt, &buf);
851         }
852         if (notypes)
853                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
854         for (i = 0; i < notypes; ++i) {
855                 MonoReflectionType *pt;
856
857                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
858                 encode_reflection_type (assembly, pt, &buf);
859         }
860
861         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
862         sigbuffer_free (&buf);
863         return idx;
864 }
865
866 static guint32
867 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
868 {
869         MonoDynamicTable *table;
870         guint32 *values;
871         guint32 idx, sig_idx;
872         guint nl = mono_array_length (ilgen->locals);
873         SigBuffer buf;
874         int i;
875
876         sigbuffer_init (&buf, 32);
877         sigbuffer_add_value (&buf, 0x07);
878         sigbuffer_add_value (&buf, nl);
879         for (i = 0; i < nl; ++i) {
880                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
881                 
882                 if (lb->is_pinned)
883                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
884                 
885                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
886         }
887         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
888         sigbuffer_free (&buf);
889
890         if (assembly->standalonesig_cache == NULL)
891                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
892         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
893         if (idx)
894                 return idx;
895
896         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
897         idx = table->next_idx ++;
898         table->rows ++;
899         alloc_table (table, table->rows);
900         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
901
902         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
903
904         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
905
906         return idx;
907 }
908
909 static guint32
910 method_count_clauses (MonoReflectionILGen *ilgen)
911 {
912         guint32 num_clauses = 0;
913         int i;
914
915         MonoILExceptionInfo *ex_info;
916         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
917                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
918                 if (ex_info->handlers)
919                         num_clauses += mono_array_length (ex_info->handlers);
920                 else
921                         num_clauses++;
922         }
923
924         return num_clauses;
925 }
926
927 #ifndef DISABLE_REFLECTION_EMIT
928 static MonoExceptionClause*
929 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
930 {
931         MonoExceptionClause *clauses;
932         MonoExceptionClause *clause;
933         MonoILExceptionInfo *ex_info;
934         MonoILExceptionBlock *ex_block;
935         guint32 finally_start;
936         int i, j, clause_index;;
937
938         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
939
940         clause_index = 0;
941         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
942                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
943                 finally_start = ex_info->start + ex_info->len;
944                 if (!ex_info->handlers)
945                         continue;
946                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
947                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
948                         clause = &(clauses [clause_index]);
949
950                         clause->flags = ex_block->type;
951                         clause->try_offset = ex_info->start;
952
953                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
954                                 clause->try_len = finally_start - ex_info->start;
955                         else
956                                 clause->try_len = ex_info->len;
957                         clause->handler_offset = ex_block->start;
958                         clause->handler_len = ex_block->len;
959                         if (ex_block->extype) {
960                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
961                         } else {
962                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
963                                         clause->data.filter_offset = ex_block->filter_offset;
964                                 else
965                                         clause->data.filter_offset = 0;
966                         }
967                         finally_start = ex_block->start + ex_block->len;
968
969                         clause_index ++;
970                 }
971         }
972
973         return clauses;
974 }
975 #endif /* !DISABLE_REFLECTION_EMIT */
976
977 static guint32
978 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
979 {
980         char flags = 0;
981         guint32 idx;
982         guint32 code_size;
983         gint32 max_stack, i;
984         gint32 num_locals = 0;
985         gint32 num_exception = 0;
986         gint maybe_small;
987         guint32 fat_flags;
988         char fat_header [12];
989         guint32 int_value;
990         guint16 short_value;
991         guint32 local_sig = 0;
992         guint32 header_size = 12;
993         MonoArray *code;
994
995         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
996                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
997                 return 0;
998
999         /*if (mb->name)
1000                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1001         if (mb->ilgen) {
1002                 code = mb->ilgen->code;
1003                 code_size = mb->ilgen->code_len;
1004                 max_stack = mb->ilgen->max_stack;
1005                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1006                 if (mb->ilgen->ex_handlers)
1007                         num_exception = method_count_clauses (mb->ilgen);
1008         } else {
1009                 code = mb->code;
1010                 if (code == NULL){
1011                         char *name = mono_string_to_utf8 (mb->name);
1012                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1013                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1014                         g_free (str);
1015                         g_free (name);
1016                         mono_raise_exception (exception);
1017                 }
1018
1019                 code_size = mono_array_length (code);
1020                 max_stack = 8; /* we probably need to run a verifier on the code... */
1021         }
1022
1023         stream_data_align (&assembly->code);
1024
1025         /* check for exceptions, maxstack, locals */
1026         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1027         if (maybe_small) {
1028                 if (code_size < 64 && !(code_size & 1)) {
1029                         flags = (code_size << 2) | 0x2;
1030                 } else if (code_size < 32 && (code_size & 1)) {
1031                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1032                 } else {
1033                         goto fat_header;
1034                 }
1035                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1036                 /* add to the fixup todo list */
1037                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1038                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1039                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1040                 return assembly->text_rva + idx;
1041         } 
1042 fat_header:
1043         if (num_locals)
1044                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1045         /* 
1046          * FIXME: need to set also the header size in fat_flags.
1047          * (and more sects and init locals flags)
1048          */
1049         fat_flags =  0x03;
1050         if (num_exception)
1051                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1052         if (mb->init_locals)
1053                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1054         fat_header [0] = fat_flags;
1055         fat_header [1] = (header_size / 4 ) << 4;
1056         short_value = GUINT16_TO_LE (max_stack);
1057         memcpy (fat_header + 2, &short_value, 2);
1058         int_value = GUINT32_TO_LE (code_size);
1059         memcpy (fat_header + 4, &int_value, 4);
1060         int_value = GUINT32_TO_LE (local_sig);
1061         memcpy (fat_header + 8, &int_value, 4);
1062         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1063         /* add to the fixup todo list */
1064         if (mb->ilgen && mb->ilgen->num_token_fixups)
1065                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1066         
1067         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1068         if (num_exception) {
1069                 unsigned char sheader [4];
1070                 MonoILExceptionInfo * ex_info;
1071                 MonoILExceptionBlock * ex_block;
1072                 int j;
1073
1074                 stream_data_align (&assembly->code);
1075                 /* always use fat format for now */
1076                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1077                 num_exception *= 6 * sizeof (guint32);
1078                 num_exception += 4; /* include the size of the header */
1079                 sheader [1] = num_exception & 0xff;
1080                 sheader [2] = (num_exception >> 8) & 0xff;
1081                 sheader [3] = (num_exception >> 16) & 0xff;
1082                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1083                 /* fat header, so we are already aligned */
1084                 /* reverse order */
1085                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1086                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1087                         if (ex_info->handlers) {
1088                                 int finally_start = ex_info->start + ex_info->len;
1089                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1090                                         guint32 val;
1091                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1092                                         /* the flags */
1093                                         val = GUINT32_TO_LE (ex_block->type);
1094                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1095                                         /* try offset */
1096                                         val = GUINT32_TO_LE (ex_info->start);
1097                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1098                                         /* need fault, too, probably */
1099                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1100                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1101                                         else
1102                                                 val = GUINT32_TO_LE (ex_info->len);
1103                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1104                                         /* handler offset */
1105                                         val = GUINT32_TO_LE (ex_block->start);
1106                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1107                                         /* handler len */
1108                                         val = GUINT32_TO_LE (ex_block->len);
1109                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1110                                         finally_start = ex_block->start + ex_block->len;
1111                                         if (ex_block->extype) {
1112                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1113                                         } else {
1114                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1115                                                         val = ex_block->filter_offset;
1116                                                 else
1117                                                         val = 0;
1118                                         }
1119                                         val = GUINT32_TO_LE (val);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1122                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1123                                 }
1124                         } else {
1125                                 g_error ("No clauses for ex info block %d", i);
1126                         }
1127                 }
1128         }
1129         return assembly->text_rva + idx;
1130 }
1131
1132 static guint32
1133 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1134 {
1135         int i;
1136         MonoDynamicTable *table;
1137         guint32 *values;
1138         
1139         table = &assembly->tables [table_idx];
1140
1141         g_assert (col < table->columns);
1142
1143         values = table->values + table->columns;
1144         for (i = 1; i <= table->rows; ++i) {
1145                 if (values [col] == token)
1146                         return i;
1147                 values += table->columns;
1148         }
1149         return 0;
1150 }
1151
1152 /*
1153  * LOCKING: Acquires the loader lock. 
1154  */
1155 static MonoCustomAttrInfo*
1156 lookup_custom_attr (MonoImage *image, gpointer member)
1157 {
1158         MonoCustomAttrInfo* res;
1159
1160         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1161
1162         if (!res)
1163                 return NULL;
1164
1165         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1166         res->cached = 0;
1167         return res;
1168 }
1169
1170 static gboolean
1171 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1172 {
1173         /* FIXME: Need to do more checks */
1174         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1175                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1176
1177                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1178                         return FALSE;
1179         }
1180
1181         return TRUE;
1182 }
1183
1184 static MonoCustomAttrInfo*
1185 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1186 {
1187         int i, index, count, not_visible;
1188         MonoCustomAttrInfo *ainfo;
1189         MonoReflectionCustomAttr *cattr;
1190
1191         if (!cattrs)
1192                 return NULL;
1193         /* FIXME: check in assembly the Run flag is set */
1194
1195         count = mono_array_length (cattrs);
1196
1197         /* Skip nonpublic attributes since MS.NET seems to do the same */
1198         /* FIXME: This needs to be done more globally */
1199         not_visible = 0;
1200         for (i = 0; i < count; ++i) {
1201                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1202                 if (!custom_attr_visible (image, cattr))
1203                         not_visible ++;
1204         }
1205         count -= not_visible;
1206
1207         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1208
1209         ainfo->image = image;
1210         ainfo->num_attrs = count;
1211         ainfo->cached = alloc_img != NULL;
1212         index = 0;
1213         for (i = 0; i < count; ++i) {
1214                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1215                 if (custom_attr_visible (image, cattr)) {
1216                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1217                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1218                         ainfo->attrs [index].ctor = cattr->ctor->method;
1219                         ainfo->attrs [index].data = saved;
1220                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1221                         index ++;
1222                 }
1223         }
1224
1225         return ainfo;
1226 }
1227
1228 #ifndef DISABLE_REFLECTION_EMIT
1229 /*
1230  * LOCKING: Acquires the loader lock. 
1231  */
1232 static void
1233 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1234 {
1235         MonoCustomAttrInfo *ainfo, *tmp;
1236
1237         if (!cattrs || !mono_array_length (cattrs))
1238                 return;
1239
1240         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1241
1242         mono_loader_lock ();
1243         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1244         if (tmp)
1245                 mono_custom_attrs_free (tmp);
1246         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1247         mono_loader_unlock ();
1248
1249 }
1250 #endif
1251
1252 void
1253 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1254 {
1255         if (!ainfo->cached)
1256                 g_free (ainfo);
1257 }
1258
1259 /*
1260  * idx is the table index of the object
1261  * type is one of MONO_CUSTOM_ATTR_*
1262  */
1263 static void
1264 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1265 {
1266         MonoDynamicTable *table;
1267         MonoReflectionCustomAttr *cattr;
1268         guint32 *values;
1269         guint32 count, i, token;
1270         char blob_size [6];
1271         char *p = blob_size;
1272         
1273         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1274         if (!cattrs)
1275                 return;
1276         count = mono_array_length (cattrs);
1277         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1278         table->rows += count;
1279         alloc_table (table, table->rows);
1280         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1281         idx <<= MONO_CUSTOM_ATTR_BITS;
1282         idx |= type;
1283         for (i = 0; i < count; ++i) {
1284                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1285                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1286                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1287                 type = mono_metadata_token_index (token);
1288                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1289                 switch (mono_metadata_token_table (token)) {
1290                 case MONO_TABLE_METHOD:
1291                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1292                         break;
1293                 case MONO_TABLE_MEMBERREF:
1294                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1295                         break;
1296                 default:
1297                         g_warning ("got wrong token in custom attr");
1298                         continue;
1299                 }
1300                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1301                 p = blob_size;
1302                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1303                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1304                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1305                 values += MONO_CUSTOM_ATTR_SIZE;
1306                 ++table->next_idx;
1307         }
1308 }
1309
1310 static void
1311 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1312 {
1313         MonoDynamicTable *table;
1314         guint32 *values;
1315         guint32 count, i, idx;
1316         MonoReflectionPermissionSet *perm;
1317
1318         if (!permissions)
1319                 return;
1320
1321         count = mono_array_length (permissions);
1322         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1323         table->rows += count;
1324         alloc_table (table, table->rows);
1325
1326         for (i = 0; i < mono_array_length (permissions); ++i) {
1327                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1328
1329                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1330
1331                 idx = mono_metadata_token_index (parent_token);
1332                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1333                 switch (mono_metadata_token_table (parent_token)) {
1334                 case MONO_TABLE_TYPEDEF:
1335                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1336                         break;
1337                 case MONO_TABLE_METHOD:
1338                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1339                         break;
1340                 case MONO_TABLE_ASSEMBLY:
1341                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1342                         break;
1343                 default:
1344                         g_assert_not_reached ();
1345                 }
1346
1347                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1348                 values [MONO_DECL_SECURITY_PARENT] = idx;
1349                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1350
1351                 ++table->next_idx;
1352         }
1353 }
1354
1355 /*
1356  * Fill in the MethodDef and ParamDef tables for a method.
1357  * This is used for both normal methods and constructors.
1358  */
1359 static void
1360 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1361 {
1362         MonoDynamicTable *table;
1363         guint32 *values;
1364         guint i, count;
1365
1366         /* room in this table is already allocated */
1367         table = &assembly->tables [MONO_TABLE_METHOD];
1368         *mb->table_idx = table->next_idx ++;
1369         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1370         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1371         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1372         values [MONO_METHOD_FLAGS] = mb->attrs;
1373         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1374         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1375         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1376         
1377         table = &assembly->tables [MONO_TABLE_PARAM];
1378         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1379
1380         mono_image_add_decl_security (assembly, 
1381                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1382
1383         if (mb->pinfo) {
1384                 MonoDynamicTable *mtable;
1385                 guint32 *mvalues;
1386                 
1387                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1388                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1389                 
1390                 count = 0;
1391                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1392                         if (mono_array_get (mb->pinfo, gpointer, i))
1393                                 count++;
1394                 }
1395                 table->rows += count;
1396                 alloc_table (table, table->rows);
1397                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1398                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1399                         MonoReflectionParamBuilder *pb;
1400                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1401                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1402                                 values [MONO_PARAM_SEQUENCE] = i;
1403                                 if (pb->name != NULL) {
1404                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1405                                 } else {
1406                                         values [MONO_PARAM_NAME] = 0;
1407                                 }
1408                                 values += MONO_PARAM_SIZE;
1409                                 if (pb->marshal_info) {
1410                                         mtable->rows++;
1411                                         alloc_table (mtable, mtable->rows);
1412                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1413                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1414                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1415                                 }
1416                                 pb->table_idx = table->next_idx++;
1417                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1418                                         guint32 field_type = 0;
1419                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1420                                         mtable->rows ++;
1421                                         alloc_table (mtable, mtable->rows);
1422                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1423                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1424                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1425                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1426                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1427                                 }
1428                         }
1429                 }
1430         }
1431 }
1432
1433 #ifndef DISABLE_REFLECTION_EMIT
1434 static void
1435 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1436 {
1437         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1438
1439         rmb->ilgen = mb->ilgen;
1440         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1441         rmb->parameters = mb->parameters;
1442         rmb->generic_params = mb->generic_params;
1443         rmb->generic_container = mb->generic_container;
1444         rmb->opt_types = NULL;
1445         rmb->pinfo = mb->pinfo;
1446         rmb->attrs = mb->attrs;
1447         rmb->iattrs = mb->iattrs;
1448         rmb->call_conv = mb->call_conv;
1449         rmb->code = mb->code;
1450         rmb->type = mb->type;
1451         rmb->name = mb->name;
1452         rmb->table_idx = &mb->table_idx;
1453         rmb->init_locals = mb->init_locals;
1454         rmb->skip_visibility = FALSE;
1455         rmb->return_modreq = mb->return_modreq;
1456         rmb->return_modopt = mb->return_modopt;
1457         rmb->param_modreq = mb->param_modreq;
1458         rmb->param_modopt = mb->param_modopt;
1459         rmb->permissions = mb->permissions;
1460         rmb->mhandle = mb->mhandle;
1461         rmb->nrefs = 0;
1462         rmb->refs = NULL;
1463
1464         if (mb->dll) {
1465                 rmb->charset = mb->charset;
1466                 rmb->extra_flags = mb->extra_flags;
1467                 rmb->native_cc = mb->native_cc;
1468                 rmb->dllentry = mb->dllentry;
1469                 rmb->dll = mb->dll;
1470         }
1471 }
1472
1473 static void
1474 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1475 {
1476         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1477
1478         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1479
1480         rmb->ilgen = mb->ilgen;
1481         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1482         rmb->parameters = mb->parameters;
1483         rmb->generic_params = NULL;
1484         rmb->generic_container = NULL;
1485         rmb->opt_types = NULL;
1486         rmb->pinfo = mb->pinfo;
1487         rmb->attrs = mb->attrs;
1488         rmb->iattrs = mb->iattrs;
1489         rmb->call_conv = mb->call_conv;
1490         rmb->code = NULL;
1491         rmb->type = mb->type;
1492         rmb->name = mono_string_new (mono_domain_get (), name);
1493         rmb->table_idx = &mb->table_idx;
1494         rmb->init_locals = mb->init_locals;
1495         rmb->skip_visibility = FALSE;
1496         rmb->return_modreq = NULL;
1497         rmb->return_modopt = NULL;
1498         rmb->param_modreq = mb->param_modreq;
1499         rmb->param_modopt = mb->param_modopt;
1500         rmb->permissions = mb->permissions;
1501         rmb->mhandle = mb->mhandle;
1502         rmb->nrefs = 0;
1503         rmb->refs = NULL;
1504 }
1505
1506 static void
1507 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1508 {
1509         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1510
1511         rmb->ilgen = mb->ilgen;
1512         rmb->rtype = mb->rtype;
1513         rmb->parameters = mb->parameters;
1514         rmb->generic_params = NULL;
1515         rmb->generic_container = NULL;
1516         rmb->opt_types = NULL;
1517         rmb->pinfo = NULL;
1518         rmb->attrs = mb->attrs;
1519         rmb->iattrs = 0;
1520         rmb->call_conv = mb->call_conv;
1521         rmb->code = NULL;
1522         rmb->type = (MonoObject *) mb->owner;
1523         rmb->name = mb->name;
1524         rmb->table_idx = NULL;
1525         rmb->init_locals = mb->init_locals;
1526         rmb->skip_visibility = mb->skip_visibility;
1527         rmb->return_modreq = NULL;
1528         rmb->return_modopt = NULL;
1529         rmb->param_modreq = NULL;
1530         rmb->param_modopt = NULL;
1531         rmb->permissions = NULL;
1532         rmb->mhandle = mb->mhandle;
1533         rmb->nrefs = 0;
1534         rmb->refs = NULL;
1535 }       
1536 #endif
1537
1538 static void
1539 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1540 {
1541         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1542         MonoDynamicTable *table;
1543         guint32 *values;
1544         guint32 tok;
1545
1546         if (!mb->override_method)
1547                 return;
1548
1549         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1550         table->rows ++;
1551         alloc_table (table, table->rows);
1552         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1553         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1554         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1555
1556         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1557         switch (mono_metadata_token_table (tok)) {
1558         case MONO_TABLE_MEMBERREF:
1559                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1560                 break;
1561         case MONO_TABLE_METHOD:
1562                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1563                 break;
1564         default:
1565                 g_assert_not_reached ();
1566         }
1567         values [MONO_METHODIMPL_DECLARATION] = tok;
1568 }
1569
1570 #ifndef DISABLE_REFLECTION_EMIT
1571 static void
1572 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1573 {
1574         MonoDynamicTable *table;
1575         guint32 *values;
1576         ReflectionMethodBuilder rmb;
1577         int i;
1578
1579         reflection_methodbuilder_from_method_builder (&rmb, mb);
1580
1581         mono_image_basic_method (&rmb, assembly);
1582         mb->table_idx = *rmb.table_idx;
1583
1584         if (mb->dll) { /* It's a P/Invoke method */
1585                 guint32 moduleref;
1586                 /* map CharSet values to on-disk values */
1587                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1588                 int extra_flags = mb->extra_flags;
1589                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1590                 table->rows ++;
1591                 alloc_table (table, table->rows);
1592                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1593                 
1594                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1595                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1596                 if (mb->dllentry)
1597                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1598                 else
1599                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1600                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1601                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1602                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1603                         table->rows ++;
1604                         alloc_table (table, table->rows);
1605                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1606                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1607                 }
1608         }
1609
1610         if (mb->generic_params) {
1611                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1612                 table->rows += mono_array_length (mb->generic_params);
1613                 alloc_table (table, table->rows);
1614                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1615                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1616
1617                         mono_image_get_generic_param_info (
1618                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1619                 }
1620         }
1621
1622 }
1623
1624 static void
1625 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1626 {
1627         ReflectionMethodBuilder rmb;
1628
1629         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1630
1631         mono_image_basic_method (&rmb, assembly);
1632         mb->table_idx = *rmb.table_idx;
1633 }
1634 #endif
1635
1636 static char*
1637 type_get_fully_qualified_name (MonoType *type)
1638 {
1639         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1640 }
1641
1642 static char*
1643 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1644         MonoClass *klass;
1645         MonoAssembly *ta;
1646
1647         klass = mono_class_from_mono_type (type);
1648         if (!klass) 
1649                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1650         ta = klass->image->assembly;
1651         if (ta->dynamic || (ta == ass)) {
1652                 if (klass->generic_class || klass->generic_container)
1653                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1654                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1655                 else
1656                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1657         }
1658
1659         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1660 }
1661
1662 #ifndef DISABLE_REFLECTION_EMIT
1663 /*field_image is the image to which the eventual custom mods have been encoded against*/
1664 static guint32
1665 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1666 {
1667         SigBuffer buf;
1668         guint32 idx, i, token;
1669
1670         if (!assembly->save)
1671                 return 0;
1672
1673         sigbuffer_init (&buf, 32);
1674         
1675         sigbuffer_add_value (&buf, 0x06);
1676         /* encode custom attributes before the type */
1677         if (type->num_mods) {
1678                 for (i = 0; i < type->num_mods; ++i) {
1679                         if (field_image) {
1680                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1681                                 g_assert (class);
1682                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1683                         } else {
1684                                 token = type->modifiers [i].token;
1685                         }
1686
1687                         if (type->modifiers [i].required)
1688                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1689                         else
1690                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1691
1692                         sigbuffer_add_value (&buf, token);
1693                 }
1694         }
1695         encode_type (assembly, type, &buf);
1696         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1697         sigbuffer_free (&buf);
1698         return idx;
1699 }
1700 #endif
1701
1702 static guint32
1703 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1704 {
1705         SigBuffer buf;
1706         guint32 idx;
1707         guint32 typespec = 0;
1708         MonoType *type;
1709         MonoClass *class;
1710
1711         init_type_builder_generics (fb->type);
1712
1713         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1714         class = mono_class_from_mono_type (type);
1715
1716         sigbuffer_init (&buf, 32);
1717         
1718         sigbuffer_add_value (&buf, 0x06);
1719         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1720         /* encode custom attributes before the type */
1721
1722         if (class->generic_container)
1723                 typespec = create_typespec (assembly, type);
1724
1725         if (typespec) {
1726                 MonoGenericClass *gclass;
1727                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1728                 encode_generic_class (assembly, gclass, &buf);
1729         } else {
1730                 encode_type (assembly, type, &buf);
1731         }
1732         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1733         sigbuffer_free (&buf);
1734         return idx;
1735 }
1736
1737 static guint32
1738 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1739         char blob_size [64];
1740         char *b = blob_size;
1741         char *p, *box_val;
1742         char* buf;
1743         guint32 idx = 0, len = 0, dummy = 0;
1744 #ifdef ARM_FPU_FPA
1745 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1746         guint32 fpa_double [2];
1747         guint32 *fpa_p;
1748 #endif
1749 #endif
1750         
1751         p = buf = g_malloc (64);
1752         if (!val) {
1753                 *ret_type = MONO_TYPE_CLASS;
1754                 len = 4;
1755                 box_val = (char*)&dummy;
1756         } else {
1757                 box_val = ((char*)val) + sizeof (MonoObject);
1758                 *ret_type = val->vtable->klass->byval_arg.type;
1759         }
1760 handle_enum:
1761         switch (*ret_type) {
1762         case MONO_TYPE_BOOLEAN:
1763         case MONO_TYPE_U1:
1764         case MONO_TYPE_I1:
1765                 len = 1;
1766                 break;
1767         case MONO_TYPE_CHAR:
1768         case MONO_TYPE_U2:
1769         case MONO_TYPE_I2:
1770                 len = 2;
1771                 break;
1772         case MONO_TYPE_U4:
1773         case MONO_TYPE_I4:
1774         case MONO_TYPE_R4:
1775                 len = 4;
1776                 break;
1777         case MONO_TYPE_U8:
1778         case MONO_TYPE_I8:
1779                 len = 8;
1780                 break;
1781         case MONO_TYPE_R8:
1782                 len = 8;
1783 #ifdef ARM_FPU_FPA
1784 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1785                 fpa_p = (guint32*)box_val;
1786                 fpa_double [0] = fpa_p [1];
1787                 fpa_double [1] = fpa_p [0];
1788                 box_val = (char*)fpa_double;
1789 #endif
1790 #endif
1791                 break;
1792         case MONO_TYPE_VALUETYPE: {
1793                 MonoClass *klass = val->vtable->klass;
1794                 
1795                 if (klass->enumtype) {
1796                         *ret_type = mono_class_enum_basetype (klass)->type;
1797                         goto handle_enum;
1798                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1799                         len = 8;
1800                 } else 
1801                         g_error ("we can't encode valuetypes, we should have never reached this line");
1802                 break;
1803         }
1804         case MONO_TYPE_CLASS:
1805                 break;
1806         case MONO_TYPE_STRING: {
1807                 MonoString *str = (MonoString*)val;
1808                 /* there is no signature */
1809                 len = str->length * 2;
1810                 mono_metadata_encode_value (len, b, &b);
1811 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1812                 {
1813                         char *swapped = g_malloc (2 * mono_string_length (str));
1814                         const char *p = (const char*)mono_string_chars (str);
1815
1816                         swap_with_size (swapped, p, 2, mono_string_length (str));
1817                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1818                         g_free (swapped);
1819                 }
1820 #else
1821                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1822 #endif
1823
1824                 g_free (buf);
1825                 return idx;
1826         }
1827         case MONO_TYPE_GENERICINST:
1828                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1829                 goto handle_enum;
1830         default:
1831                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1832         }
1833
1834         /* there is no signature */
1835         mono_metadata_encode_value (len, b, &b);
1836 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1837         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1838         swap_with_size (blob_size, box_val, len, 1);
1839         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1840 #else
1841         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1842 #endif
1843
1844         g_free (buf);
1845         return idx;
1846 }
1847
1848 static guint32
1849 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1850         char *str;
1851         SigBuffer buf;
1852         guint32 idx, len;
1853
1854         sigbuffer_init (&buf, 32);
1855
1856         sigbuffer_add_value (&buf, minfo->type);
1857
1858         switch (minfo->type) {
1859         case MONO_NATIVE_BYVALTSTR:
1860         case MONO_NATIVE_BYVALARRAY:
1861                 sigbuffer_add_value (&buf, minfo->count);
1862                 break;
1863         case MONO_NATIVE_LPARRAY:
1864                 if (minfo->eltype || minfo->has_size) {
1865                         sigbuffer_add_value (&buf, minfo->eltype);
1866                         if (minfo->has_size) {
1867                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1868                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1869
1870                                 /* LAMESPEC: ElemMult is undocumented */
1871                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1872                         }
1873                 }
1874                 break;
1875         case MONO_NATIVE_SAFEARRAY:
1876                 if (minfo->eltype)
1877                         sigbuffer_add_value (&buf, minfo->eltype);
1878                 break;
1879         case MONO_NATIVE_CUSTOM:
1880                 if (minfo->guid) {
1881                         str = mono_string_to_utf8 (minfo->guid);
1882                         len = strlen (str);
1883                         sigbuffer_add_value (&buf, len);
1884                         sigbuffer_add_mem (&buf, str, len);
1885                         g_free (str);
1886                 } else {
1887                         sigbuffer_add_value (&buf, 0);
1888                 }
1889                 /* native type name */
1890                 sigbuffer_add_value (&buf, 0);
1891                 /* custom marshaler type name */
1892                 if (minfo->marshaltype || minfo->marshaltyperef) {
1893                         if (minfo->marshaltyperef)
1894                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1895                         else
1896                                 str = mono_string_to_utf8 (minfo->marshaltype);
1897                         len = strlen (str);
1898                         sigbuffer_add_value (&buf, len);
1899                         sigbuffer_add_mem (&buf, str, len);
1900                         g_free (str);
1901                 } else {
1902                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1903                         sigbuffer_add_value (&buf, 0);
1904                 }
1905                 if (minfo->mcookie) {
1906                         str = mono_string_to_utf8 (minfo->mcookie);
1907                         len = strlen (str);
1908                         sigbuffer_add_value (&buf, len);
1909                         sigbuffer_add_mem (&buf, str, len);
1910                         g_free (str);
1911                 } else {
1912                         sigbuffer_add_value (&buf, 0);
1913                 }
1914                 break;
1915         default:
1916                 break;
1917         }
1918         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1919         sigbuffer_free (&buf);
1920         return idx;
1921 }
1922
1923 static void
1924 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1925 {
1926         MonoDynamicTable *table;
1927         guint32 *values;
1928
1929         /* maybe this fixup should be done in the C# code */
1930         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1931                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1932         table = &assembly->tables [MONO_TABLE_FIELD];
1933         fb->table_idx = table->next_idx ++;
1934         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1935         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1936         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1937         values [MONO_FIELD_FLAGS] = fb->attrs;
1938         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1939
1940         if (fb->offset != -1) {
1941                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1942                 table->rows ++;
1943                 alloc_table (table, table->rows);
1944                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1945                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1946                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1947         }
1948         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1949                 guint32 field_type = 0;
1950                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1951                 table->rows ++;
1952                 alloc_table (table, table->rows);
1953                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1954                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1955                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1956                 values [MONO_CONSTANT_TYPE] = field_type;
1957                 values [MONO_CONSTANT_PADDING] = 0;
1958         }
1959         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1960                 guint32 rva_idx;
1961                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1962                 table->rows ++;
1963                 alloc_table (table, table->rows);
1964                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1965                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1966                 /*
1967                  * We store it in the code section because it's simpler for now.
1968                  */
1969                 if (fb->rva_data) {
1970                         if (mono_array_length (fb->rva_data) >= 10)
1971                                 stream_data_align (&assembly->code);
1972                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1973                 } else
1974                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1975                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1976         }
1977         if (fb->marshal_info) {
1978                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1979                 table->rows ++;
1980                 alloc_table (table, table->rows);
1981                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1982                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1983                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1984         }
1985 }
1986
1987 static guint32
1988 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1989 {
1990         SigBuffer buf;
1991         guint32 nparams = 0;
1992         MonoReflectionMethodBuilder *mb = fb->get_method;
1993         MonoReflectionMethodBuilder *smb = fb->set_method;
1994         guint32 idx, i;
1995
1996         if (mb && mb->parameters)
1997                 nparams = mono_array_length (mb->parameters);
1998         if (!mb && smb && smb->parameters)
1999                 nparams = mono_array_length (smb->parameters) - 1;
2000         sigbuffer_init (&buf, 32);
2001         if (fb->call_conv & 0x20)
2002                 sigbuffer_add_byte (&buf, 0x28);
2003         else
2004                 sigbuffer_add_byte (&buf, 0x08);
2005         sigbuffer_add_value (&buf, nparams);
2006         if (mb) {
2007                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2008                 for (i = 0; i < nparams; ++i) {
2009                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2010                         encode_reflection_type (assembly, pt, &buf);
2011                 }
2012         } else if (smb && smb->parameters) {
2013                 /* the property type is the last param */
2014                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2015                 for (i = 0; i < nparams; ++i) {
2016                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2017                         encode_reflection_type (assembly, pt, &buf);
2018                 }
2019         } else {
2020                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2021         }
2022
2023         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2024         sigbuffer_free (&buf);
2025         return idx;
2026 }
2027
2028 static void
2029 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2030 {
2031         MonoDynamicTable *table;
2032         guint32 *values;
2033         guint num_methods = 0;
2034         guint32 semaidx;
2035
2036         /* 
2037          * we need to set things in the following tables:
2038          * PROPERTYMAP (info already filled in _get_type_info ())
2039          * PROPERTY    (rows already preallocated in _get_type_info ())
2040          * METHOD      (method info already done with the generic method code)
2041          * METHODSEMANTICS
2042          * CONSTANT
2043          */
2044         table = &assembly->tables [MONO_TABLE_PROPERTY];
2045         pb->table_idx = table->next_idx ++;
2046         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2047         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2048         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2049         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2050
2051         /* FIXME: we still don't handle 'other' methods */
2052         if (pb->get_method) num_methods ++;
2053         if (pb->set_method) num_methods ++;
2054
2055         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2056         table->rows += num_methods;
2057         alloc_table (table, table->rows);
2058
2059         if (pb->get_method) {
2060                 semaidx = table->next_idx ++;
2061                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2062                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2063                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2064                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2065         }
2066         if (pb->set_method) {
2067                 semaidx = table->next_idx ++;
2068                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2069                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2070                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2071                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2072         }
2073         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2074                 guint32 field_type = 0;
2075                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2076                 table->rows ++;
2077                 alloc_table (table, table->rows);
2078                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2079                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2080                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2081                 values [MONO_CONSTANT_TYPE] = field_type;
2082                 values [MONO_CONSTANT_PADDING] = 0;
2083         }
2084 }
2085
2086 static void
2087 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2088 {
2089         MonoDynamicTable *table;
2090         guint32 *values;
2091         guint num_methods = 0;
2092         guint32 semaidx;
2093
2094         /* 
2095          * we need to set things in the following tables:
2096          * EVENTMAP (info already filled in _get_type_info ())
2097          * EVENT    (rows already preallocated in _get_type_info ())
2098          * METHOD      (method info already done with the generic method code)
2099          * METHODSEMANTICS
2100          */
2101         table = &assembly->tables [MONO_TABLE_EVENT];
2102         eb->table_idx = table->next_idx ++;
2103         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2104         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2105         values [MONO_EVENT_FLAGS] = eb->attrs;
2106         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2107
2108         /*
2109          * FIXME: we still don't handle 'other' methods 
2110          */
2111         if (eb->add_method) num_methods ++;
2112         if (eb->remove_method) num_methods ++;
2113         if (eb->raise_method) num_methods ++;
2114
2115         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2116         table->rows += num_methods;
2117         alloc_table (table, table->rows);
2118
2119         if (eb->add_method) {
2120                 semaidx = table->next_idx ++;
2121                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2122                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2123                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2124                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2125         }
2126         if (eb->remove_method) {
2127                 semaidx = table->next_idx ++;
2128                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2129                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2130                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2131                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2132         }
2133         if (eb->raise_method) {
2134                 semaidx = table->next_idx ++;
2135                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2136                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2137                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2138                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2139         }
2140 }
2141
2142 static void
2143 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2144 {
2145         MonoDynamicTable *table;
2146         guint32 num_constraints, i;
2147         guint32 *values;
2148         guint32 table_idx;
2149
2150         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2151         num_constraints = gparam->iface_constraints ?
2152                 mono_array_length (gparam->iface_constraints) : 0;
2153         table->rows += num_constraints;
2154         if (gparam->base_type)
2155                 table->rows++;
2156         alloc_table (table, table->rows);
2157
2158         if (gparam->base_type) {
2159                 table_idx = table->next_idx ++;
2160                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2161
2162                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2163                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2164                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2165         }
2166
2167         for (i = 0; i < num_constraints; i++) {
2168                 MonoReflectionType *constraint = mono_array_get (
2169                         gparam->iface_constraints, gpointer, i);
2170
2171                 table_idx = table->next_idx ++;
2172                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2173
2174                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176                         assembly, mono_reflection_type_get_handle (constraint));
2177         }
2178 }
2179
2180 static void
2181 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2182 {
2183         GenericParamTableEntry *entry;
2184
2185         /*
2186          * The GenericParam table must be sorted according to the `owner' field.
2187          * We need to do this sorting prior to writing the GenericParamConstraint
2188          * table, since we have to use the final GenericParam table indices there
2189          * and they must also be sorted.
2190          */
2191
2192         entry = g_new0 (GenericParamTableEntry, 1);
2193         entry->owner = owner;
2194         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2195         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2196         entry->gparam = gparam;
2197         
2198         g_ptr_array_add (assembly->gen_params, entry);
2199 }
2200
2201 static void
2202 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2203 {
2204         MonoDynamicTable *table;
2205         MonoGenericParam *param;
2206         guint32 *values;
2207         guint32 table_idx;
2208
2209         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2210         table_idx = table->next_idx ++;
2211         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2212
2213         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2214
2215         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2216         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2217         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2218         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2219
2220         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2221
2222         encode_constraints (entry->gparam, table_idx, assembly);
2223 }
2224
2225 static guint32
2226 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2227 {
2228         MonoDynamicTable *table;
2229         guint32 token;
2230         guint32 *values;
2231         guint32 cols [MONO_ASSEMBLY_SIZE];
2232         const char *pubkey;
2233         guint32 publen;
2234
2235         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2236                 return token;
2237
2238         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2239                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2240                 token = table->next_idx ++;
2241                 table->rows ++;
2242                 alloc_table (table, table->rows);
2243                 values = table->values + token * MONO_MODULEREF_SIZE;
2244                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2245
2246                 token <<= MONO_RESOLTION_SCOPE_BITS;
2247                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2248                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2249
2250                 return token;
2251         }
2252         
2253         if (image->assembly->dynamic)
2254                 /* FIXME: */
2255                 memset (cols, 0, sizeof (cols));
2256         else {
2257                 /* image->assembly->image is the manifest module */
2258                 image = image->assembly->image;
2259                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2260         }
2261
2262         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2263         token = table->next_idx ++;
2264         table->rows ++;
2265         alloc_table (table, table->rows);
2266         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2267         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2268         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2269         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2270         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2271         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2272         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2273         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2274         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2275
2276         if (strcmp ("", image->assembly->aname.culture)) {
2277                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2278                                 image->assembly->aname.culture);
2279         }
2280
2281         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2282                 guchar pubtoken [9];
2283                 pubtoken [0] = 8;
2284                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2285                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2286         } else {
2287                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2288         }
2289         token <<= MONO_RESOLTION_SCOPE_BITS;
2290         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2291         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2292         return token;
2293 }
2294
2295 static guint32
2296 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2297 {
2298         MonoDynamicTable *table;
2299         guint32 *values;
2300         guint32 token;
2301         SigBuffer buf;
2302
2303         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2304                 return token;
2305
2306         sigbuffer_init (&buf, 32);
2307         switch (type->type) {
2308         case MONO_TYPE_FNPTR:
2309         case MONO_TYPE_PTR:
2310         case MONO_TYPE_SZARRAY:
2311         case MONO_TYPE_ARRAY:
2312         case MONO_TYPE_VAR:
2313         case MONO_TYPE_MVAR:
2314         case MONO_TYPE_GENERICINST:
2315                 encode_type (assembly, type, &buf);
2316                 break;
2317         case MONO_TYPE_CLASS:
2318         case MONO_TYPE_VALUETYPE: {
2319                 MonoClass *k = mono_class_from_mono_type (type);
2320                 if (!k || !k->generic_container) {
2321                         sigbuffer_free (&buf);
2322                         return 0;
2323                 }
2324                 encode_type (assembly, type, &buf);
2325                 break;
2326         }
2327         default:
2328                 sigbuffer_free (&buf);
2329                 return 0;
2330         }
2331
2332         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2333         if (assembly->save) {
2334                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2335                 alloc_table (table, table->rows + 1);
2336                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2337                 values [MONO_TYPESPEC_SIGNATURE] = token;
2338         }
2339         sigbuffer_free (&buf);
2340
2341         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2342         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2343         table->next_idx ++;
2344         return token;
2345 }
2346
2347 static guint32
2348 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2349 {
2350         MonoDynamicTable *table;
2351         guint32 *values;
2352         guint32 token, scope, enclosing;
2353         MonoClass *klass;
2354
2355         /* if the type requires a typespec, we must try that first*/
2356         if (try_typespec && (token = create_typespec (assembly, type)))
2357                 return token;
2358         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2359         if (token)
2360                 return token;
2361         klass = mono_class_from_mono_type (type);
2362         if (!klass)
2363                 klass = mono_class_from_mono_type (type);
2364
2365         /*
2366          * If it's in the same module and not a generic type parameter:
2367          */
2368         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2369                         (type->type != MONO_TYPE_MVAR)) {
2370                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2371                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2372                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2373                 return token;
2374         }
2375
2376         if (klass->nested_in) {
2377                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2378                 /* get the typeref idx of the enclosing type */
2379                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2380                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2381         } else {
2382                 scope = resolution_scope_from_image (assembly, klass->image);
2383         }
2384         table = &assembly->tables [MONO_TABLE_TYPEREF];
2385         if (assembly->save) {
2386                 alloc_table (table, table->rows + 1);
2387                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2388                 values [MONO_TYPEREF_SCOPE] = scope;
2389                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2390                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2391         }
2392         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2393         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2394         table->next_idx ++;
2395         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2396         return token;
2397 }
2398
2399 /*
2400  * Despite the name, we handle also TypeSpec (with the above helper).
2401  */
2402 static guint32
2403 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2404 {
2405         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2406 }
2407
2408 #ifndef DISABLE_REFLECTION_EMIT
2409 static guint32
2410 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2411 {
2412         MonoDynamicTable *table;
2413         guint32 *values;
2414         guint32 token, pclass;
2415
2416         switch (parent & MONO_TYPEDEFORREF_MASK) {
2417         case MONO_TYPEDEFORREF_TYPEREF:
2418                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2419                 break;
2420         case MONO_TYPEDEFORREF_TYPESPEC:
2421                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2422                 break;
2423         case MONO_TYPEDEFORREF_TYPEDEF:
2424                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2425                 break;
2426         default:
2427                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2428                 return 0;
2429         }
2430         /* extract the index */
2431         parent >>= MONO_TYPEDEFORREF_BITS;
2432
2433         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2434
2435         if (assembly->save) {
2436                 alloc_table (table, table->rows + 1);
2437                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2438                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2439                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2440                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2441         }
2442
2443         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2444         table->next_idx ++;
2445
2446         return token;
2447 }
2448
2449 /*
2450  * Insert a memberef row into the metadata: the token that point to the memberref
2451  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2452  * mono_image_get_fieldref_token()).
2453  * The sig param is an index to an already built signature.
2454  */
2455 static guint32
2456 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2457 {
2458         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2459         return mono_image_add_memberef_row (assembly, parent, name, sig);
2460 }
2461
2462
2463 static guint32
2464 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2465 {
2466         guint32 token;
2467         MonoMethodSignature *sig;
2468         
2469         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2470
2471         if (create_typespec) {
2472                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2473                 if (token)
2474                         return token;
2475         } 
2476
2477         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2478         if (token && !create_typespec)
2479                 return token;
2480
2481         g_assert (!method->is_inflated);
2482         if (!token) {
2483                 /*
2484                  * A methodref signature can't contain an unmanaged calling convention.
2485                  */
2486                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2487                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2488                         sig->call_convention = MONO_CALL_DEFAULT;
2489                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2490                         method->name,  method_encode_signature (assembly, sig));
2491                 g_free (sig);
2492                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2493         }
2494
2495         if (create_typespec) {
2496                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2497                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2498                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2499
2500                 if (assembly->save) {
2501                         guint32 *values;
2502
2503                         alloc_table (table, table->rows + 1);
2504                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2505                         values [MONO_METHODSPEC_METHOD] = token;
2506                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2507                 }
2508
2509                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2510                 table->next_idx ++;
2511                 /*methodspec and memberef tokens are diferent, */
2512                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2513                 return token;
2514         }
2515         return token;
2516 }
2517
2518 static guint32
2519 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2520 {
2521         guint32 token, parent, sig;
2522         ReflectionMethodBuilder rmb;
2523         char *name;
2524         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2525         
2526         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2527         if (token)
2528                 return token;
2529
2530         name = mono_string_to_utf8 (method->name);
2531         reflection_methodbuilder_from_method_builder (&rmb, method);
2532
2533         /*
2534          * A methodref signature can't contain an unmanaged calling convention.
2535          * Since some flags are encoded as part of call_conv, we need to check against it.
2536         */
2537         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2538                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2539
2540         sig = method_builder_encode_signature (assembly, &rmb);
2541
2542         if (tb->generic_params)
2543                 parent = create_generic_typespec (assembly, tb);
2544         else
2545                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2546
2547         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2548
2549         g_free (name);
2550         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2551         return token;
2552 }
2553
2554 static guint32
2555 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2556                                      const gchar *name, guint32 sig)
2557 {
2558         MonoDynamicTable *table;
2559         guint32 token;
2560         guint32 *values;
2561         
2562         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2563
2564         if (assembly->save) {
2565                 alloc_table (table, table->rows + 1);
2566                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2567                 values [MONO_MEMBERREF_CLASS] = original;
2568                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2569                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2570         }
2571
2572         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2573         table->next_idx ++;
2574
2575         return token;
2576 }
2577
2578 static guint32
2579 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2580 {
2581         SigBuffer buf;
2582         int i;
2583         guint32 nparams = mono_array_length (mb->generic_params);
2584         guint32 idx;
2585
2586         if (!assembly->save)
2587                 return 0;
2588
2589         sigbuffer_init (&buf, 32);
2590
2591         sigbuffer_add_value (&buf, 0xa);
2592         sigbuffer_add_value (&buf, nparams);
2593
2594         for (i = 0; i < nparams; i++) {
2595                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2596                 sigbuffer_add_value (&buf, i);
2597         }
2598
2599         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2600         sigbuffer_free (&buf);
2601         return idx;
2602 }
2603
2604 static guint32
2605 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2606 {
2607         MonoDynamicTable *table;
2608         guint32 *values;
2609         guint32 token, mtoken = 0;
2610
2611         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2612         if (token)
2613                 return token;
2614
2615         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2616
2617         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2618         switch (mono_metadata_token_table (mtoken)) {
2619         case MONO_TABLE_MEMBERREF:
2620                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2621                 break;
2622         case MONO_TABLE_METHOD:
2623                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2624                 break;
2625         default:
2626                 g_assert_not_reached ();
2627         }
2628
2629         if (assembly->save) {
2630                 alloc_table (table, table->rows + 1);
2631                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2632                 values [MONO_METHODSPEC_METHOD] = mtoken;
2633                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2634         }
2635
2636         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2637         table->next_idx ++;
2638
2639         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2640         return token;
2641 }
2642
2643 static guint32
2644 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2645 {
2646         guint32 token;
2647
2648         if (mb->generic_params && create_methodspec) 
2649                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2650
2651         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2652         if (token)
2653                 return token;
2654
2655         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2656         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2657         return token;
2658 }
2659
2660 static guint32
2661 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2662 {
2663         guint32 token, parent, sig;
2664         ReflectionMethodBuilder rmb;
2665         char *name;
2666         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2667         
2668         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2669         if (token)
2670                 return token;
2671
2672         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2673
2674         if (tb->generic_params)
2675                 parent = create_generic_typespec (assembly, tb);
2676         else
2677                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2678         
2679         name = mono_string_to_utf8 (rmb.name);
2680         sig = method_builder_encode_signature (assembly, &rmb);
2681
2682         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2683
2684         g_free (name);
2685         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2686         return token;
2687 }
2688 #endif
2689
2690 static gboolean
2691 is_field_on_inst (MonoClassField *field)
2692 {
2693         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2694 }
2695
2696 /*
2697  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2698  */
2699 static MonoType*
2700 get_field_on_inst_generic_type (MonoClassField *field)
2701 {
2702         MonoClass *class, *gtd;
2703         MonoDynamicGenericClass *dgclass;
2704         int field_index;
2705
2706         g_assert (is_field_on_inst (field));
2707
2708         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2709
2710         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2711                 field_index = field - dgclass->fields;
2712                 return dgclass->field_generic_types [field_index];              
2713         }
2714
2715         class = field->parent;
2716         gtd = class->generic_class->container_class;
2717
2718         if (field >= class->fields && field - class->fields < class->field.count) {
2719                 field_index = field - class->fields;
2720                 return gtd->fields [field_index].type;
2721         }
2722
2723         g_assert_not_reached ();
2724         return 0;
2725 }
2726
2727 #ifndef DISABLE_REFLECTION_EMIT
2728 static guint32
2729 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2730 {
2731         MonoType *type;
2732         guint32 token;
2733
2734         g_assert (field);
2735         g_assert (field->parent);
2736
2737         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2738         if (token)
2739                 return token;
2740
2741         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2742                 int index = field - field->parent->fields;
2743                 type = field->parent->generic_class->container_class->fields [index].type;
2744         } else {
2745                 if (is_field_on_inst (field))
2746                         type = get_field_on_inst_generic_type (field);
2747                 else
2748                         type = mono_field_get_type (field);
2749         }
2750         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2751                                                                                         mono_field_get_name (field),
2752                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2753         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2754         return token;
2755 }
2756
2757 static guint32
2758 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2759 {
2760         guint32 token;
2761         MonoClass *klass;
2762         MonoGenericClass *gclass;
2763         MonoDynamicGenericClass *dgclass;
2764         MonoType *type;
2765         char *name;
2766
2767         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2768         if (token)
2769                 return token;
2770         if (is_sre_field_builder (mono_object_class (f->fb))) {
2771                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2772                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2773                 klass = mono_class_from_mono_type (type);
2774                 gclass = type->data.generic_class;
2775                 g_assert (gclass->is_dynamic);
2776                 dgclass = (MonoDynamicGenericClass *) gclass;
2777
2778                 name = mono_string_to_utf8 (fb->name);
2779                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2780                                                                                                 field_encode_signature (assembly, fb));
2781                 g_free (name);          
2782         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2783                 guint32 sig;
2784                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2785
2786                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2787                 klass = mono_class_from_mono_type (type);
2788
2789                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2790                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2791         } else {
2792                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2793                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2794         }
2795
2796         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2797         return token;
2798 }
2799
2800 static guint32
2801 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2802 {
2803         guint32 sig, token;
2804         MonoClass *klass;
2805         MonoGenericClass *gclass;
2806         MonoType *type;
2807
2808         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2809
2810         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2811         if (token)
2812                 return token;
2813
2814         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2815                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2816                 MonoDynamicGenericClass *dgclass;
2817                 ReflectionMethodBuilder rmb;
2818                 char *name;
2819
2820                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2821                 klass = mono_class_from_mono_type (type);
2822
2823                 gclass = type->data.generic_class;
2824                 g_assert (gclass->is_dynamic);
2825                 dgclass = (MonoDynamicGenericClass *) gclass;
2826
2827                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2828
2829                 name = mono_string_to_utf8 (rmb.name);
2830
2831                 sig = method_builder_encode_signature (assembly, &rmb);
2832
2833                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2834                 g_free (name);
2835         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2836                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2837
2838                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2839                 klass = mono_class_from_mono_type (type);
2840
2841                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2842                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2843         } else {
2844                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2845                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2846         }
2847
2848
2849         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2850         return token;
2851 }
2852
2853 static MonoMethod*
2854 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2855 {
2856         MonoClass *klass;
2857         MonoGenericContext tmp_context;
2858         MonoType **type_argv;
2859         MonoGenericInst *ginst;
2860         MonoMethod *method, *inflated;
2861         int count, i;
2862
2863         init_type_builder_generics ((MonoObject*)m->inst);
2864
2865         method = inflate_method (m->inst, (MonoObject*)m->mb);
2866
2867         klass = method->klass;
2868
2869         if (m->method_args == NULL)
2870                 return method;
2871
2872         if (method->is_inflated)
2873                 method = ((MonoMethodInflated *) method)->declaring;
2874
2875         count = mono_array_length (m->method_args);
2876
2877         type_argv = g_new0 (MonoType *, count);
2878         for (i = 0; i < count; i++) {
2879                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2880                 type_argv [i] = mono_reflection_type_get_handle (garg);
2881         }
2882         ginst = mono_metadata_get_generic_inst (count, type_argv);
2883         g_free (type_argv);
2884
2885         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2886         tmp_context.method_inst = ginst;
2887
2888         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2889         return inflated;
2890 }
2891
2892 static guint32
2893 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2894 {
2895         guint32 sig, token = 0;
2896         MonoType *type;
2897         MonoClass *klass;
2898
2899         if (m->method_args) {
2900                 MonoMethod *inflated;
2901
2902                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2903                 if (create_methodspec)
2904                         token = mono_image_get_methodspec_token (assembly, inflated);
2905                 else
2906                         token = mono_image_get_inflated_method_token (assembly, inflated);
2907                 return token;
2908         }
2909
2910         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2911         if (token)
2912                 return token;
2913
2914         if (is_sre_method_builder (mono_object_class (m->mb))) {
2915                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2916                 MonoGenericClass *gclass;
2917                 ReflectionMethodBuilder rmb;
2918                 char *name;
2919
2920                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2921                 klass = mono_class_from_mono_type (type);
2922                 gclass = type->data.generic_class;
2923                 g_assert (gclass->is_dynamic);
2924
2925                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2926
2927                 name = mono_string_to_utf8 (rmb.name);
2928
2929                 sig = method_builder_encode_signature (assembly, &rmb);
2930
2931                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2932                 g_free (name);          
2933         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2934                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2935
2936                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2937                 klass = mono_class_from_mono_type (type);
2938
2939                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2940                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2941         } else {
2942                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2943                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2944         }
2945
2946         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2947         return token;
2948 }
2949
2950 static guint32
2951 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2952 {
2953         SigBuffer buf;
2954         int i;
2955         guint32 nparams = context->method_inst->type_argc;
2956         guint32 idx;
2957
2958         if (!assembly->save)
2959                 return 0;
2960
2961         sigbuffer_init (&buf, 32);
2962         /*
2963          * FIXME: vararg, explicit_this, differenc call_conv values...
2964          */
2965         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2966         sigbuffer_add_value (&buf, nparams);
2967
2968         for (i = 0; i < nparams; i++)
2969                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2970
2971         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2972         sigbuffer_free (&buf);
2973         return idx;
2974 }
2975
2976 static guint32
2977 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2978 {
2979         MonoDynamicTable *table;
2980         guint32 *values;
2981         guint32 token, mtoken = 0, sig;
2982         MonoMethodInflated *imethod;
2983         MonoMethod *declaring;
2984
2985         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2986
2987         g_assert (method->is_inflated);
2988         imethod = (MonoMethodInflated *) method;
2989         declaring = imethod->declaring;
2990
2991         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2992         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2993
2994         if (!mono_method_signature (declaring)->generic_param_count)
2995                 return mtoken;
2996
2997         switch (mono_metadata_token_table (mtoken)) {
2998         case MONO_TABLE_MEMBERREF:
2999                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3000                 break;
3001         case MONO_TABLE_METHOD:
3002                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3003                 break;
3004         default:
3005                 g_assert_not_reached ();
3006         }
3007
3008         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3009
3010         if (assembly->save) {
3011                 alloc_table (table, table->rows + 1);
3012                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3013                 values [MONO_METHODSPEC_METHOD] = mtoken;
3014                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3015         }
3016
3017         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3018         table->next_idx ++;
3019
3020         return token;
3021 }
3022
3023 static guint32
3024 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3025 {
3026         MonoMethodInflated *imethod;
3027         guint32 token;
3028         
3029         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3030         if (token)
3031                 return token;
3032
3033         g_assert (method->is_inflated);
3034         imethod = (MonoMethodInflated *) method;
3035
3036         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3037                 token = method_encode_methodspec (assembly, method);
3038         } else {
3039                 guint32 sig = method_encode_signature (
3040                         assembly, mono_method_signature (imethod->declaring));
3041                 token = mono_image_get_memberref_token (
3042                         assembly, &method->klass->byval_arg, method->name, sig);
3043         }
3044
3045         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3046         return token;
3047 }
3048
3049 static guint32
3050 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3051 {
3052         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3053         guint32 sig, token;
3054
3055         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3056         token = mono_image_get_memberref_token (
3057                 assembly, &m->klass->byval_arg, m->name, sig);
3058
3059         return token;
3060 }
3061
3062 static guint32
3063 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3064 {
3065         MonoDynamicTable *table;
3066         MonoClass *klass;
3067         MonoType *type;
3068         guint32 *values;
3069         guint32 token;
3070         SigBuffer buf;
3071         int count, i;
3072
3073         /*
3074          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3075          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3076          * Because of this, we must not insert it into the `typeref' hash table.
3077          */
3078         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3079         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3080         if (token)
3081                 return token;
3082
3083         sigbuffer_init (&buf, 32);
3084
3085         g_assert (tb->generic_params);
3086         klass = mono_class_from_mono_type (type);
3087
3088         if (tb->generic_container)
3089                 mono_reflection_create_generic_class (tb);
3090
3091         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3092         g_assert (klass->generic_container);
3093         sigbuffer_add_value (&buf, klass->byval_arg.type);
3094         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3095
3096         count = mono_array_length (tb->generic_params);
3097         sigbuffer_add_value (&buf, count);
3098         for (i = 0; i < count; i++) {
3099                 MonoReflectionGenericParam *gparam;
3100
3101                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3102
3103                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3104         }
3105
3106         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3107
3108         if (assembly->save) {
3109                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3110                 alloc_table (table, table->rows + 1);
3111                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3112                 values [MONO_TYPESPEC_SIGNATURE] = token;
3113         }
3114         sigbuffer_free (&buf);
3115
3116         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3117         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3118         table->next_idx ++;
3119         return token;
3120 }
3121
3122 /*
3123  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3124  */
3125 static MonoType*
3126 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3127 {
3128         int i, count, len, pos;
3129         MonoType *t;
3130
3131         count = 0;
3132         if (modreq)
3133                 count += mono_array_length (modreq);
3134         if (modopt)
3135                 count += mono_array_length (modopt);
3136
3137         if (count == 0)
3138                 return mono_metadata_type_dup (NULL, type);
3139
3140         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3141         t = g_malloc (len);
3142         memcpy (t, type, MONO_SIZEOF_TYPE);
3143
3144         t->num_mods = count;
3145         pos = 0;
3146         if (modreq) {
3147                 for (i = 0; i < mono_array_length (modreq); ++i) {
3148                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3149                         t->modifiers [pos].required = 1;
3150                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3151                         pos ++;
3152                 }
3153         }
3154         if (modopt) {
3155                 for (i = 0; i < mono_array_length (modopt); ++i) {
3156                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3157                         t->modifiers [pos].required = 0;
3158                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3159                         pos ++;
3160                 }
3161         }
3162
3163         return t;
3164 }
3165
3166 static void
3167 init_type_builder_generics (MonoObject *type)
3168 {
3169         MonoReflectionTypeBuilder *tb;
3170
3171         if (!is_sre_type_builder(mono_object_class (type)))
3172                 return;
3173         tb = (MonoReflectionTypeBuilder *)type;
3174
3175         if (tb && tb->generic_container)
3176                 mono_reflection_create_generic_class (tb);
3177 }
3178
3179 static guint32
3180 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3181 {
3182         MonoDynamicTable *table;
3183         MonoClass *klass;
3184         MonoType *custom = NULL, *type;
3185         guint32 *values;
3186         guint32 token, pclass, parent, sig;
3187         gchar *name;
3188
3189         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3190         if (token)
3191                 return token;
3192
3193         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3194         name = mono_string_to_utf8 (fb->name);
3195
3196         /*FIXME this is one more layer of ugliness due how types are created.*/
3197         init_type_builder_generics (fb->type);
3198
3199         /* fb->type does not include the custom modifiers */
3200         /* FIXME: We should do this in one place when a fieldbuilder is created */
3201         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3202         if (fb->modreq || fb->modopt)
3203                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3204
3205         sig = fieldref_encode_signature (assembly, NULL, type);
3206         g_free (custom);
3207
3208         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3209         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3210         
3211         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3212         parent >>= MONO_TYPEDEFORREF_BITS;
3213
3214         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3215
3216         if (assembly->save) {
3217                 alloc_table (table, table->rows + 1);
3218                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3219                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3220                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3221                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3222         }
3223
3224         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3225         table->next_idx ++;
3226         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3227         g_free (name);
3228         return token;
3229 }
3230
3231 static guint32
3232 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3233 {
3234         SigBuffer buf;
3235         guint32 nargs;
3236         guint32 size;
3237         guint32 i, idx;
3238
3239         if (!assembly->save)
3240                 return 0;
3241
3242         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3243         g_assert (helper->type == 2);
3244
3245         if (helper->arguments)
3246                 nargs = mono_array_length (helper->arguments);
3247         else
3248                 nargs = 0;
3249
3250         size = 10 + (nargs * 10);
3251         
3252         sigbuffer_init (&buf, 32);
3253
3254         /* Encode calling convention */
3255         /* Change Any to Standard */
3256         if ((helper->call_conv & 0x03) == 0x03)
3257                 helper->call_conv = 0x01;
3258         /* explicit_this implies has_this */
3259         if (helper->call_conv & 0x40)
3260                 helper->call_conv &= 0x20;
3261
3262         if (helper->call_conv == 0) { /* Unmanaged */
3263                 idx = helper->unmanaged_call_conv - 1;
3264         } else {
3265                 /* Managed */
3266                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3267                 if (helper->call_conv & 0x02) /* varargs */
3268                         idx += 0x05;
3269         }
3270
3271         sigbuffer_add_byte (&buf, idx);
3272         sigbuffer_add_value (&buf, nargs);
3273         encode_reflection_type (assembly, helper->return_type, &buf);
3274         for (i = 0; i < nargs; ++i) {
3275                 MonoArray *modreqs = NULL;
3276                 MonoArray *modopts = NULL;
3277                 MonoReflectionType *pt;
3278
3279                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3280                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3281                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3282                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3283
3284                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3285                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3286                 encode_reflection_type (assembly, pt, &buf);
3287         }
3288         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3289         sigbuffer_free (&buf);
3290
3291         return idx;
3292 }
3293
3294 static guint32 
3295 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3296 {
3297         guint32 idx;
3298         MonoDynamicTable *table;
3299         guint32 *values;
3300
3301         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3302         idx = table->next_idx ++;
3303         table->rows ++;
3304         alloc_table (table, table->rows);
3305         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3306
3307         values [MONO_STAND_ALONE_SIGNATURE] =
3308                 mono_reflection_encode_sighelper (assembly, helper);
3309
3310         return idx;
3311 }
3312
3313 static int
3314 reflection_cc_to_file (int call_conv) {
3315         switch (call_conv & 0x3) {
3316         case 0:
3317         case 1: return MONO_CALL_DEFAULT;
3318         case 2: return MONO_CALL_VARARG;
3319         default:
3320                 g_assert_not_reached ();
3321         }
3322         return 0;
3323 }
3324 #endif /* !DISABLE_REFLECTION_EMIT */
3325
3326 typedef struct {
3327         MonoType *parent;
3328         MonoMethodSignature *sig;
3329         char *name;
3330         guint32 token;
3331 } ArrayMethod;
3332
3333 #ifndef DISABLE_REFLECTION_EMIT
3334 static guint32
3335 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3336 {
3337         guint32 nparams, i;
3338         GList *tmp;
3339         char *name;
3340         MonoMethodSignature *sig;
3341         ArrayMethod *am;
3342         MonoType *mtype;
3343
3344         name = mono_string_to_utf8 (m->name);
3345         nparams = mono_array_length (m->parameters);
3346         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3347         sig->hasthis = 1;
3348         sig->sentinelpos = -1;
3349         sig->call_convention = reflection_cc_to_file (m->call_conv);
3350         sig->param_count = nparams;
3351         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3352         mtype = mono_reflection_type_get_handle (m->parent);
3353         for (i = 0; i < nparams; ++i)
3354                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3355
3356         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3357                 am = tmp->data;
3358                 if (strcmp (name, am->name) == 0 && 
3359                                 mono_metadata_type_equal (am->parent, mtype) &&
3360                                 mono_metadata_signature_equal (am->sig, sig)) {
3361                         g_free (name);
3362                         g_free (sig);
3363                         m->table_idx = am->token & 0xffffff;
3364                         return am->token;
3365                 }
3366         }
3367         am = g_new0 (ArrayMethod, 1);
3368         am->name = name;
3369         am->sig = sig;
3370         am->parent = mtype;
3371         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3372                 method_encode_signature (assembly, sig));
3373         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3374         m->table_idx = am->token & 0xffffff;
3375         return am->token;
3376 }
3377
3378 /*
3379  * Insert into the metadata tables all the info about the TypeBuilder tb.
3380  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3381  */
3382 static void
3383 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3384 {
3385         MonoDynamicTable *table;
3386         guint *values;
3387         int i, is_object = 0, is_system = 0;
3388         char *n;
3389
3390         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3391         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3392         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3393         n = mono_string_to_utf8 (tb->name);
3394         if (strcmp (n, "Object") == 0)
3395                 is_object++;
3396         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3397         g_free (n);
3398         n = mono_string_to_utf8 (tb->nspace);
3399         if (strcmp (n, "System") == 0)
3400                 is_system++;
3401         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3402         g_free (n);
3403         if (tb->parent && !(is_system && is_object) && 
3404                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3405                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3406         } else {
3407                 values [MONO_TYPEDEF_EXTENDS] = 0;
3408         }
3409         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3410         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3411
3412         /*
3413          * if we have explicitlayout or sequentiallayouts, output data in the
3414          * ClassLayout table.
3415          */
3416         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3417                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3418                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3419                 table->rows++;
3420                 alloc_table (table, table->rows);
3421                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3422                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3423                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3424                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3425         }
3426
3427         /* handle interfaces */
3428         if (tb->interfaces) {
3429                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3430                 i = table->rows;
3431                 table->rows += mono_array_length (tb->interfaces);
3432                 alloc_table (table, table->rows);
3433                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3434                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3435                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3436                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3437                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3438                         values += MONO_INTERFACEIMPL_SIZE;
3439                 }
3440         }
3441
3442         /* handle fields */
3443         if (tb->fields) {
3444                 table = &assembly->tables [MONO_TABLE_FIELD];
3445                 table->rows += tb->num_fields;
3446                 alloc_table (table, table->rows);
3447                 for (i = 0; i < tb->num_fields; ++i)
3448                         mono_image_get_field_info (
3449                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3450         }
3451
3452         /* handle constructors */
3453         if (tb->ctors) {
3454                 table = &assembly->tables [MONO_TABLE_METHOD];
3455                 table->rows += mono_array_length (tb->ctors);
3456                 alloc_table (table, table->rows);
3457                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3458                         mono_image_get_ctor_info (domain,
3459                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3460         }
3461
3462         /* handle methods */
3463         if (tb->methods) {
3464                 table = &assembly->tables [MONO_TABLE_METHOD];
3465                 table->rows += tb->num_methods;
3466                 alloc_table (table, table->rows);
3467                 for (i = 0; i < tb->num_methods; ++i)
3468                         mono_image_get_method_info (
3469                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3470         }
3471
3472         /* Do the same with properties etc.. */
3473         if (tb->events && mono_array_length (tb->events)) {
3474                 table = &assembly->tables [MONO_TABLE_EVENT];
3475                 table->rows += mono_array_length (tb->events);
3476                 alloc_table (table, table->rows);
3477                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3478                 table->rows ++;
3479                 alloc_table (table, table->rows);
3480                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3481                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3482                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3483                 for (i = 0; i < mono_array_length (tb->events); ++i)
3484                         mono_image_get_event_info (
3485                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3486         }
3487         if (tb->properties && mono_array_length (tb->properties)) {
3488                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3489                 table->rows += mono_array_length (tb->properties);
3490                 alloc_table (table, table->rows);
3491                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3492                 table->rows ++;
3493                 alloc_table (table, table->rows);
3494                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3495                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3496                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3497                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3498                         mono_image_get_property_info (
3499                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3500         }
3501
3502         /* handle generic parameters */
3503         if (tb->generic_params) {
3504                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3505                 table->rows += mono_array_length (tb->generic_params);
3506                 alloc_table (table, table->rows);
3507                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3508                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3509
3510                         mono_image_get_generic_param_info (
3511                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3512                 }
3513         }
3514
3515         mono_image_add_decl_security (assembly, 
3516                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3517
3518         if (tb->subtypes) {
3519                 MonoDynamicTable *ntable;
3520                 
3521                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3522                 ntable->rows += mono_array_length (tb->subtypes);
3523                 alloc_table (ntable, ntable->rows);
3524                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3525
3526                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3527                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3528
3529                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3530                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3531                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3532                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3533                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3534                                 ntable->next_idx, ntable->rows);*/
3535                         values += MONO_NESTED_CLASS_SIZE;
3536                         ntable->next_idx++;
3537                 }
3538         }
3539 }
3540 #endif
3541
3542 static void
3543 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3544 {
3545         int i;
3546
3547         mono_ptr_array_append (*types, type);
3548
3549         if (!type->subtypes)
3550                 return;
3551
3552         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3553                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3554                 collect_types (types, subtype);
3555         }
3556 }
3557
3558 static gint
3559 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3560 {
3561         if ((*type1)->table_idx < (*type2)->table_idx)
3562                 return -1;
3563         else
3564                 if ((*type1)->table_idx > (*type2)->table_idx)
3565                         return 1;
3566         else
3567                 return 0;
3568 }
3569
3570 static void
3571 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3572         int i;
3573
3574         if (!pinfo)
3575                 return;
3576         for (i = 0; i < mono_array_length (pinfo); ++i) {
3577                 MonoReflectionParamBuilder *pb;
3578                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3579                 if (!pb)
3580                         continue;
3581                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3582         }
3583 }
3584
3585 static void
3586 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3587         int i;
3588         
3589         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3590         if (tb->fields) {
3591                 for (i = 0; i < tb->num_fields; ++i) {
3592                         MonoReflectionFieldBuilder* fb;
3593                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3594                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3595                 }
3596         }
3597         if (tb->events) {
3598                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3599                         MonoReflectionEventBuilder* eb;
3600                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3601                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3602                 }
3603         }
3604         if (tb->properties) {
3605                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3606                         MonoReflectionPropertyBuilder* pb;
3607                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3608                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3609                 }
3610         }
3611         if (tb->ctors) {
3612                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3613                         MonoReflectionCtorBuilder* cb;
3614                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3615                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3616                         params_add_cattrs (assembly, cb->pinfo);
3617                 }
3618         }
3619
3620         if (tb->methods) {
3621                 for (i = 0; i < tb->num_methods; ++i) {
3622                         MonoReflectionMethodBuilder* mb;
3623                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3624                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3625                         params_add_cattrs (assembly, mb->pinfo);
3626                 }
3627         }
3628
3629         if (tb->subtypes) {
3630                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3631                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3632         }
3633 }
3634
3635 static void
3636 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3637 {
3638         int i;
3639         
3640         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3641
3642         if (moduleb->global_methods) {
3643                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3644                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3645                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3646                         params_add_cattrs (assembly, mb->pinfo);
3647                 }
3648         }
3649
3650         if (moduleb->global_fields) {
3651                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3652                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3653                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3654                 }
3655         }
3656         
3657         if (moduleb->types) {
3658                 for (i = 0; i < moduleb->num_types; ++i)
3659                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3660         }
3661 }
3662
3663 static void
3664 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3665 {
3666         MonoDynamicTable *table;
3667         guint32 *values;
3668         char blob_size [6];
3669         guchar hash [20];
3670         char *b = blob_size;
3671         char *dir, *path;
3672
3673         table = &assembly->tables [MONO_TABLE_FILE];
3674         table->rows++;
3675         alloc_table (table, table->rows);
3676         values = table->values + table->next_idx * MONO_FILE_SIZE;
3677         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3678         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3679         if (module->image->dynamic) {
3680                 /* This depends on the fact that the main module is emitted last */
3681                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3682                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3683         } else {
3684                 dir = NULL;
3685                 path = g_strdup (module->image->name);
3686         }
3687         mono_sha1_get_digest_from_file (path, hash);
3688         g_free (dir);
3689         g_free (path);
3690         mono_metadata_encode_value (20, b, &b);
3691         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3692         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3693         table->next_idx ++;
3694 }
3695
3696 static void
3697 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3698 {
3699         MonoDynamicTable *table;
3700         int i;
3701
3702         table = &assembly->tables [MONO_TABLE_MODULE];
3703         mb->table_idx = table->next_idx ++;
3704         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3705         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3706         i /= 16;
3707         ++i;
3708         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3709         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3710         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3711         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3712 }
3713
3714 static guint32
3715 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3716         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3717 {
3718         MonoDynamicTable *table;
3719         guint32 *values;
3720         guint32 visib, res;
3721
3722         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3723         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3724                 return 0;
3725
3726         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3727         table->rows++;
3728         alloc_table (table, table->rows);
3729         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3730
3731         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3732         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3733         if (klass->nested_in)
3734                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3735         else
3736                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3737         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3738         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3739
3740         res = table->next_idx;
3741
3742         table->next_idx ++;
3743
3744         /* Emit nested types */
3745         if (klass->ext && klass->ext->nested_classes) {
3746                 GList *tmp;
3747
3748                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3749                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3750         }
3751
3752         return res;
3753 }
3754
3755 static void
3756 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3757         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3758 {
3759         MonoClass *klass;
3760         guint32 idx, i;
3761
3762         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3763
3764         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3765
3766         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3767                                                                                                    parent_index, assembly);
3768
3769         /* 
3770          * Emit nested types
3771          * We need to do this ourselves since klass->nested_classes is not set up.
3772          */
3773         if (tb->subtypes) {
3774                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3775                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3776         }
3777 }
3778
3779 static void
3780 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3781         guint32 module_index, MonoDynamicImage *assembly)
3782 {
3783         MonoImage *image = module->image;
3784         MonoTableInfo  *t;
3785         guint32 i;
3786
3787         t = &image->tables [MONO_TABLE_TYPEDEF];
3788
3789         for (i = 0; i < t->rows; ++i) {
3790                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3791
3792                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3793                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3794         }
3795 }
3796
3797 static void
3798 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3799 {
3800         MonoDynamicTable *table;
3801         guint32 *values;
3802         guint32 scope, scope_idx, impl, current_idx;
3803         gboolean forwarder = TRUE;
3804         gpointer iter = NULL;
3805         MonoClass *nested;
3806
3807         if (klass->nested_in) {
3808                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3809                 forwarder = FALSE;
3810         } else {
3811                 scope = resolution_scope_from_image (assembly, klass->image);
3812                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3813                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3814                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3815         }
3816
3817         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3818
3819         table->rows++;
3820         alloc_table (table, table->rows);
3821         current_idx = table->next_idx;
3822         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3823
3824         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3825         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3826         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3827         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3828         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3829
3830         table->next_idx++;
3831
3832         while ((nested = mono_class_get_nested_types (klass, &iter)))
3833                 add_exported_type (assemblyb, assembly, nested, current_idx);
3834 }
3835
3836 static void
3837 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3838 {
3839         MonoClass *klass;
3840         int i;
3841
3842         if (!assemblyb->type_forwarders)
3843                 return;
3844
3845         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3846                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3847                 MonoType *type;
3848                 if (!t)
3849                         continue;
3850
3851                 type = mono_reflection_type_get_handle (t);
3852                 g_assert (type);
3853
3854                 klass = mono_class_from_mono_type (type);
3855
3856                 add_exported_type (assemblyb, assembly, klass, 0);
3857         }
3858 }
3859
3860 #define align_pointer(base,p)\
3861         do {\
3862                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3863                 if (__diff & 3)\
3864                         (p) += 4 - (__diff & 3);\
3865         } while (0)
3866
3867 static int
3868 compare_constants (const void *a, const void *b)
3869 {
3870         const guint32 *a_values = a;
3871         const guint32 *b_values = b;
3872         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3873 }
3874
3875 static int
3876 compare_semantics (const void *a, const void *b)
3877 {
3878         const guint32 *a_values = a;
3879         const guint32 *b_values = b;
3880         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3881         if (assoc)
3882                 return assoc;
3883         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3884 }
3885
3886 static int
3887 compare_custom_attrs (const void *a, const void *b)
3888 {
3889         const guint32 *a_values = a;
3890         const guint32 *b_values = b;
3891
3892         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3893 }
3894
3895 static int
3896 compare_field_marshal (const void *a, const void *b)
3897 {
3898         const guint32 *a_values = a;
3899         const guint32 *b_values = b;
3900
3901         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3902 }
3903
3904 static int
3905 compare_nested (const void *a, const void *b)
3906 {
3907         const guint32 *a_values = a;
3908         const guint32 *b_values = b;
3909
3910         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3911 }
3912
3913 static int
3914 compare_genericparam (const void *a, const void *b)
3915 {
3916         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3917         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3918
3919         if ((*b_entry)->owner == (*a_entry)->owner)
3920                 return 
3921                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3922                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3923         else
3924                 return (*a_entry)->owner - (*b_entry)->owner;
3925 }
3926
3927 static int
3928 compare_declsecurity_attrs (const void *a, const void *b)
3929 {
3930         const guint32 *a_values = a;
3931         const guint32 *b_values = b;
3932
3933         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3934 }
3935
3936 static int
3937 compare_interface_impl (const void *a, const void *b)
3938 {
3939         const guint32 *a_values = a;
3940         const guint32 *b_values = b;
3941
3942         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3943         if (klass)
3944                 return klass;
3945
3946         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3947 }
3948
3949 static void
3950 pad_heap (MonoDynamicStream *sh)
3951 {
3952         if (sh->index & 3) {
3953                 int sz = 4 - (sh->index & 3);
3954                 memset (sh->data + sh->index, 0, sz);
3955                 sh->index += sz;
3956         }
3957 }
3958
3959 struct StreamDesc {
3960         const char *name;
3961         MonoDynamicStream *stream;
3962 };
3963
3964 /*
3965  * build_compressed_metadata() fills in the blob of data that represents the 
3966  * raw metadata as it will be saved in the PE file. The five streams are output 
3967  * and the metadata tables are comnpressed from the guint32 array representation, 
3968  * to the compressed on-disk format.
3969  */
3970 static void
3971 build_compressed_metadata (MonoDynamicImage *assembly)
3972 {
3973         MonoDynamicTable *table;
3974         int i;
3975         guint64 valid_mask = 0;
3976         guint64 sorted_mask;
3977         guint32 heapt_size = 0;
3978         guint32 meta_size = 256; /* allow for header and other stuff */
3979         guint32 table_offset;
3980         guint32 ntables = 0;
3981         guint64 *int64val;
3982         guint32 *int32val;
3983         guint16 *int16val;
3984         MonoImage *meta;
3985         unsigned char *p;
3986         struct StreamDesc stream_desc [5];
3987
3988         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3989         for (i = 0; i < assembly->gen_params->len; i++){
3990                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3991                 write_generic_param_entry (assembly, entry);
3992         }
3993
3994         stream_desc [0].name  = "#~";
3995         stream_desc [0].stream = &assembly->tstream;
3996         stream_desc [1].name  = "#Strings";
3997         stream_desc [1].stream = &assembly->sheap;
3998         stream_desc [2].name  = "#US";
3999         stream_desc [2].stream = &assembly->us;
4000         stream_desc [3].name  = "#Blob";
4001         stream_desc [3].stream = &assembly->blob;
4002         stream_desc [4].name  = "#GUID";
4003         stream_desc [4].stream = &assembly->guid;
4004         
4005         /* tables that are sorted */
4006         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4007                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4008                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4009                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4010                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4011                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4012                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4013         
4014         /* Compute table sizes */
4015         /* the MonoImage has already been created in mono_image_basic_init() */
4016         meta = &assembly->image;
4017
4018         /* sizes should be multiple of 4 */
4019         pad_heap (&assembly->blob);
4020         pad_heap (&assembly->guid);
4021         pad_heap (&assembly->sheap);
4022         pad_heap (&assembly->us);
4023
4024         /* Setup the info used by compute_sizes () */
4025         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4026         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4027         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4028
4029         meta_size += assembly->blob.index;
4030         meta_size += assembly->guid.index;
4031         meta_size += assembly->sheap.index;
4032         meta_size += assembly->us.index;
4033
4034         for (i=0; i < MONO_TABLE_NUM; ++i)
4035                 meta->tables [i].rows = assembly->tables [i].rows;
4036         
4037         for (i = 0; i < MONO_TABLE_NUM; i++){
4038                 if (meta->tables [i].rows == 0)
4039                         continue;
4040                 valid_mask |= (guint64)1 << i;
4041                 ntables ++;
4042                 meta->tables [i].row_size = mono_metadata_compute_size (
4043                         meta, i, &meta->tables [i].size_bitfield);
4044                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4045         }
4046         heapt_size += 24; /* #~ header size */
4047         heapt_size += ntables * 4;
4048         /* make multiple of 4 */
4049         heapt_size += 3;
4050         heapt_size &= ~3;
4051         meta_size += heapt_size;
4052         meta->raw_metadata = g_malloc0 (meta_size);
4053         p = (unsigned char*)meta->raw_metadata;
4054         /* the metadata signature */
4055         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4056         /* version numbers and 4 bytes reserved */
4057         int16val = (guint16*)p;
4058         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4059         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4060         p += 8;
4061         /* version string */
4062         int32val = (guint32*)p;
4063         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4064         p += 4;
4065         memcpy (p, meta->version, strlen (meta->version));
4066         p += GUINT32_FROM_LE (*int32val);
4067         align_pointer (meta->raw_metadata, p);
4068         int16val = (guint16*)p;
4069         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4070         *int16val = GUINT16_TO_LE (5); /* number of streams */
4071         p += 4;
4072
4073         /*
4074          * write the stream info.
4075          */
4076         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4077         table_offset += 3; table_offset &= ~3;
4078
4079         assembly->tstream.index = heapt_size;
4080         for (i = 0; i < 5; ++i) {
4081                 int32val = (guint32*)p;
4082                 stream_desc [i].stream->offset = table_offset;
4083                 *int32val++ = GUINT32_TO_LE (table_offset);
4084                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4085                 table_offset += GUINT32_FROM_LE (*int32val);
4086                 table_offset += 3; table_offset &= ~3;
4087                 p += 8;
4088                 strcpy ((char*)p, stream_desc [i].name);
4089                 p += strlen (stream_desc [i].name) + 1;
4090                 align_pointer (meta->raw_metadata, p);
4091         }
4092         /* 
4093          * now copy the data, the table stream header and contents goes first.
4094          */
4095         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4096         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4097         int32val = (guint32*)p;
4098         *int32val = GUINT32_TO_LE (0); /* reserved */
4099         p += 4;
4100
4101         *p++ = 2; /* version */
4102         *p++ = 0;
4103
4104         if (meta->idx_string_wide)
4105                 *p |= 0x01;
4106         if (meta->idx_guid_wide)
4107                 *p |= 0x02;
4108         if (meta->idx_blob_wide)
4109                 *p |= 0x04;
4110         ++p;
4111         *p++ = 1; /* reserved */
4112         int64val = (guint64*)p;
4113         *int64val++ = GUINT64_TO_LE (valid_mask);
4114         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4115         p += 16;
4116         int32val = (guint32*)p;
4117         for (i = 0; i < MONO_TABLE_NUM; i++){
4118                 if (meta->tables [i].rows == 0)
4119                         continue;
4120                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4121         }
4122         p = (unsigned char*)int32val;
4123
4124         /* sort the tables that still need sorting */
4125         table = &assembly->tables [MONO_TABLE_CONSTANT];
4126         if (table->rows)
4127                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4128         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4129         if (table->rows)
4130                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4131         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4132         if (table->rows)
4133                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4134         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4135         if (table->rows)
4136                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4137         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4138         if (table->rows)
4139                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4140         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4141         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4142         if (table->rows)
4143                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4144         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4145         if (table->rows)
4146                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4147
4148         /* compress the tables */
4149         for (i = 0; i < MONO_TABLE_NUM; i++){
4150                 int row, col;
4151                 guint32 *values;
4152                 guint32 bitfield = meta->tables [i].size_bitfield;
4153                 if (!meta->tables [i].rows)
4154                         continue;
4155                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4156                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4157                 meta->tables [i].base = (char*)p;
4158                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4159                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4160                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4161                                 switch (mono_metadata_table_size (bitfield, col)) {
4162                                 case 1:
4163                                         *p++ = values [col];
4164                                         break;
4165                                 case 2:
4166                                         *p++ = values [col] & 0xff;
4167                                         *p++ = (values [col] >> 8) & 0xff;
4168                                         break;
4169                                 case 4:
4170                                         *p++ = values [col] & 0xff;
4171                                         *p++ = (values [col] >> 8) & 0xff;
4172                                         *p++ = (values [col] >> 16) & 0xff;
4173                                         *p++ = (values [col] >> 24) & 0xff;
4174                                         break;
4175                                 default:
4176                                         g_assert_not_reached ();
4177                                 }
4178                         }
4179                 }
4180                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4181         }
4182         
4183         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4184         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4185         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4186         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4187         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4188
4189         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4190 }
4191
4192 /*
4193  * Some tables in metadata need to be sorted according to some criteria, but
4194  * when methods and fields are first created with reflection, they may be assigned a token
4195  * that doesn't correspond to the final token they will get assigned after the sorting.
4196  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4197  * with the reflection objects that represent them. Once all the tables are set up, the 
4198  * reflection objects will contains the correct table index. fixup_method() will fixup the
4199  * tokens for the method with ILGenerator @ilgen.
4200  */
4201 static void
4202 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4203 {
4204         guint32 code_idx = GPOINTER_TO_UINT (value);
4205         MonoReflectionILTokenInfo *iltoken;
4206         MonoReflectionFieldBuilder *field;
4207         MonoReflectionCtorBuilder *ctor;
4208         MonoReflectionMethodBuilder *method;
4209         MonoReflectionTypeBuilder *tb;
4210         MonoReflectionArrayMethod *am;
4211         guint32 i, idx = 0;
4212         unsigned char *target;
4213
4214         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4215                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4216                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4217                 switch (target [3]) {
4218                 case MONO_TABLE_FIELD:
4219                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4220                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4221                                 idx = field->table_idx;
4222                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4223                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4224                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4225                         } else {
4226                                 g_assert_not_reached ();
4227                         }
4228                         break;
4229                 case MONO_TABLE_METHOD:
4230                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4231                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4232                                 idx = method->table_idx;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4234                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4235                                 idx = ctor->table_idx;
4236                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4237                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4238                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4239                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4240                         } else {
4241                                 g_assert_not_reached ();
4242                         }
4243                         break;
4244                 case MONO_TABLE_TYPEDEF:
4245                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4246                                 g_assert_not_reached ();
4247                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4248                         idx = tb->table_idx;
4249                         break;
4250                 case MONO_TABLE_MEMBERREF:
4251                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4252                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4253                                 idx = am->table_idx;
4254                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4255                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4256                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4257                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4258                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4259                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4260                                 continue;
4261                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4262                                 continue;
4263                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4264                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4265                                 g_assert (is_field_on_inst (f));
4266                                 continue;
4267                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4268                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4269                                 continue;
4270                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4273                                 continue;
4274                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4275                                 continue;
4276                         } else {
4277                                 g_assert_not_reached ();
4278                         }
4279                         break;
4280                 case MONO_TABLE_METHODSPEC:
4281                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4282                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4283                                 g_assert (mono_method_signature (m)->generic_param_count);
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4286                                 continue;
4287                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4288                                 continue;
4289                         } else {
4290                                 g_assert_not_reached ();
4291                         }
4292                         break;
4293                 default:
4294                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4295                 }
4296                 target [0] = idx & 0xff;
4297                 target [1] = (idx >> 8) & 0xff;
4298                 target [2] = (idx >> 16) & 0xff;
4299         }
4300 }
4301
4302 /*
4303  * fixup_cattrs:
4304  *
4305  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4306  * value is not known when the table is emitted.
4307  */
4308 static void
4309 fixup_cattrs (MonoDynamicImage *assembly)
4310 {
4311         MonoDynamicTable *table;
4312         guint32 *values;
4313         guint32 type, i, idx, token;
4314         MonoObject *ctor;
4315
4316         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4317
4318         for (i = 0; i < table->rows; ++i) {
4319                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4320
4321                 type = values [MONO_CUSTOM_ATTR_TYPE];
4322                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4323                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4324                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4325                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4326                         g_assert (ctor);
4327
4328                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4329                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4330                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4331                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4332                         }
4333                 }
4334         }
4335 }
4336
4337 static void
4338 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4339 {
4340         MonoDynamicTable *table;
4341         guint32 *values;
4342
4343         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4344         table->rows++;
4345         alloc_table (table, table->rows);
4346         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4347         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4348         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4349         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4350         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4351         table->next_idx++;
4352 }
4353
4354 static void
4355 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4356 {
4357         MonoDynamicTable *table;
4358         guint32 *values;
4359         char blob_size [6];
4360         guchar hash [20];
4361         char *b = blob_size;
4362         char *name, *sname;
4363         guint32 idx, offset;
4364
4365         if (rsrc->filename) {
4366                 name = mono_string_to_utf8 (rsrc->filename);
4367                 sname = g_path_get_basename (name);
4368         
4369                 table = &assembly->tables [MONO_TABLE_FILE];
4370                 table->rows++;
4371                 alloc_table (table, table->rows);
4372                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4373                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4374                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4375                 g_free (sname);
4376
4377                 mono_sha1_get_digest_from_file (name, hash);
4378                 mono_metadata_encode_value (20, b, &b);
4379                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4380                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4381                 g_free (name);
4382                 idx = table->next_idx++;
4383                 rsrc->offset = 0;
4384                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4385         } else {
4386                 char sizebuf [4];
4387                 char *data;
4388                 guint len;
4389                 if (rsrc->data) {
4390                         data = mono_array_addr (rsrc->data, char, 0);
4391                         len = mono_array_length (rsrc->data);
4392                 } else {
4393                         data = NULL;
4394                         len = 0;
4395                 }
4396                 offset = len;
4397                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4398                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4399                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4400                 mono_image_add_stream_data (&assembly->resources, data, len);
4401
4402                 if (!mb->is_main)
4403                         /* 
4404                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4405                          * the main module, but that needs to reference the FILE table
4406                          * which isn't emitted yet.
4407                          */
4408                         return;
4409                 else
4410                         idx = 0;
4411         }
4412
4413         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4414 }
4415
4416 static void
4417 set_version_from_string (MonoString *version, guint32 *values)
4418 {
4419         gchar *ver, *p, *str;
4420         guint32 i;
4421         
4422         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4423         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4424         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4425         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4426         if (!version)
4427                 return;
4428         ver = str = mono_string_to_utf8 (version);
4429         for (i = 0; i < 4; ++i) {
4430                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4431                 switch (*p) {
4432                 case '.':
4433                         p++;
4434                         break;
4435                 case '*':
4436                         /* handle Revision and Build */
4437                         p++;
4438                         break;
4439                 }
4440                 ver = p;
4441         }
4442         g_free (str);
4443 }
4444
4445 static guint32
4446 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4447         gsize len;
4448         guint32 token = 0;
4449         char blob_size [6];
4450         char *b = blob_size;
4451
4452         if (!pkey)
4453                 return token;
4454
4455         len = mono_array_length (pkey);
4456         mono_metadata_encode_value (len, b, &b);
4457         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4458         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4459
4460         assembly->public_key = g_malloc (len);
4461         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4462         assembly->public_key_len = len;
4463
4464         /* Special case: check for ECMA key (16 bytes) */
4465         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4466                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4467                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4468         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4469                 /* minimum key size (in 2.0) is 384 bits */
4470                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4471         } else {
4472                 /* FIXME - verifier */
4473                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4474                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4475         }
4476         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4477
4478         return token;
4479 }
4480
4481 static void
4482 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4483 {
4484         MonoDynamicTable *table;
4485         MonoDynamicImage *assembly;
4486         MonoReflectionAssemblyBuilder *assemblyb;
4487         MonoDomain *domain;
4488         guint32 *values;
4489         int i;
4490         guint32 module_index;
4491
4492         assemblyb = moduleb->assemblyb;
4493         assembly = moduleb->dynamic_image;
4494         domain = mono_object_domain (assemblyb);
4495
4496         /* Emit ASSEMBLY table */
4497         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4498         alloc_table (table, 1);
4499         values = table->values + MONO_ASSEMBLY_SIZE;
4500         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4501         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4502         if (assemblyb->culture) {
4503                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4504         } else {
4505                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4506         }
4507         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4508         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4509         set_version_from_string (assemblyb->version, values);
4510
4511         /* Emit FILE + EXPORTED_TYPE table */
4512         module_index = 0;
4513         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4514                 int j;
4515                 MonoReflectionModuleBuilder *file_module = 
4516                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4517                 if (file_module != moduleb) {
4518                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4519                         module_index ++;
4520                         if (file_module->types) {
4521                                 for (j = 0; j < file_module->num_types; ++j) {
4522                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4523                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4524                                 }
4525                         }
4526                 }
4527         }
4528         if (assemblyb->loaded_modules) {
4529                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4530                         MonoReflectionModule *file_module = 
4531                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4532                         mono_image_fill_file_table (domain, file_module, assembly);
4533                         module_index ++;
4534                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4535                 }
4536         }
4537         if (assemblyb->type_forwarders)
4538                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4539
4540         /* Emit MANIFESTRESOURCE table */
4541         module_index = 0;
4542         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4543                 int j;
4544                 MonoReflectionModuleBuilder *file_module = 
4545                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4546                 /* The table for the main module is emitted later */
4547                 if (file_module != moduleb) {
4548                         module_index ++;
4549                         if (file_module->resources) {
4550                                 int len = mono_array_length (file_module->resources);
4551                                 for (j = 0; j < len; ++j) {
4552                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4553                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4554                                 }
4555                         }
4556                 }
4557         }               
4558 }
4559
4560 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4561
4562 /*
4563  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4564  * for the modulebuilder @moduleb.
4565  * At the end of the process, method and field tokens are fixed up and the 
4566  * on-disk compressed metadata representation is created.
4567  */
4568 void
4569 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4570 {
4571         MonoDynamicTable *table;
4572         MonoDynamicImage *assembly;
4573         MonoReflectionAssemblyBuilder *assemblyb;
4574         MonoDomain *domain;
4575         MonoPtrArray types;
4576         guint32 *values;
4577         int i, j;
4578
4579         assemblyb = moduleb->assemblyb;
4580         assembly = moduleb->dynamic_image;
4581         domain = mono_object_domain (assemblyb);
4582
4583         if (assembly->text_rva)
4584                 return;
4585
4586         assembly->text_rva = START_TEXT_RVA;
4587
4588         if (moduleb->is_main) {
4589                 mono_image_emit_manifest (moduleb);
4590         }
4591
4592         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4593         table->rows = 1; /* .<Module> */
4594         table->next_idx++;
4595         alloc_table (table, table->rows);
4596         /*
4597          * Set the first entry.
4598          */
4599         values = table->values + table->columns;
4600         values [MONO_TYPEDEF_FLAGS] = 0;
4601         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4602         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4603         values [MONO_TYPEDEF_EXTENDS] = 0;
4604         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4605         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4606
4607         /* 
4608          * handle global methods 
4609          * FIXME: test what to do when global methods are defined in multiple modules.
4610          */
4611         if (moduleb->global_methods) {
4612                 table = &assembly->tables [MONO_TABLE_METHOD];
4613                 table->rows += mono_array_length (moduleb->global_methods);
4614                 alloc_table (table, table->rows);
4615                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4616                         mono_image_get_method_info (
4617                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4618         }
4619         if (moduleb->global_fields) {
4620                 table = &assembly->tables [MONO_TABLE_FIELD];
4621                 table->rows += mono_array_length (moduleb->global_fields);
4622                 alloc_table (table, table->rows);
4623                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4624                         mono_image_get_field_info (
4625                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4626         }
4627
4628         table = &assembly->tables [MONO_TABLE_MODULE];
4629         alloc_table (table, 1);
4630         mono_image_fill_module_table (domain, moduleb, assembly);
4631
4632         /* Collect all types into a list sorted by their table_idx */
4633         mono_ptr_array_init (types, moduleb->num_types);
4634
4635         if (moduleb->types)
4636                 for (i = 0; i < moduleb->num_types; ++i) {
4637                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4638                         collect_types (&types, type);
4639                 }
4640
4641         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4642         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4643         table->rows += mono_ptr_array_size (types);
4644         alloc_table (table, table->rows);
4645
4646         /*
4647          * Emit type names + namespaces at one place inside the string heap,
4648          * so load_class_names () needs to touch fewer pages.
4649          */
4650         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4651                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4652                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4653         }
4654         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4655                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4656                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4657         }
4658
4659         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4660                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4661                 mono_image_get_type_info (domain, type, assembly);
4662         }
4663
4664         /* 
4665          * table->rows is already set above and in mono_image_fill_module_table.
4666          */
4667         /* add all the custom attributes at the end, once all the indexes are stable */
4668         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4669
4670         /* CAS assembly permissions */
4671         if (assemblyb->permissions_minimum)
4672                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4673         if (assemblyb->permissions_optional)
4674                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4675         if (assemblyb->permissions_refused)
4676                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4677
4678         module_add_cattrs (assembly, moduleb);
4679
4680         /* fixup tokens */
4681         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4682
4683         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4684          * the final tokens and don't need another fixup pass. */
4685
4686         if (moduleb->global_methods) {
4687                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4688                         MonoReflectionMethodBuilder *mb = mono_array_get (
4689                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4690                         mono_image_add_methodimpl (assembly, mb);
4691                 }
4692         }
4693
4694         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4695                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4696                 if (type->methods) {
4697                         for (j = 0; j < type->num_methods; ++j) {
4698                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4699                                         type->methods, MonoReflectionMethodBuilder*, j);
4700
4701                                 mono_image_add_methodimpl (assembly, mb);
4702                         }
4703                 }
4704         }
4705
4706         mono_ptr_array_destroy (types);
4707
4708         fixup_cattrs (assembly);
4709 }
4710
4711 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4712
4713 void
4714 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4715 {
4716         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4717 }
4718
4719 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4720
4721
4722 typedef struct {
4723         guint32 import_lookup_table;
4724         guint32 timestamp;
4725         guint32 forwarder;
4726         guint32 name_rva;
4727         guint32 import_address_table_rva;
4728 } MonoIDT;
4729
4730 typedef struct {
4731         guint32 name_rva;
4732         guint32 flags;
4733 } MonoILT;
4734
4735 #ifndef DISABLE_REFLECTION_EMIT
4736
4737 /*
4738  * mono_image_insert_string:
4739  * @module: module builder object
4740  * @str: a string
4741  *
4742  * Insert @str into the user string stream of @module.
4743  */
4744 guint32
4745 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4746 {
4747         MonoDynamicImage *assembly;
4748         guint32 idx;
4749         char buf [16];
4750         char *b = buf;
4751         
4752         MONO_ARCH_SAVE_REGS;
4753
4754         if (!module->dynamic_image)
4755                 mono_image_module_basic_init (module);
4756
4757         assembly = module->dynamic_image;
4758         
4759         if (assembly->save) {
4760                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4761                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4762 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4763         {
4764                 char *swapped = g_malloc (2 * mono_string_length (str));
4765                 const char *p = (const char*)mono_string_chars (str);
4766
4767                 swap_with_size (swapped, p, 2, mono_string_length (str));
4768                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4769                 g_free (swapped);
4770         }
4771 #else
4772                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4773 #endif
4774                 mono_image_add_stream_data (&assembly->us, "", 1);
4775         } else {
4776                 idx = assembly->us.index ++;
4777         }
4778
4779         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4780
4781         return MONO_TOKEN_STRING | idx;
4782 }
4783
4784 guint32
4785 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4786 {
4787         MonoClass *klass;
4788         guint32 token = 0;
4789         MonoMethodSignature *sig;
4790
4791         klass = obj->vtable->klass;
4792         if (strcmp (klass->name, "MonoMethod") == 0) {
4793                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4794                 MonoMethodSignature *old;
4795                 guint32 sig_token, parent;
4796                 int nargs, i;
4797
4798                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4799
4800                 nargs = mono_array_length (opt_param_types);
4801                 old = mono_method_signature (method);
4802                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4803
4804                 sig->hasthis = old->hasthis;
4805                 sig->explicit_this = old->explicit_this;
4806                 sig->call_convention = old->call_convention;
4807                 sig->generic_param_count = old->generic_param_count;
4808                 sig->param_count = old->param_count + nargs;
4809                 sig->sentinelpos = old->param_count;
4810                 sig->ret = old->ret;
4811
4812                 for (i = 0; i < old->param_count; i++)
4813                         sig->params [i] = old->params [i];
4814
4815                 for (i = 0; i < nargs; i++) {
4816                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4817                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4818                 }
4819
4820                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4821                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4822                 parent >>= MONO_TYPEDEFORREF_BITS;
4823
4824                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4825                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4826
4827                 sig_token = method_encode_signature (assembly, sig);
4828                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4829         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4830                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4831                 ReflectionMethodBuilder rmb;
4832                 guint32 parent, sig_token;
4833                 int nopt_args, nparams, ngparams, i;
4834                 char *name;
4835
4836                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4837                 rmb.opt_types = opt_param_types;
4838                 nopt_args = mono_array_length (opt_param_types);
4839
4840                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4841                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4842                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4843
4844                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4845                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4846                 sig->call_convention = rmb.call_conv;
4847                 sig->generic_param_count = ngparams;
4848                 sig->param_count = nparams + nopt_args;
4849                 sig->sentinelpos = nparams;
4850                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4851
4852                 for (i = 0; i < nparams; i++) {
4853                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4854                         sig->params [i] = mono_reflection_type_get_handle (rt);
4855                 }
4856
4857                 for (i = 0; i < nopt_args; i++) {
4858                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4859                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4860                 }
4861
4862                 sig_token = method_builder_encode_signature (assembly, &rmb);
4863
4864                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4865                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4866
4867                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4868                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4869
4870                 name = mono_string_to_utf8 (rmb.name);
4871                 token = mono_image_get_varargs_method_token (
4872                         assembly, parent, name, sig_token);
4873                 g_free (name);
4874         } else {
4875                 g_error ("requested method token for %s\n", klass->name);
4876         }
4877
4878         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4879         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4880         return token;
4881 }
4882
4883 /*
4884  * mono_image_create_token:
4885  * @assembly: a dynamic assembly
4886  * @obj:
4887  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4888  *
4889  * Get a token to insert in the IL code stream for the given MemberInfo.
4890  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4891  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4892  * entry.
4893  */
4894 guint32
4895 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4896                                                  gboolean create_open_instance, gboolean register_token)
4897 {
4898         MonoClass *klass;
4899         guint32 token = 0;
4900
4901         klass = obj->vtable->klass;
4902
4903         /* Check for user defined reflection objects */
4904         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4905         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4906                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4907
4908         if (strcmp (klass->name, "MethodBuilder") == 0) {
4909                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4910                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4911
4912                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4913                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4914                 else
4915                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4916                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4917         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4918                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4919                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4920
4921                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4922                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4923                 else
4924                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4925                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4926         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4927                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4928                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4929                 if (tb->generic_params) {
4930                         token = mono_image_get_generic_field_token (assembly, fb);
4931                 } else {
4932                         if ((tb->module->dynamic_image == assembly)) {
4933                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4934                         } else {
4935                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4936                         }
4937                 }
4938         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4939                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4940                 if (create_open_instance && tb->generic_params) {
4941                         MonoType *type;
4942                         init_type_builder_generics (obj);
4943                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4944                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4945                         token = mono_metadata_token_from_dor (token);
4946                 } else if (tb->module->dynamic_image == assembly) {
4947                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4948                 } else {
4949                         MonoType *type;
4950                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4951                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4952                 }
4953         } else if (strcmp (klass->name, "MonoType") == 0) {
4954                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4955                 MonoClass *mc = mono_class_from_mono_type (type);
4956                 token = mono_metadata_token_from_dor (
4957                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4958         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4959                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4960                 token = mono_metadata_token_from_dor (
4961                         mono_image_typedef_or_ref (assembly, type));
4962         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4963                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4964                 token = mono_metadata_token_from_dor (
4965                         mono_image_typedef_or_ref (assembly, type));
4966         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4967                    strcmp (klass->name, "MonoMethod") == 0 ||
4968                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4969                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4970                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4971                 if (m->method->is_inflated) {
4972                         if (create_open_instance)
4973                                 token = mono_image_get_methodspec_token (assembly, m->method);
4974                         else
4975                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4976                 } else if ((m->method->klass->image == &assembly->image) &&
4977                          !m->method->klass->generic_class) {
4978                         static guint32 method_table_idx = 0xffffff;
4979                         if (m->method->klass->wastypebuilder) {
4980                                 /* we use the same token as the one that was assigned
4981                                  * to the Methodbuilder.
4982                                  * FIXME: do the equivalent for Fields.
4983                                  */
4984                                 token = m->method->token;
4985                         } else {
4986                                 /*
4987                                  * Each token should have a unique index, but the indexes are
4988                                  * assigned by managed code, so we don't know about them. An
4989                                  * easy solution is to count backwards...
4990                                  */
4991                                 method_table_idx --;
4992                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4993                         }
4994                 } else {
4995                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4996                 }
4997                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4998         } else if (strcmp (klass->name, "MonoField") == 0) {
4999                 MonoReflectionField *f = (MonoReflectionField *)obj;
5000                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5001                         static guint32 field_table_idx = 0xffffff;
5002                         field_table_idx --;
5003                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5004                 } else {
5005                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5006                 }
5007                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5008         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5009                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5010                 token = mono_image_get_array_token (assembly, m);
5011         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5012                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5013                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5014         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5015                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5016                 token = mono_metadata_token_from_dor (
5017                         mono_image_typedef_or_ref (assembly, type));
5018         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5019                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5020                 token = mono_image_get_field_on_inst_token (assembly, f);
5021         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5022                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5023                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5024         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5025                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5026                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5027         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5028                 MonoReflectionType *type = (MonoReflectionType *)obj;
5029                 token = mono_metadata_token_from_dor (
5030                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5031         } else {
5032                 g_error ("requested token for %s\n", klass->name);
5033         }
5034
5035         if (register_token)
5036                 mono_image_register_token (assembly, token, obj);
5037
5038         return token;
5039 }
5040
5041 /*
5042  * mono_image_register_token:
5043  *
5044  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5045  * the Module.ResolveXXXToken () methods to work.
5046  */
5047 void
5048 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5049 {
5050         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5051         if (prev) {
5052                 /* There could be multiple MethodInfo objects with the same token */
5053                 //g_assert (prev == obj);
5054         } else {
5055                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5056         }
5057 }
5058
5059 static MonoDynamicImage*
5060 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5061 {
5062         static const guchar entrycode [16] = {0xff, 0x25, 0};
5063         MonoDynamicImage *image;
5064         int i;
5065
5066         const char *version;
5067
5068         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5069                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5070         else
5071                 version = mono_get_runtime_info ()->runtime_version;
5072
5073 #if HAVE_BOEHM_GC
5074         /* The MonoGHashTable's need GC tracking */
5075         image = GC_MALLOC (sizeof (MonoDynamicImage));
5076 #else
5077         image = g_new0 (MonoDynamicImage, 1);
5078 #endif
5079         
5080         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5081         
5082         /*g_print ("created image %p\n", image);*/
5083         /* keep in sync with image.c */
5084         image->image.name = assembly_name;
5085         image->image.assembly_name = image->image.name; /* they may be different */
5086         image->image.module_name = module_name;
5087         image->image.version = g_strdup (version);
5088         image->image.md_version_major = 1;
5089         image->image.md_version_minor = 1;
5090         image->image.dynamic = TRUE;
5091
5092         image->image.references = g_new0 (MonoAssembly*, 1);
5093         image->image.references [0] = NULL;
5094
5095         mono_image_init (&image->image);
5096
5097         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5098         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5099         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5100         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5101         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5102         image->handleref = g_hash_table_new (NULL, NULL);
5103         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5104         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5105         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5106         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5107         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5108         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5109         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5110         image->gen_params = g_ptr_array_new ();
5111
5112         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5113         string_heap_init (&image->sheap);
5114         mono_image_add_stream_data (&image->us, "", 1);
5115         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5116         /* import tables... */
5117         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5118         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5119         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5120         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5121         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5122         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5123         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5124         stream_data_align (&image->code);
5125
5126         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5127
5128         for (i=0; i < MONO_TABLE_NUM; ++i) {
5129                 image->tables [i].next_idx = 1;
5130                 image->tables [i].columns = table_sizes [i];
5131         }
5132
5133         image->image.assembly = (MonoAssembly*)assembly;
5134         image->run = assembly->run;
5135         image->save = assembly->save;
5136         image->pe_kind = 0x1; /* ILOnly */
5137         image->machine = 0x14c; /* I386 */
5138         
5139         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5140
5141         return image;
5142 }
5143 #endif
5144
5145 static void
5146 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5147 {
5148         g_free (key);
5149 }
5150
5151 void
5152 mono_dynamic_image_free (MonoDynamicImage *image)
5153 {
5154         MonoDynamicImage *di = image;
5155         GList *list;
5156         int i;
5157
5158         if (di->methodspec)
5159                 mono_g_hash_table_destroy (di->methodspec);
5160         if (di->typespec)
5161                 g_hash_table_destroy (di->typespec);
5162         if (di->typeref)
5163                 g_hash_table_destroy (di->typeref);
5164         if (di->handleref)
5165                 g_hash_table_destroy (di->handleref);
5166         if (di->handleref_managed)
5167                 mono_g_hash_table_destroy (di->handleref_managed);
5168         if (di->tokens)
5169                 mono_g_hash_table_destroy (di->tokens);
5170         if (di->generic_def_objects)
5171                 mono_g_hash_table_destroy (di->generic_def_objects);
5172         if (di->blob_cache) {
5173                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5174                 g_hash_table_destroy (di->blob_cache);
5175         }
5176         if (di->standalonesig_cache)
5177                 g_hash_table_destroy (di->standalonesig_cache);
5178         for (list = di->array_methods; list; list = list->next) {
5179                 ArrayMethod *am = (ArrayMethod *)list->data;
5180                 g_free (am->sig);
5181                 g_free (am->name);
5182                 g_free (am);
5183         }
5184         g_list_free (di->array_methods);
5185         if (di->gen_params) {
5186                 for (i = 0; i < di->gen_params->len; i++) {
5187                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5188                         mono_gc_deregister_root ((char*) &entry->gparam);
5189                         g_free (entry);
5190                 }
5191                 g_ptr_array_free (di->gen_params, TRUE);
5192         }
5193         if (di->token_fixups)
5194                 mono_g_hash_table_destroy (di->token_fixups);
5195         if (di->method_to_table_idx)
5196                 g_hash_table_destroy (di->method_to_table_idx);
5197         if (di->field_to_table_idx)
5198                 g_hash_table_destroy (di->field_to_table_idx);
5199         if (di->method_aux_hash)
5200                 g_hash_table_destroy (di->method_aux_hash);
5201         if (di->vararg_aux_hash)
5202                 g_hash_table_destroy (di->vararg_aux_hash);
5203         g_free (di->strong_name);
5204         g_free (di->win32_res);
5205         if (di->public_key)
5206                 g_free (di->public_key);
5207
5208         /*g_print ("string heap destroy for image %p\n", di);*/
5209         mono_dynamic_stream_reset (&di->sheap);
5210         mono_dynamic_stream_reset (&di->code);
5211         mono_dynamic_stream_reset (&di->resources);
5212         mono_dynamic_stream_reset (&di->us);
5213         mono_dynamic_stream_reset (&di->blob);
5214         mono_dynamic_stream_reset (&di->tstream);
5215         mono_dynamic_stream_reset (&di->guid);
5216         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5217                 g_free (di->tables [i].values);
5218         }
5219 }       
5220
5221 #ifndef DISABLE_REFLECTION_EMIT
5222
5223 /*
5224  * mono_image_basic_init:
5225  * @assembly: an assembly builder object
5226  *
5227  * Create the MonoImage that represents the assembly builder and setup some
5228  * of the helper hash table and the basic metadata streams.
5229  */
5230 void
5231 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5232 {
5233         MonoDynamicAssembly *assembly;
5234         MonoDynamicImage *image;
5235         MonoDomain *domain = mono_object_domain (assemblyb);
5236         
5237         MONO_ARCH_SAVE_REGS;
5238
5239         if (assemblyb->dynamic_assembly)
5240                 return;
5241
5242 #if HAVE_BOEHM_GC
5243         /* assembly->assembly.image might be GC allocated */
5244         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5245 #else
5246         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5247 #endif
5248
5249         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5250         
5251         assembly->assembly.ref_count = 1;
5252         assembly->assembly.dynamic = TRUE;
5253         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5254         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5255         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5256         if (assemblyb->culture)
5257                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5258         else
5259                 assembly->assembly.aname.culture = g_strdup ("");
5260
5261         if (assemblyb->version) {
5262                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5263                         char **version = g_strsplit (vstr, ".", 4);
5264                         char **parts = version;
5265                         assembly->assembly.aname.major = atoi (*parts++);
5266                         assembly->assembly.aname.minor = atoi (*parts++);
5267                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5268                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5269
5270                         g_strfreev (version);
5271                         g_free (vstr);
5272         } else {
5273                         assembly->assembly.aname.major = 0;
5274                         assembly->assembly.aname.minor = 0;
5275                         assembly->assembly.aname.build = 0;
5276                         assembly->assembly.aname.revision = 0;
5277         }
5278
5279         assembly->run = assemblyb->access != 2;
5280         assembly->save = assemblyb->access != 1;
5281         assembly->domain = domain;
5282
5283         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5284         image->initial_image = TRUE;
5285         assembly->assembly.aname.name = image->image.name;
5286         assembly->assembly.image = &image->image;
5287         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5288                 /* -1 to correct for the trailing NULL byte */
5289                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5290                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5291                 }
5292                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5293         }
5294
5295         mono_domain_assemblies_lock (domain);
5296         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5297         mono_domain_assemblies_unlock (domain);
5298
5299         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5300         
5301         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5302         
5303         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5304 }
5305
5306 #endif /* !DISABLE_REFLECTION_EMIT */
5307
5308 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5309
5310 static int
5311 calc_section_size (MonoDynamicImage *assembly)
5312 {
5313         int nsections = 0;
5314
5315         /* alignment constraints */
5316         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5317         g_assert ((assembly->code.index % 4) == 0);
5318         assembly->meta_size += 3;
5319         assembly->meta_size &= ~3;
5320         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5321         g_assert ((assembly->resources.index % 4) == 0);
5322
5323         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5324         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5325         nsections++;
5326
5327         if (assembly->win32_res) {
5328                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5329
5330                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5331                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5332                 nsections++;
5333         }
5334
5335         assembly->sections [MONO_SECTION_RELOC].size = 12;
5336         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5337         nsections++;
5338
5339         return nsections;
5340 }
5341
5342 typedef struct {
5343         guint32 id;
5344         guint32 offset;
5345         GSList *children;
5346         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5347 } ResTreeNode;
5348
5349 static int
5350 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5351 {
5352         ResTreeNode *t1 = (ResTreeNode*)a;
5353         ResTreeNode *t2 = (ResTreeNode*)b;
5354
5355         return t1->id - t2->id;
5356 }
5357
5358 /*
5359  * resource_tree_create:
5360  *
5361  *  Organize the resources into a resource tree.
5362  */
5363 static ResTreeNode *
5364 resource_tree_create (MonoArray *win32_resources)
5365 {
5366         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5367         GSList *l;
5368         int i;
5369
5370         tree = g_new0 (ResTreeNode, 1);
5371         
5372         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5373                 MonoReflectionWin32Resource *win32_res =
5374                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5375
5376                 /* Create node */
5377
5378                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5379                 lang_node = g_new0 (ResTreeNode, 1);
5380                 lang_node->id = win32_res->lang_id;
5381                 lang_node->win32_res = win32_res;
5382
5383                 /* Create type node if neccesary */
5384                 type_node = NULL;
5385                 for (l = tree->children; l; l = l->next)
5386                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5387                                 type_node = (ResTreeNode*)l->data;
5388                                 break;
5389                         }
5390
5391                 if (!type_node) {
5392                         type_node = g_new0 (ResTreeNode, 1);
5393                         type_node->id = win32_res->res_type;
5394
5395                         /* 
5396                          * The resource types have to be sorted otherwise
5397                          * Windows Explorer can't display the version information.
5398                          */
5399                         tree->children = g_slist_insert_sorted (tree->children, 
5400                                 type_node, resource_tree_compare_by_id);
5401                 }
5402
5403                 /* Create res node if neccesary */
5404                 res_node = NULL;
5405                 for (l = type_node->children; l; l = l->next)
5406                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5407                                 res_node = (ResTreeNode*)l->data;
5408                                 break;
5409                         }
5410
5411                 if (!res_node) {
5412                         res_node = g_new0 (ResTreeNode, 1);
5413                         res_node->id = win32_res->res_id;
5414                         type_node->children = g_slist_append (type_node->children, res_node);
5415                 }
5416
5417                 res_node->children = g_slist_append (res_node->children, lang_node);
5418         }
5419
5420         return tree;
5421 }
5422
5423 /*
5424  * resource_tree_encode:
5425  * 
5426  *   Encode the resource tree into the format used in the PE file.
5427  */
5428 static void
5429 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5430 {
5431         char *entries;
5432         MonoPEResourceDir dir;
5433         MonoPEResourceDirEntry dir_entry;
5434         MonoPEResourceDataEntry data_entry;
5435         GSList *l;
5436         guint32 res_id_entries;
5437
5438         /*
5439          * For the format of the resource directory, see the article
5440          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5441          * Matt Pietrek
5442          */
5443
5444         memset (&dir, 0, sizeof (dir));
5445         memset (&dir_entry, 0, sizeof (dir_entry));
5446         memset (&data_entry, 0, sizeof (data_entry));
5447
5448         g_assert (sizeof (dir) == 16);
5449         g_assert (sizeof (dir_entry) == 8);
5450         g_assert (sizeof (data_entry) == 16);
5451
5452         node->offset = p - begin;
5453
5454         /* IMAGE_RESOURCE_DIRECTORY */
5455         res_id_entries = g_slist_length (node->children);
5456         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5457
5458         memcpy (p, &dir, sizeof (dir));
5459         p += sizeof (dir);
5460
5461         /* Reserve space for entries */
5462         entries = p;
5463         p += sizeof (dir_entry) * res_id_entries;
5464
5465         /* Write children */
5466         for (l = node->children; l; l = l->next) {
5467                 ResTreeNode *child = (ResTreeNode*)l->data;
5468
5469                 if (child->win32_res) {
5470                         guint32 size;
5471
5472                         child->offset = p - begin;
5473
5474                         /* IMAGE_RESOURCE_DATA_ENTRY */
5475                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5476                         size = mono_array_length (child->win32_res->res_data);
5477                         data_entry.rde_size = GUINT32_TO_LE (size);
5478
5479                         memcpy (p, &data_entry, sizeof (data_entry));
5480                         p += sizeof (data_entry);
5481
5482                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5483                         p += size;
5484                 } else {
5485                         resource_tree_encode (child, begin, p, &p);
5486                 }
5487         }
5488
5489         /* IMAGE_RESOURCE_ENTRY */
5490         for (l = node->children; l; l = l->next) {
5491                 ResTreeNode *child = (ResTreeNode*)l->data;
5492
5493                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5494                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5495
5496                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5497                 entries += sizeof (dir_entry);
5498         }
5499
5500         *endbuf = p;
5501 }
5502
5503 static void
5504 resource_tree_free (ResTreeNode * node)
5505 {
5506         GSList * list;
5507         for (list = node->children; list; list = list->next)
5508                 resource_tree_free ((ResTreeNode*)list->data);
5509         g_slist_free(node->children);
5510         g_free (node);
5511 }
5512
5513 static void
5514 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5515 {
5516         char *buf;
5517         char *p;
5518         guint32 size, i;
5519         MonoReflectionWin32Resource *win32_res;
5520         ResTreeNode *tree;
5521
5522         if (!assemblyb->win32_resources)
5523                 return;
5524
5525         /*
5526          * Resources are stored in a three level tree inside the PE file.
5527          * - level one contains a node for each type of resource
5528          * - level two contains a node for each resource
5529          * - level three contains a node for each instance of a resource for a
5530          *   specific language.
5531          */
5532
5533         tree = resource_tree_create (assemblyb->win32_resources);
5534
5535         /* Estimate the size of the encoded tree */
5536         size = 0;
5537         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5538                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5539                 size += mono_array_length (win32_res->res_data);
5540         }
5541         /* Directory structure */
5542         size += mono_array_length (assemblyb->win32_resources) * 256;
5543         p = buf = g_malloc (size);
5544
5545         resource_tree_encode (tree, p, p, &p);
5546
5547         g_assert (p - buf <= size);
5548
5549         assembly->win32_res = g_malloc (p - buf);
5550         assembly->win32_res_size = p - buf;
5551         memcpy (assembly->win32_res, buf, p - buf);
5552
5553         g_free (buf);
5554         resource_tree_free (tree);
5555 }
5556
5557 static void
5558 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5559 {
5560         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5561         int i;
5562
5563         p += sizeof (MonoPEResourceDir);
5564         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5565                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5566                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5567                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5568                         fixup_resource_directory (res_section, child, rva);
5569                 } else {
5570                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5571                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5572                 }
5573
5574                 p += sizeof (MonoPEResourceDirEntry);
5575         }
5576 }
5577
5578 static void
5579 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5580 {
5581         guint32 dummy;
5582         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5583                 g_error ("WriteFile returned %d\n", GetLastError ());
5584 }
5585
5586 /*
5587  * mono_image_create_pefile:
5588  * @mb: a module builder object
5589  * 
5590  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5591  * assembly->pefile where it can be easily retrieved later in chunks.
5592  */
5593 void
5594 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5595 {
5596         MonoMSDOSHeader *msdos;
5597         MonoDotNetHeader *header;
5598         MonoSectionTable *section;
5599         MonoCLIHeader *cli_header;
5600         guint32 size, image_size, virtual_base, text_offset;
5601         guint32 header_start, section_start, file_offset, virtual_offset;
5602         MonoDynamicImage *assembly;
5603         MonoReflectionAssemblyBuilder *assemblyb;
5604         MonoDynamicStream pefile_stream = {0};
5605         MonoDynamicStream *pefile = &pefile_stream;
5606         int i, nsections;
5607         guint32 *rva, value;
5608         guchar *p;
5609         static const unsigned char msheader[] = {
5610                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5611                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5612                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5613                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5614                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5615                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5616                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5617                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5618         };
5619
5620         assemblyb = mb->assemblyb;
5621
5622         mono_image_basic_init (assemblyb);
5623         assembly = mb->dynamic_image;
5624
5625         assembly->pe_kind = assemblyb->pe_kind;
5626         assembly->machine = assemblyb->machine;
5627         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5628         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5629         
5630         mono_image_build_metadata (mb);
5631
5632         if (mb->is_main && assemblyb->resources) {
5633                 int len = mono_array_length (assemblyb->resources);
5634                 for (i = 0; i < len; ++i)
5635                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5636         }
5637
5638         if (mb->resources) {
5639                 int len = mono_array_length (mb->resources);
5640                 for (i = 0; i < len; ++i)
5641                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5642         }
5643
5644         build_compressed_metadata (assembly);
5645
5646         if (mb->is_main)
5647                 assembly_add_win32_resources (assembly, assemblyb);
5648
5649         nsections = calc_section_size (assembly);
5650         
5651         /* The DOS header and stub */
5652         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5653         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5654
5655         /* the dotnet header */
5656         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5657
5658         /* the section tables */
5659         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5660
5661         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5662         virtual_offset = VIRT_ALIGN;
5663         image_size = 0;
5664
5665         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5666                 if (!assembly->sections [i].size)
5667                         continue;
5668                 /* align offsets */
5669                 file_offset += FILE_ALIGN - 1;
5670                 file_offset &= ~(FILE_ALIGN - 1);
5671                 virtual_offset += VIRT_ALIGN - 1;
5672                 virtual_offset &= ~(VIRT_ALIGN - 1);
5673
5674                 assembly->sections [i].offset = file_offset;
5675                 assembly->sections [i].rva = virtual_offset;
5676
5677                 file_offset += assembly->sections [i].size;
5678                 virtual_offset += assembly->sections [i].size;
5679                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5680         }
5681
5682         file_offset += FILE_ALIGN - 1;
5683         file_offset &= ~(FILE_ALIGN - 1);
5684
5685         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5686
5687         /* back-patch info */
5688         msdos = (MonoMSDOSHeader*)pefile->data;
5689         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5690
5691         header = (MonoDotNetHeader*)(pefile->data + header_start);
5692         header->pesig [0] = 'P';
5693         header->pesig [1] = 'E';
5694         
5695         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5696         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5697         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5698         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5699         if (assemblyb->pekind == 1) {
5700                 /* it's a dll */
5701                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5702         } else {
5703                 /* it's an exe */
5704                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5705         }
5706
5707         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5708
5709         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5710         header->pe.pe_major = 6;
5711         header->pe.pe_minor = 0;
5712         size = assembly->sections [MONO_SECTION_TEXT].size;
5713         size += FILE_ALIGN - 1;
5714         size &= ~(FILE_ALIGN - 1);
5715         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5716         size = assembly->sections [MONO_SECTION_RSRC].size;
5717         size += FILE_ALIGN - 1;
5718         size &= ~(FILE_ALIGN - 1);
5719         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5720         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5721         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5722         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5723         /* pe_rva_entry_point always at the beginning of the text section */
5724         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5725
5726         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5727         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5728         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5729         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5730         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5731         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5732         size = section_start;
5733         size += FILE_ALIGN - 1;
5734         size &= ~(FILE_ALIGN - 1);
5735         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5736         size = image_size;
5737         size += VIRT_ALIGN - 1;
5738         size &= ~(VIRT_ALIGN - 1);
5739         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5740
5741         /*
5742         // Translate the PEFileKind value to the value expected by the Windows loader
5743         */
5744         {
5745                 short kind;
5746
5747                 /*
5748                 // PEFileKinds.Dll == 1
5749                 // PEFileKinds.ConsoleApplication == 2
5750                 // PEFileKinds.WindowApplication == 3
5751                 //
5752                 // need to get:
5753                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5754                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5755                 */
5756                 if (assemblyb->pekind == 3)
5757                         kind = 2;
5758                 else
5759                         kind = 3;
5760                 
5761                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5762         }    
5763         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5764         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5765         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5766         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5767         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5768         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5769
5770         /* fill data directory entries */
5771
5772         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5773         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5774
5775         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5776         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5777
5778         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5779         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5780         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5781         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5782         /* patch entrypoint name */
5783         if (assemblyb->pekind == 1)
5784                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5785         else
5786                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5787         /* patch imported function RVA name */
5788         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5789         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5790
5791         /* the import table */
5792         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5793         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5794         /* patch imported dll RVA name and other entries in the dir */
5795         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5796         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5797         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5798         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5799         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5800         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5801
5802         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5803         value = (assembly->text_rva + assembly->imp_names_offset);
5804         *p++ = (value) & 0xff;
5805         *p++ = (value >> 8) & (0xff);
5806         *p++ = (value >> 16) & (0xff);
5807         *p++ = (value >> 24) & (0xff);
5808
5809         /* the CLI header info */
5810         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5811         cli_header->ch_size = GUINT32_FROM_LE (72);
5812         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5813         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5814         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5815         if (assemblyb->entry_point) {
5816                 guint32 table_idx = 0;
5817                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5818                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5819                         table_idx = methodb->table_idx;
5820                 } else {
5821                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5822                 }
5823                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5824         } else {
5825                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5826         }
5827         /* The embedded managed resources */
5828         text_offset = assembly->text_rva + assembly->code.index;
5829         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5830         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5831         text_offset += assembly->resources.index;
5832         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5833         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5834         text_offset += assembly->meta_size;
5835         if (assembly->strong_name_size) {
5836                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5837                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5838                 text_offset += assembly->strong_name_size;
5839         }
5840
5841         /* write the section tables and section content */
5842         section = (MonoSectionTable*)(pefile->data + section_start);
5843         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5844                 static const char section_names [][7] = {
5845                         ".text", ".rsrc", ".reloc"
5846                 };
5847                 if (!assembly->sections [i].size)
5848                         continue;
5849                 strcpy (section->st_name, section_names [i]);
5850                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5851                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5852                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5853                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5854                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5855                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5856                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5857                 section ++;
5858         }
5859         
5860         checked_write_file (file, pefile->data, pefile->index);
5861         
5862         mono_dynamic_stream_reset (pefile);
5863         
5864         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5865                 if (!assembly->sections [i].size)
5866                         continue;
5867                 
5868                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5869                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5870                 
5871                 switch (i) {
5872                 case MONO_SECTION_TEXT:
5873                         /* patch entry point */
5874                         p = (guchar*)(assembly->code.data + 2);
5875                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5876                         *p++ = (value) & 0xff;
5877                         *p++ = (value >> 8) & 0xff;
5878                         *p++ = (value >> 16) & 0xff;
5879                         *p++ = (value >> 24) & 0xff;
5880                 
5881                         checked_write_file (file, assembly->code.data, assembly->code.index);
5882                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5883                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5884                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5885                                 
5886
5887                         g_free (assembly->image.raw_metadata);
5888                         break;
5889                 case MONO_SECTION_RELOC: {
5890                         struct {
5891                                 guint32 page_rva;
5892                                 guint32 block_size;
5893                                 guint16 type_and_offset;
5894                                 guint16 term;
5895                         } reloc;
5896                         
5897                         g_assert (sizeof (reloc) == 12);
5898                         
5899                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5900                         reloc.block_size = GUINT32_FROM_LE (12);
5901                         
5902                         /* 
5903                          * the entrypoint is always at the start of the text section 
5904                          * 3 is IMAGE_REL_BASED_HIGHLOW
5905                          * 2 is patch_size_rva - text_rva
5906                          */
5907                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5908                         reloc.term = 0;
5909                         
5910                         checked_write_file (file, &reloc, sizeof (reloc));
5911                         
5912                         break;
5913                 }
5914                 case MONO_SECTION_RSRC:
5915                         if (assembly->win32_res) {
5916
5917                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5918                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5919                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5920                         }
5921                         break;
5922                 default:
5923                         g_assert_not_reached ();
5924                 }
5925         }
5926         
5927         /* check that the file is properly padded */
5928         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5929                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5930         if (! SetEndOfFile (file))
5931                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5932         
5933         mono_dynamic_stream_reset (&assembly->code);
5934         mono_dynamic_stream_reset (&assembly->us);
5935         mono_dynamic_stream_reset (&assembly->blob);
5936         mono_dynamic_stream_reset (&assembly->guid);
5937         mono_dynamic_stream_reset (&assembly->sheap);
5938
5939         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5940         g_hash_table_destroy (assembly->blob_cache);
5941         assembly->blob_cache = NULL;
5942 }
5943
5944 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5945
5946 void
5947 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5948 {
5949         g_assert_not_reached ();
5950 }
5951
5952 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5953
5954 #ifndef DISABLE_REFLECTION_EMIT
5955
5956 MonoReflectionModule *
5957 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5958 {
5959         char *name;
5960         MonoImage *image;
5961         MonoImageOpenStatus status;
5962         MonoDynamicAssembly *assembly;
5963         guint32 module_count;
5964         MonoImage **new_modules;
5965         gboolean *new_modules_loaded;
5966         
5967         name = mono_string_to_utf8 (fileName);
5968
5969         image = mono_image_open (name, &status);
5970         if (!image) {
5971                 MonoException *exc;
5972                 if (status == MONO_IMAGE_ERROR_ERRNO)
5973                         exc = mono_get_exception_file_not_found (fileName);
5974                 else
5975                         exc = mono_get_exception_bad_image_format (name);
5976                 g_free (name);
5977                 mono_raise_exception (exc);
5978         }
5979
5980         g_free (name);
5981
5982         assembly = ab->dynamic_assembly;
5983         image->assembly = (MonoAssembly*)assembly;
5984
5985         module_count = image->assembly->image->module_count;
5986         new_modules = g_new0 (MonoImage *, module_count + 1);
5987         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5988
5989         if (image->assembly->image->modules)
5990                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5991         if (image->assembly->image->modules_loaded)
5992                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5993         new_modules [module_count] = image;
5994         new_modules_loaded [module_count] = TRUE;
5995         mono_image_addref (image);
5996
5997         g_free (image->assembly->image->modules);
5998         image->assembly->image->modules = new_modules;
5999         image->assembly->image->modules_loaded = new_modules_loaded;
6000         image->assembly->image->module_count ++;
6001
6002         mono_assembly_load_references (image, &status);
6003         if (status) {
6004                 mono_image_close (image);
6005                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6006         }
6007
6008         return mono_module_get_object (mono_domain_get (), image);
6009 }
6010
6011 #endif /* DISABLE_REFLECTION_EMIT */
6012
6013 /*
6014  * We need to return always the same object for MethodInfo, FieldInfo etc..
6015  * but we need to consider the reflected type.
6016  * type uses a different hash, since it uses custom hash/equal functions.
6017  */
6018
6019 typedef struct {
6020         gpointer item;
6021         MonoClass *refclass;
6022 } ReflectedEntry;
6023
6024 static gboolean
6025 reflected_equal (gconstpointer a, gconstpointer b) {
6026         const ReflectedEntry *ea = a;
6027         const ReflectedEntry *eb = b;
6028
6029         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6030 }
6031
6032 static guint
6033 reflected_hash (gconstpointer a) {
6034         const ReflectedEntry *ea = a;
6035         return mono_aligned_addr_hash (ea->item);
6036 }
6037
6038 #define CHECK_OBJECT(t,p,k)     \
6039         do {    \
6040                 t _obj; \
6041                 ReflectedEntry e;       \
6042                 e.item = (p);   \
6043                 e.refclass = (k);       \
6044                 mono_domain_lock (domain);      \
6045                 if (!domain->refobject_hash)    \
6046                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6047                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6048                         mono_domain_unlock (domain);    \
6049                         return _obj;    \
6050                 }       \
6051         mono_domain_unlock (domain); \
6052         } while (0)
6053
6054 #ifdef HAVE_BOEHM_GC
6055 /* ReflectedEntry doesn't need to be GC tracked */
6056 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6057 #define FREE_REFENTRY(entry) g_free ((entry))
6058 #define REFENTRY_REQUIRES_CLEANUP
6059 #else
6060 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6061 /* FIXME: */
6062 #define FREE_REFENTRY(entry)
6063 #endif
6064
6065 #define CACHE_OBJECT(t,p,o,k)   \
6066         do {    \
6067                 t _obj; \
6068         ReflectedEntry pe; \
6069         pe.item = (p); \
6070         pe.refclass = (k); \
6071         mono_domain_lock (domain); \
6072                 if (!domain->refobject_hash)    \
6073                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6074         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6075         if (!_obj) { \
6076                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6077                     e->item = (p);      \
6078                     e->refclass = (k);  \
6079                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6080             _obj = o; \
6081         } \
6082                 mono_domain_unlock (domain);    \
6083         return _obj; \
6084         } while (0)
6085
6086 static void
6087 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6088 {
6089         mono_domain_lock (domain);
6090         if (domain->refobject_hash) {
6091         ReflectedEntry pe;
6092                 gpointer orig_pe, orig_value;
6093
6094                 pe.item = o;
6095                 pe.refclass = klass;
6096                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6097                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6098                         FREE_REFENTRY (orig_pe);
6099                 }
6100         }
6101         mono_domain_unlock (domain);
6102 }
6103
6104 #ifdef REFENTRY_REQUIRES_CLEANUP
6105 static void
6106 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6107 {
6108         FREE_REFENTRY (key);
6109 }
6110 #endif
6111
6112 void
6113 mono_reflection_cleanup_domain (MonoDomain *domain)
6114 {
6115         if (domain->refobject_hash) {
6116 /*let's avoid scanning the whole hashtable if not needed*/
6117 #ifdef REFENTRY_REQUIRES_CLEANUP
6118                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6119 #endif
6120                 mono_g_hash_table_destroy (domain->refobject_hash);
6121                 domain->refobject_hash = NULL;
6122         }
6123 }
6124
6125 #ifndef DISABLE_REFLECTION_EMIT
6126 static gpointer
6127 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6128 {
6129         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6130 }
6131
6132 static gpointer
6133 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6134 {
6135         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6136 }
6137
6138 void
6139 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6140 {
6141         MonoDynamicImage *image = moduleb->dynamic_image;
6142         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6143         if (!image) {
6144                 MonoError error;
6145                 int module_count;
6146                 MonoImage **new_modules;
6147                 MonoImage *ass;
6148                 char *name, *fqname;
6149                 /*
6150                  * FIXME: we already created an image in mono_image_basic_init (), but
6151                  * we don't know which module it belongs to, since that is only 
6152                  * determined at assembly save time.
6153                  */
6154                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6155                 name = mono_string_to_utf8 (ab->name);
6156                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6157                 if (!mono_error_ok (&error)) {
6158                         g_free (name);
6159                         mono_error_raise_exception (&error);
6160                 }
6161                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6162
6163                 moduleb->module.image = &image->image;
6164                 moduleb->dynamic_image = image;
6165                 register_module (mono_object_domain (moduleb), moduleb, image);
6166
6167                 /* register the module with the assembly */
6168                 ass = ab->dynamic_assembly->assembly.image;
6169                 module_count = ass->module_count;
6170                 new_modules = g_new0 (MonoImage *, module_count + 1);
6171
6172                 if (ass->modules)
6173                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6174                 new_modules [module_count] = &image->image;
6175                 mono_image_addref (&image->image);
6176
6177                 g_free (ass->modules);
6178                 ass->modules = new_modules;
6179                 ass->module_count ++;
6180         }
6181 }
6182
6183 void
6184 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6185 {
6186         MonoDynamicImage *image = moduleb->dynamic_image;
6187
6188         g_assert (type->type);
6189         image->wrappers_type = mono_class_from_mono_type (type->type);
6190 }
6191
6192 #endif
6193
6194 /*
6195  * mono_assembly_get_object:
6196  * @domain: an app domain
6197  * @assembly: an assembly
6198  *
6199  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6200  */
6201 MonoReflectionAssembly*
6202 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6203 {
6204         static MonoClass *assembly_type;
6205         MonoReflectionAssembly *res;
6206         
6207         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6208         if (!assembly_type) {
6209                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6210                 if (class == NULL)
6211                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6212                 g_assert (class);
6213                 assembly_type = class;
6214         }
6215         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6216         res->assembly = assembly;
6217
6218         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6219 }
6220
6221
6222
6223 MonoReflectionModule*   
6224 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6225 {
6226         static MonoClass *module_type;
6227         MonoReflectionModule *res;
6228         char* basename;
6229         
6230         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6231         if (!module_type) {
6232                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6233                 if (class == NULL)
6234                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6235                 g_assert (class);
6236                 module_type = class;
6237         }
6238         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6239
6240         res->image = image;
6241         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6242
6243         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6244         basename = g_path_get_basename (image->name);
6245         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6246         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6247         
6248         g_free (basename);
6249
6250         if (image->assembly->image == image) {
6251                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6252         } else {
6253                 int i;
6254                 res->token = 0;
6255                 if (image->assembly->image->modules) {
6256                         for (i = 0; i < image->assembly->image->module_count; i++) {
6257                                 if (image->assembly->image->modules [i] == image)
6258                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6259                         }
6260                         g_assert (res->token);
6261                 }
6262         }
6263
6264         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6265 }
6266
6267 MonoReflectionModule*   
6268 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6269 {
6270         static MonoClass *module_type;
6271         MonoReflectionModule *res;
6272         MonoTableInfo *table;
6273         guint32 cols [MONO_FILE_SIZE];
6274         const char *name;
6275         guint32 i, name_idx;
6276         const char *val;
6277         
6278         if (!module_type) {
6279                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6280                 if (class == NULL)
6281                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6282                 g_assert (class);
6283                 module_type = class;
6284         }
6285         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6286
6287         table = &image->tables [MONO_TABLE_FILE];
6288         g_assert (table_index < table->rows);
6289         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6290
6291         res->image = NULL;
6292         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6293         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6294
6295         /* Check whenever the row has a corresponding row in the moduleref table */
6296         table = &image->tables [MONO_TABLE_MODULEREF];
6297         for (i = 0; i < table->rows; ++i) {
6298                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6299                 val = mono_metadata_string_heap (image, name_idx);
6300                 if (strcmp (val, name) == 0)
6301                         res->image = image->modules [i];
6302         }
6303
6304         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6305         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6306         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6307         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6308         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6309
6310         return res;
6311 }
6312
6313 static gboolean
6314 verify_safe_for_managed_space (MonoType *type)
6315 {
6316         switch (type->type) {
6317 #ifdef DEBUG_HARDER
6318         case MONO_TYPE_ARRAY:
6319                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6320         case MONO_TYPE_PTR:
6321                 return verify_safe_for_managed_space (type->data.type);
6322         case MONO_TYPE_SZARRAY:
6323                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6324         case MONO_TYPE_GENERICINST: {
6325                 MonoGenericInst *inst = type->data.generic_class->inst;
6326                 int i;
6327                 if (!inst->is_open)
6328                         break;
6329                 for (i = 0; i < inst->type_argc; ++i)
6330                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6331                                 return FALSE;
6332                 break;
6333         }
6334 #endif
6335         case MONO_TYPE_VAR:
6336         case MONO_TYPE_MVAR:
6337                 return TRUE;
6338         }
6339         return TRUE;
6340 }
6341
6342 static MonoType*
6343 mono_type_normalize (MonoType *type)
6344 {
6345         int i;
6346         MonoGenericClass *gclass;
6347         MonoGenericInst *ginst;
6348         MonoClass *gtd;
6349         MonoGenericContainer *gcontainer;
6350         MonoType **argv = NULL;
6351         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6352
6353         if (type->type != MONO_TYPE_GENERICINST)
6354                 return type;
6355
6356         gclass = type->data.generic_class;
6357         ginst = gclass->context.class_inst;
6358         if (!ginst->is_open)
6359                 return type;
6360
6361         gtd = gclass->container_class;
6362         gcontainer = gtd->generic_container;
6363         argv = g_newa (MonoType*, ginst->type_argc);
6364
6365         for (i = 0; i < ginst->type_argc; ++i) {
6366                 MonoType *t = ginst->type_argv [i], *norm;
6367                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6368                         is_denorm_gtd = FALSE;
6369                 norm = mono_type_normalize (t);
6370                 argv [i] = norm;
6371                 if (norm != t)
6372                         requires_rebind = TRUE;
6373         }
6374
6375         if (is_denorm_gtd)
6376                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6377
6378         if (requires_rebind) {
6379                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6380                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6381         }
6382
6383         return type;
6384 }
6385 /*
6386  * mono_type_get_object:
6387  * @domain: an app domain
6388  * @type: a type
6389  *
6390  * Return an System.MonoType object representing the type @type.
6391  */
6392 MonoReflectionType*
6393 mono_type_get_object (MonoDomain *domain, MonoType *type)
6394 {
6395         MonoType *norm_type;
6396         MonoReflectionType *res;
6397         MonoClass *klass = mono_class_from_mono_type (type);
6398
6399         /*we must avoid using @type as it might have come
6400          * from a mono_metadata_type_dup and the caller
6401          * expects that is can be freed.
6402          * Using the right type from 
6403          */
6404         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6405
6406         /* void is very common */
6407         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6408                 return (MonoReflectionType*)domain->typeof_void;
6409
6410         /*
6411          * If the vtable of the given class was already created, we can use
6412          * the MonoType from there and avoid all locking and hash table lookups.
6413          * 
6414          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6415          * that the resulting object is different.   
6416          */
6417         if (type == &klass->byval_arg && !klass->image->dynamic) {
6418                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6419                 if (vtable && vtable->type)
6420                         return vtable->type;
6421         }
6422
6423         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6424         mono_domain_lock (domain);
6425         if (!domain->type_hash)
6426                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6427                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6428         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6429                 mono_domain_unlock (domain);
6430                 mono_loader_unlock ();
6431                 return res;
6432         }
6433
6434         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6435          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6436          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6437          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6438          * artifact of how generics are encoded and should be transparent to managed code so we
6439          * need to weed out this diference when retrieving managed System.Type objects.
6440          */
6441         norm_type = mono_type_normalize (type);
6442         if (norm_type != type) {
6443                 res = mono_type_get_object (domain, norm_type);
6444                 mono_g_hash_table_insert (domain->type_hash, type, res);
6445                 mono_domain_unlock (domain);
6446                 mono_loader_unlock ();
6447                 return res;
6448         }
6449
6450         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6451         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6452                 g_assert (0);
6453
6454         if (!verify_safe_for_managed_space (type)) {
6455                 mono_domain_unlock (domain);
6456                 mono_loader_unlock ();
6457                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6458         }
6459
6460         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6461                 gboolean is_type_done = TRUE;
6462                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6463                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6464                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6465                 */
6466                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6467                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6468
6469                         if (gparam->owner && gparam->owner->is_method) {
6470                                 MonoMethod *method = gparam->owner->owner.method;
6471                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6472                                         is_type_done = FALSE;
6473                         } else if (gparam->owner && !gparam->owner->is_method) {
6474                                 MonoClass *klass = gparam->owner->owner.klass;
6475                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6476                                         is_type_done = FALSE;
6477                         }
6478                 } 
6479
6480                 /* g_assert_not_reached (); */
6481                 /* should this be considered an error condition? */
6482                 if (is_type_done && !type->byref) {
6483                         mono_domain_unlock (domain);
6484                         mono_loader_unlock ();
6485                         return mono_class_get_ref_info (klass);
6486                 }
6487         }
6488         /* This is stored in vtables/JITted code so it has to be pinned */
6489         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6490         res->type = type;
6491         mono_g_hash_table_insert (domain->type_hash, type, res);
6492
6493         if (type->type == MONO_TYPE_VOID)
6494                 domain->typeof_void = (MonoObject*)res;
6495
6496         mono_domain_unlock (domain);
6497         mono_loader_unlock ();
6498         return res;
6499 }
6500
6501 /*
6502  * mono_method_get_object:
6503  * @domain: an app domain
6504  * @method: a method
6505  * @refclass: the reflected type (can be NULL)
6506  *
6507  * Return an System.Reflection.MonoMethod object representing the method @method.
6508  */
6509 MonoReflectionMethod*
6510 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6511 {
6512         /*
6513          * We use the same C representation for methods and constructors, but the type 
6514          * name in C# is different.
6515          */
6516         static MonoClass *System_Reflection_MonoMethod = NULL;
6517         static MonoClass *System_Reflection_MonoCMethod = NULL;
6518         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6519         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6520         MonoClass *klass;
6521         MonoReflectionMethod *ret;
6522
6523         if (method->is_inflated) {
6524                 MonoReflectionGenericMethod *gret;
6525
6526                 refclass = method->klass;
6527                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6528                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6529                         if (!System_Reflection_MonoGenericCMethod)
6530                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6531                         klass = System_Reflection_MonoGenericCMethod;
6532                 } else {
6533                         if (!System_Reflection_MonoGenericMethod)
6534                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6535                         klass = System_Reflection_MonoGenericMethod;
6536                 }
6537                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6538                 gret->method.method = method;
6539                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6540                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6541                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6542         }
6543
6544         if (!refclass)
6545                 refclass = method->klass;
6546
6547         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6548         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6549                 if (!System_Reflection_MonoCMethod)
6550                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6551                 klass = System_Reflection_MonoCMethod;
6552         }
6553         else {
6554                 if (!System_Reflection_MonoMethod)
6555                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6556                 klass = System_Reflection_MonoMethod;
6557         }
6558         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6559         ret->method = method;
6560         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6561         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6562 }
6563
6564 /*
6565  * mono_method_clear_object:
6566  *
6567  *   Clear the cached reflection objects for the dynamic method METHOD.
6568  */
6569 void
6570 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6571 {
6572         MonoClass *klass;
6573         g_assert (method->dynamic);
6574
6575         klass = method->klass;
6576         while (klass) {
6577                 clear_cached_object (domain, method, klass);
6578                 klass = klass->parent;
6579         }
6580         /* Added by mono_param_get_objects () */
6581         clear_cached_object (domain, &(method->signature), NULL);
6582         klass = method->klass;
6583         while (klass) {
6584                 clear_cached_object (domain, &(method->signature), klass);
6585                 klass = klass->parent;
6586         }
6587 }
6588
6589 /*
6590  * mono_field_get_object:
6591  * @domain: an app domain
6592  * @klass: a type
6593  * @field: a field
6594  *
6595  * Return an System.Reflection.MonoField object representing the field @field
6596  * in class @klass.
6597  */
6598 MonoReflectionField*
6599 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6600 {
6601         MonoReflectionField *res;
6602         static MonoClass *monofield_klass;
6603
6604         CHECK_OBJECT (MonoReflectionField *, field, klass);
6605         if (!monofield_klass)
6606                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6607         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6608         res->klass = klass;
6609         res->field = field;
6610         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6611
6612         if (is_field_on_inst (field)) {
6613                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6614                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6615         } else {
6616                 if (field->type)
6617                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6618                 res->attrs = mono_field_get_flags (field);
6619         }
6620         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6621 }
6622
6623 /*
6624  * mono_property_get_object:
6625  * @domain: an app domain
6626  * @klass: a type
6627  * @property: a property
6628  *
6629  * Return an System.Reflection.MonoProperty object representing the property @property
6630  * in class @klass.
6631  */
6632 MonoReflectionProperty*
6633 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6634 {
6635         MonoReflectionProperty *res;
6636         static MonoClass *monoproperty_klass;
6637
6638         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6639         if (!monoproperty_klass)
6640                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6641         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6642         res->klass = klass;
6643         res->property = property;
6644         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6645 }
6646
6647 /*
6648  * mono_event_get_object:
6649  * @domain: an app domain
6650  * @klass: a type
6651  * @event: a event
6652  *
6653  * Return an System.Reflection.MonoEvent object representing the event @event
6654  * in class @klass.
6655  */
6656 MonoReflectionEvent*
6657 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6658 {
6659         MonoReflectionEvent *res;
6660         MonoReflectionMonoEvent *mono_event;
6661         static MonoClass *monoevent_klass;
6662
6663         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6664         if (!monoevent_klass)
6665                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6666         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6667         mono_event->klass = klass;
6668         mono_event->event = event;
6669         res = (MonoReflectionEvent*)mono_event;
6670         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6671 }
6672
6673 /**
6674  * mono_get_reflection_missing_object:
6675  * @domain: Domain where the object lives
6676  *
6677  * Returns the System.Reflection.Missing.Value singleton object
6678  * (of type System.Reflection.Missing).
6679  *
6680  * Used as the value for ParameterInfo.DefaultValue when Optional
6681  * is present
6682  */
6683 static MonoObject *
6684 mono_get_reflection_missing_object (MonoDomain *domain)
6685 {
6686         MonoObject *obj;
6687         static MonoClassField *missing_value_field = NULL;
6688         
6689         if (!missing_value_field) {
6690                 MonoClass *missing_klass;
6691                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6692                 mono_class_init (missing_klass);
6693                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6694                 g_assert (missing_value_field);
6695         }
6696         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6697         g_assert (obj);
6698         return obj;
6699 }
6700
6701 static MonoObject*
6702 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6703 {
6704         if (!*dbnull)
6705                 *dbnull = mono_get_dbnull_object (domain);
6706         return *dbnull;
6707 }
6708
6709 static MonoObject*
6710 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6711 {
6712         if (!*reflection_missing)
6713                 *reflection_missing = mono_get_reflection_missing_object (domain);
6714         return *reflection_missing;
6715 }
6716
6717 /*
6718  * mono_param_get_objects:
6719  * @domain: an app domain
6720  * @method: a method
6721  *
6722  * Return an System.Reflection.ParameterInfo array object representing the parameters
6723  * in the method @method.
6724  */
6725 MonoArray*
6726 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6727 {
6728         static MonoClass *System_Reflection_ParameterInfo;
6729         static MonoClass *System_Reflection_ParameterInfo_array;
6730         MonoError error;
6731         MonoArray *res = NULL;
6732         MonoReflectionMethod *member = NULL;
6733         MonoReflectionParameter *param = NULL;
6734         char **names, **blobs = NULL;
6735         guint32 *types = NULL;
6736         MonoType *type = NULL;
6737         MonoObject *dbnull = NULL;
6738         MonoObject *missing = NULL;
6739         MonoMarshalSpec **mspecs;
6740         MonoMethodSignature *sig;
6741         MonoVTable *pinfo_vtable;
6742         int i;
6743
6744         if (!System_Reflection_ParameterInfo_array) {
6745                 MonoClass *klass;
6746
6747                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6748                 mono_memory_barrier ();
6749                 System_Reflection_ParameterInfo = klass; 
6750         
6751                 klass = mono_array_class_get (klass, 1);
6752                 mono_memory_barrier ();
6753                 System_Reflection_ParameterInfo_array = klass;
6754         }
6755
6756         sig = mono_method_signature_checked (method, &error);
6757         if (!mono_error_ok (&error))
6758                 mono_error_raise_exception (&error);
6759
6760         if (!sig->param_count)
6761                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6762
6763         /* Note: the cache is based on the address of the signature into the method
6764          * since we already cache MethodInfos with the method as keys.
6765          */
6766         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6767
6768         member = mono_method_get_object (domain, method, refclass);
6769         names = g_new (char *, sig->param_count);
6770         mono_method_get_param_names (method, (const char **) names);
6771
6772         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6773         mono_method_get_marshal_info (method, mspecs);
6774
6775         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6776         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6777         for (i = 0; i < sig->param_count; ++i) {
6778                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6779                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6780                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6781                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6782                 param->PositionImpl = i;
6783                 param->AttrsImpl = sig->params [i]->attrs;
6784
6785                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6786                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6787                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6788                         else
6789                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6790                 } else {
6791
6792                         if (!blobs) {
6793                                 blobs = g_new0 (char *, sig->param_count);
6794                                 types = g_new0 (guint32, sig->param_count);
6795                                 get_default_param_value_blobs (method, blobs, types); 
6796                         }
6797
6798                         /* Build MonoType for the type from the Constant Table */
6799                         if (!type)
6800                                 type = g_new0 (MonoType, 1);
6801                         type->type = types [i];
6802                         type->data.klass = NULL;
6803                         if (types [i] == MONO_TYPE_CLASS)
6804                                 type->data.klass = mono_defaults.object_class;
6805                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6806                                 /* For enums, types [i] contains the base type */
6807
6808                                         type->type = MONO_TYPE_VALUETYPE;
6809                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6810                         } else
6811                                 type->data.klass = mono_class_from_mono_type (type);
6812
6813                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6814
6815                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6816                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6817                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6818                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6819                                 else
6820                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6821                         }
6822                         
6823                 }
6824
6825                 if (mspecs [i + 1])
6826                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6827                 
6828                 mono_array_setref (res, i, param);
6829         }
6830         g_free (names);
6831         g_free (blobs);
6832         g_free (types);
6833         g_free (type);
6834
6835         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6836                 if (mspecs [i])
6837                         mono_metadata_free_marshal_spec (mspecs [i]);
6838         g_free (mspecs);
6839         
6840         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6841 }
6842
6843 MonoArray*
6844 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6845 {
6846         return mono_param_get_objects_internal (domain, method, NULL);
6847 }
6848
6849 /*
6850  * mono_method_body_get_object:
6851  * @domain: an app domain
6852  * @method: a method
6853  *
6854  * Return an System.Reflection.MethodBody object representing the method @method.
6855  */
6856 MonoReflectionMethodBody*
6857 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6858 {
6859         static MonoClass *System_Reflection_MethodBody = NULL;
6860         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6861         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6862         MonoReflectionMethodBody *ret;
6863         MonoMethodHeader *header;
6864         MonoImage *image;
6865         guint32 method_rva, local_var_sig_token;
6866     char *ptr;
6867         unsigned char format, flags;
6868         int i;
6869
6870         /* for compatibility with .net */
6871     if (method->dynamic)
6872         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6873
6874         if (!System_Reflection_MethodBody)
6875                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6876         if (!System_Reflection_LocalVariableInfo)
6877                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6878         if (!System_Reflection_ExceptionHandlingClause)
6879                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6880
6881         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6882
6883         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6884                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6885             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6886             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6887                 return NULL;
6888
6889         image = method->klass->image;
6890         header = mono_method_get_header (method);
6891
6892         if (!image->dynamic) {
6893                 /* Obtain local vars signature token */
6894                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6895                 ptr = mono_image_rva_map (image, method_rva);
6896                 flags = *(const unsigned char *) ptr;
6897                 format = flags & METHOD_HEADER_FORMAT_MASK;
6898                 switch (format){
6899                 case METHOD_HEADER_TINY_FORMAT:
6900                         local_var_sig_token = 0;
6901                         break;
6902                 case METHOD_HEADER_FAT_FORMAT:
6903                         ptr += 2;
6904                         ptr += 2;
6905                         ptr += 4;
6906                         local_var_sig_token = read32 (ptr);
6907                         break;
6908                 default:
6909                         g_assert_not_reached ();
6910                 }
6911         } else
6912                 local_var_sig_token = 0; //FIXME
6913
6914         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6915
6916         ret->init_locals = header->init_locals;
6917         ret->max_stack = header->max_stack;
6918         ret->local_var_sig_token = local_var_sig_token;
6919         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6920         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6921
6922         /* Locals */
6923         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6924         for (i = 0; i < header->num_locals; ++i) {
6925                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6926                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6927                 info->is_pinned = header->locals [i]->pinned;
6928                 info->local_index = i;
6929                 mono_array_setref (ret->locals, i, info);
6930         }
6931
6932         /* Exceptions */
6933         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6934         for (i = 0; i < header->num_clauses; ++i) {
6935                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6936                 MonoExceptionClause *clause = &header->clauses [i];
6937
6938                 info->flags = clause->flags;
6939                 info->try_offset = clause->try_offset;
6940                 info->try_length = clause->try_len;
6941                 info->handler_offset = clause->handler_offset;
6942                 info->handler_length = clause->handler_len;
6943                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6944                         info->filter_offset = clause->data.filter_offset;
6945                 else if (clause->data.catch_class)
6946                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6947
6948                 mono_array_setref (ret->clauses, i, info);
6949         }
6950
6951         mono_metadata_free_mh (header);
6952         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6953         return ret;
6954 }
6955
6956 /**
6957  * mono_get_dbnull_object:
6958  * @domain: Domain where the object lives
6959  *
6960  * Returns the System.DBNull.Value singleton object
6961  *
6962  * Used as the value for ParameterInfo.DefaultValue 
6963  */
6964 MonoObject *
6965 mono_get_dbnull_object (MonoDomain *domain)
6966 {
6967         MonoObject *obj;
6968         static MonoClassField *dbnull_value_field = NULL;
6969         
6970         if (!dbnull_value_field) {
6971                 MonoClass *dbnull_klass;
6972                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6973                 mono_class_init (dbnull_klass);
6974                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6975                 g_assert (dbnull_value_field);
6976         }
6977         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6978         g_assert (obj);
6979         return obj;
6980 }
6981
6982 static void
6983 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6984 {
6985         guint32 param_index, i, lastp, crow = 0;
6986         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6987         gint32 idx;
6988
6989         MonoClass *klass = method->klass;
6990         MonoImage *image = klass->image;
6991         MonoMethodSignature *methodsig = mono_method_signature (method);
6992
6993         MonoTableInfo *constt;
6994         MonoTableInfo *methodt;
6995         MonoTableInfo *paramt;
6996
6997         if (!methodsig->param_count)
6998                 return;
6999
7000         mono_class_init (klass);
7001
7002         if (klass->image->dynamic) {
7003                 MonoReflectionMethodAux *aux;
7004                 if (method->is_inflated)
7005                         method = ((MonoMethodInflated*)method)->declaring;
7006                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7007                 if (aux && aux->param_defaults) {
7008                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7009                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7010                 }
7011                 return;
7012         }
7013
7014         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7015         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7016         constt = &image->tables [MONO_TABLE_CONSTANT];
7017
7018         idx = mono_method_get_index (method) - 1;
7019         g_assert (idx != -1);
7020
7021         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7022         if (idx + 1 < methodt->rows)
7023                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7024         else
7025                 lastp = paramt->rows + 1;
7026
7027         for (i = param_index; i < lastp; ++i) {
7028                 guint32 paramseq;
7029
7030                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7031                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7032
7033                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7034                         continue;
7035
7036                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7037                 if (!crow) {
7038                         continue;
7039                 }
7040         
7041                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7042                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7043                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7044         }
7045
7046         return;
7047 }
7048
7049 MonoObject *
7050 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7051 {
7052         void *retval;
7053         MonoClass *klass;
7054         MonoObject *object;
7055         MonoType *basetype = type;
7056
7057         if (!blob)
7058                 return NULL;
7059         
7060         klass = mono_class_from_mono_type (type);
7061         if (klass->valuetype) {
7062                 object = mono_object_new (domain, klass);
7063                 retval = ((gchar *) object + sizeof (MonoObject));
7064                 if (klass->enumtype)
7065                         basetype = mono_class_enum_basetype (klass);
7066         } else {
7067                 retval = &object;
7068         }
7069                         
7070         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7071                 return object;
7072         else
7073                 return NULL;
7074 }
7075
7076 static int
7077 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7078         int found_sep;
7079         char *s;
7080         gboolean quoted = FALSE;
7081
7082         memset (assembly, 0, sizeof (MonoAssemblyName));
7083         assembly->culture = "";
7084         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7085
7086         if (*p == '"') {
7087                 quoted = TRUE;
7088                 p++;
7089         }
7090         assembly->name = p;
7091         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7092                 p++;
7093         if (quoted) {
7094                 if (*p != '"')
7095                         return 1;
7096                 *p = 0;
7097                 p++;
7098         }
7099         if (*p != ',')
7100                 return 1;
7101         *p = 0;
7102         /* Remove trailing whitespace */
7103         s = p - 1;
7104         while (*s && g_ascii_isspace (*s))
7105                 *s-- = 0;
7106         p ++;
7107         while (g_ascii_isspace (*p))
7108                 p++;
7109         while (*p) {
7110                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7111                         p += 8;
7112                         assembly->major = strtoul (p, &s, 10);
7113                         if (s == p || *s != '.')
7114                                 return 1;
7115                         p = ++s;
7116                         assembly->minor = strtoul (p, &s, 10);
7117                         if (s == p || *s != '.')
7118                                 return 1;
7119                         p = ++s;
7120                         assembly->build = strtoul (p, &s, 10);
7121                         if (s == p || *s != '.')
7122                                 return 1;
7123                         p = ++s;
7124                         assembly->revision = strtoul (p, &s, 10);
7125                         if (s == p)
7126                                 return 1;
7127                         p = s;
7128                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7129                         p += 8;
7130                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7131                                 assembly->culture = "";
7132                                 p += 7;
7133                         } else {
7134                                 assembly->culture = p;
7135                                 while (*p && *p != ',') {
7136                                         p++;
7137                                 }
7138                         }
7139                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7140                         p += 15;
7141                         if (strncmp (p, "null", 4) == 0) {
7142                                 p += 4;
7143                         } else {
7144                                 int len;
7145                                 gchar *start = p;
7146                                 while (*p && *p != ',') {
7147                                         p++;
7148                                 }
7149                                 len = (p - start + 1);
7150                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7151                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7152                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7153                         }
7154                 } else {
7155                         while (*p && *p != ',')
7156                                 p++;
7157                 }
7158                 found_sep = 0;
7159                 while (g_ascii_isspace (*p) || *p == ',') {
7160                         *p++ = 0;
7161                         found_sep = 1;
7162                         continue;
7163                 }
7164                 /* failed */
7165                 if (!found_sep)
7166                         return 1;
7167         }
7168
7169         return 0;
7170 }
7171
7172 /*
7173  * mono_reflection_parse_type:
7174  * @name: type name
7175  *
7176  * Parse a type name as accepted by the GetType () method and output the info
7177  * extracted in the info structure.
7178  * the name param will be mangled, so, make a copy before passing it to this function.
7179  * The fields in info will be valid until the memory pointed to by name is valid.
7180  *
7181  * See also mono_type_get_name () below.
7182  *
7183  * Returns: 0 on parse error.
7184  */
7185 static int
7186 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7187                              MonoTypeNameParse *info)
7188 {
7189         char *start, *p, *w, *temp, *last_point, *startn;
7190         int in_modifiers = 0;
7191         int isbyref = 0, rank, arity = 0, i;
7192
7193         start = p = w = name;
7194
7195         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7196         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7197         info->name = info->name_space = NULL;
7198         info->nested = NULL;
7199         info->modifiers = NULL;
7200         info->type_arguments = NULL;
7201
7202         /* last_point separates the namespace from the name */
7203         last_point = NULL;
7204         /* Skips spaces */
7205         while (*p == ' ') p++, start++, w++, name++;
7206
7207         while (*p) {
7208                 switch (*p) {
7209                 case '+':
7210                         *p = 0; /* NULL terminate the name */
7211                         startn = p + 1;
7212                         info->nested = g_list_append (info->nested, startn);
7213                         /* we have parsed the nesting namespace + name */
7214                         if (info->name)
7215                                 break;
7216                         if (last_point) {
7217                                 info->name_space = start;
7218                                 *last_point = 0;
7219                                 info->name = last_point + 1;
7220                         } else {
7221                                 info->name_space = (char *)"";
7222                                 info->name = start;
7223                         }
7224                         break;
7225                 case '.':
7226                         last_point = p;
7227                         break;
7228                 case '\\':
7229                         ++p;
7230                         break;
7231                 case '&':
7232                 case '*':
7233                 case '[':
7234                 case ',':
7235                 case ']':
7236                         in_modifiers = 1;
7237                         break;
7238                 case '`':
7239                         ++p;
7240                         i = strtol (p, &temp, 10);
7241                         arity += i;
7242                         if (p == temp)
7243                                 return 0;
7244                         p = temp-1;
7245                         break;
7246                 default:
7247                         break;
7248                 }
7249                 if (in_modifiers)
7250                         break;
7251                 // *w++ = *p++;
7252                 p++;
7253         }
7254         
7255         if (!info->name) {
7256                 if (last_point) {
7257                         info->name_space = start;
7258                         *last_point = 0;
7259                         info->name = last_point + 1;
7260                 } else {
7261                         info->name_space = (char *)"";
7262                         info->name = start;
7263                 }
7264         }
7265         while (*p) {
7266                 switch (*p) {
7267                 case '&':
7268                         if (isbyref) /* only one level allowed by the spec */
7269                                 return 0;
7270                         isbyref = 1;
7271                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7272                         *p++ = 0;
7273                         break;
7274                 case '*':
7275                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7276                         *p++ = 0;
7277                         break;
7278                 case '[':
7279                         if (arity != 0) {
7280                                 *p++ = 0;
7281                                 info->type_arguments = g_ptr_array_new ();
7282                                 for (i = 0; i < arity; i++) {
7283                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7284                                         gboolean fqname = FALSE;
7285
7286                                         g_ptr_array_add (info->type_arguments, subinfo);
7287
7288                                         if (*p == '[') {
7289                                                 p++;
7290                                                 fqname = TRUE;
7291                                         }
7292
7293                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7294                                                 return 0;
7295
7296                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7297                                         if (fqname && (*p != ']')) {
7298                                                 char *aname;
7299
7300                                                 if (*p != ',')
7301                                                         return 0;
7302                                                 *p++ = 0;
7303
7304                                                 aname = p;
7305                                                 while (*p && (*p != ']'))
7306                                                         p++;
7307
7308                                                 if (*p != ']')
7309                                                         return 0;
7310
7311                                                 *p++ = 0;
7312                                                 while (*aname) {
7313                                                         if (g_ascii_isspace (*aname)) {
7314                                                                 ++aname;
7315                                                                 continue;
7316                                                         }
7317                                                         break;
7318                                                 }
7319                                                 if (!*aname ||
7320                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7321                                                         return 0;
7322                                         } else if (fqname && (*p == ']')) {
7323                                                 *p++ = 0;
7324                                         }
7325
7326                                         if (i + 1 < arity) {
7327                                                 if (*p != ',')
7328                                                         return 0;
7329                                         } else {
7330                                                 if (*p != ']')
7331                                                         return 0;
7332                                         }
7333                                         *p++ = 0;
7334                                 }
7335
7336                                 arity = 0;
7337                                 break;
7338                         }
7339                         rank = 1;
7340                         *p++ = 0;
7341                         while (*p) {
7342                                 if (*p == ']')
7343                                         break;
7344                                 if (*p == ',')
7345                                         rank++;
7346                                 else if (*p == '*') /* '*' means unknown lower bound */
7347                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7348                                 else
7349                                         return 0;
7350                                 ++p;
7351                         }
7352                         if (*p++ != ']')
7353                                 return 0;
7354                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7355                         break;
7356                 case ']':
7357                         if (is_recursed)
7358                                 goto end;
7359                         return 0;
7360                 case ',':
7361                         if (is_recursed)
7362                                 goto end;
7363                         *p++ = 0;
7364                         while (*p) {
7365                                 if (g_ascii_isspace (*p)) {
7366                                         ++p;
7367                                         continue;
7368                                 }
7369                                 break;
7370                         }
7371                         if (!*p)
7372                                 return 0; /* missing assembly name */
7373                         if (!assembly_name_to_aname (&info->assembly, p))
7374                                 return 0;
7375                         break;
7376                 default:
7377                         return 0;
7378                 }
7379                 if (info->assembly.name)
7380                         break;
7381         }
7382         // *w = 0; /* terminate class name */
7383  end:
7384         if (!info->name || !*info->name)
7385                 return 0;
7386         if (endptr)
7387                 *endptr = p;
7388         /* add other consistency checks */
7389         return 1;
7390 }
7391
7392 int
7393 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7394 {
7395         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7396 }
7397
7398 static MonoType*
7399 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7400 {
7401         gboolean type_resolve = FALSE;
7402         MonoType *type;
7403         MonoImage *rootimage = image;
7404
7405         if (info->assembly.name) {
7406                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7407                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7408                         /* 
7409                          * This could happen in the AOT compiler case when the search hook is not
7410                          * installed.
7411                          */
7412                         assembly = image->assembly;
7413                 if (!assembly) {
7414                         /* then we must load the assembly ourselve - see #60439 */
7415                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7416                         if (!assembly)
7417                                 return NULL;
7418                 }
7419                 image = assembly->image;
7420         } else if (!image) {
7421                 image = mono_defaults.corlib;
7422         }
7423
7424         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7425         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7426                 image = mono_defaults.corlib;
7427                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7428         }
7429
7430         return type;
7431 }
7432
7433 static MonoType*
7434 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7435 {
7436         MonoClass *klass;
7437         GList *mod;
7438         int modval;
7439         gboolean bounded = FALSE;
7440         
7441         if (!image)
7442                 image = mono_defaults.corlib;
7443
7444         if (ignorecase)
7445                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7446         else
7447                 klass = mono_class_from_name (image, info->name_space, info->name);
7448         if (!klass)
7449                 return NULL;
7450         for (mod = info->nested; mod; mod = mod->next) {
7451                 gpointer iter = NULL;
7452                 MonoClass *parent;
7453
7454                 parent = klass;
7455                 mono_class_init (parent);
7456
7457                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7458                         if (ignorecase) {
7459                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7460                                         break;
7461                         } else {
7462                                 if (strcmp (klass->name, mod->data) == 0)
7463                                         break;
7464                         }
7465                 }
7466                 if (!klass)
7467                         break;
7468         }
7469         if (!klass)
7470                 return NULL;
7471
7472         if (info->type_arguments) {
7473                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7474                 MonoReflectionType *the_type;
7475                 MonoType *instance;
7476                 int i;
7477
7478                 for (i = 0; i < info->type_arguments->len; i++) {
7479                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7480
7481                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7482                         if (!type_args [i]) {
7483                                 g_free (type_args);
7484                                 return NULL;
7485                         }
7486                 }
7487
7488                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7489
7490                 instance = mono_reflection_bind_generic_parameters (
7491                         the_type, info->type_arguments->len, type_args);
7492
7493                 g_free (type_args);
7494                 if (!instance)
7495                         return NULL;
7496
7497                 klass = mono_class_from_mono_type (instance);
7498         }
7499
7500         for (mod = info->modifiers; mod; mod = mod->next) {
7501                 modval = GPOINTER_TO_UINT (mod->data);
7502                 if (!modval) { /* byref: must be last modifier */
7503                         return &klass->this_arg;
7504                 } else if (modval == -1) {
7505                         klass = mono_ptr_class_get (&klass->byval_arg);
7506                 } else if (modval == -2) {
7507                         bounded = TRUE;
7508                 } else { /* array rank */
7509                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7510                 }
7511         }
7512
7513         return &klass->byval_arg;
7514 }
7515
7516 /*
7517  * mono_reflection_get_type:
7518  * @image: a metadata context
7519  * @info: type description structure
7520  * @ignorecase: flag for case-insensitive string compares
7521  * @type_resolve: whenever type resolve was already tried
7522  *
7523  * Build a MonoType from the type description in @info.
7524  * 
7525  */
7526
7527 MonoType*
7528 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7529         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7530 }
7531
7532 static MonoType*
7533 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7534 {
7535         MonoReflectionAssemblyBuilder *abuilder;
7536         MonoType *type;
7537         int i;
7538
7539         g_assert (assembly->dynamic);
7540         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7541
7542         /* Enumerate all modules */
7543
7544         type = NULL;
7545         if (abuilder->modules) {
7546                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7547                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7548                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7549                         if (type)
7550                                 break;
7551                 }
7552         }
7553
7554         if (!type && abuilder->loaded_modules) {
7555                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7556                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7557                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7558                         if (type)
7559                                 break;
7560                 }
7561         }
7562
7563         return type;
7564 }
7565         
7566 MonoType*
7567 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7568 {
7569         MonoType *type;
7570         MonoReflectionAssembly *assembly;
7571         GString *fullName;
7572         GList *mod;
7573
7574         if (image && image->dynamic)
7575                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7576         else
7577                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7578         if (type)
7579                 return type;
7580         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7581                 return NULL;
7582
7583         if (type_resolve) {
7584                 if (*type_resolve) 
7585                         return NULL;
7586                 else
7587                         *type_resolve = TRUE;
7588         }
7589         
7590         /* Reconstruct the type name */
7591         fullName = g_string_new ("");
7592         if (info->name_space && (info->name_space [0] != '\0'))
7593                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7594         else
7595                 g_string_printf (fullName, "%s", info->name);
7596         for (mod = info->nested; mod; mod = mod->next)
7597                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7598
7599         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7600         if (assembly) {
7601                 if (assembly->assembly->dynamic)
7602                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7603                 else
7604                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7605                                                                                                           info, ignorecase);
7606         }
7607         g_string_free (fullName, TRUE);
7608         return type;
7609 }
7610
7611 void
7612 mono_reflection_free_type_info (MonoTypeNameParse *info)
7613 {
7614         g_list_free (info->modifiers);
7615         g_list_free (info->nested);
7616
7617         if (info->type_arguments) {
7618                 int i;
7619
7620                 for (i = 0; i < info->type_arguments->len; i++) {
7621                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7622
7623                         mono_reflection_free_type_info (subinfo);
7624                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7625                         g_free (subinfo);
7626                 }
7627
7628                 g_ptr_array_free (info->type_arguments, TRUE);
7629         }
7630 }
7631
7632 /*
7633  * mono_reflection_type_from_name:
7634  * @name: type name.
7635  * @image: a metadata context (can be NULL).
7636  *
7637  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7638  * it defaults to get the type from @image or, if @image is NULL or loading
7639  * from it fails, uses corlib.
7640  * 
7641  */
7642 MonoType*
7643 mono_reflection_type_from_name (char *name, MonoImage *image)
7644 {
7645         MonoType *type = NULL;
7646         MonoTypeNameParse info;
7647         char *tmp;
7648
7649         /* Make a copy since parse_type modifies its argument */
7650         tmp = g_strdup (name);
7651         
7652         /*g_print ("requested type %s\n", str);*/
7653         if (mono_reflection_parse_type (tmp, &info)) {
7654                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7655         }
7656
7657         g_free (tmp);
7658         mono_reflection_free_type_info (&info);
7659         return type;
7660 }
7661
7662 /*
7663  * mono_reflection_get_token:
7664  *
7665  *   Return the metadata token of OBJ which should be an object
7666  * representing a metadata element.
7667  */
7668 guint32
7669 mono_reflection_get_token (MonoObject *obj)
7670 {
7671         MonoClass *klass;
7672         guint32 token = 0;
7673
7674         klass = obj->vtable->klass;
7675
7676         if (strcmp (klass->name, "MethodBuilder") == 0) {
7677                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7678
7679                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7680         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7681                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7682
7683                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7684         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7685                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7686
7687                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7688         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7689                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7690                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7691         } else if (strcmp (klass->name, "MonoType") == 0) {
7692                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7693                 MonoClass *mc = mono_class_from_mono_type (type);
7694                 if (!mono_class_init (mc))
7695                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7696
7697                 token = mc->type_token;
7698         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7699                    strcmp (klass->name, "MonoMethod") == 0 ||
7700                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7701                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7702                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7703                 if (m->method->is_inflated) {
7704                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7705                         return inflated->declaring->token;
7706                 } else {
7707                         token = m->method->token;
7708                 }
7709         } else if (strcmp (klass->name, "MonoField") == 0) {
7710                 MonoReflectionField *f = (MonoReflectionField*)obj;
7711
7712                 if (is_field_on_inst (f->field)) {
7713                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7714                         int field_index = f->field - dgclass->fields;
7715                         MonoObject *obj;
7716
7717                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7718                         obj = dgclass->field_objects [field_index];
7719                         return mono_reflection_get_token (obj);
7720                 }
7721                 token = mono_class_get_field_token (f->field);
7722         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7723                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7724
7725                 token = mono_class_get_property_token (p->property);
7726         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7727                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7728
7729                 token = mono_class_get_event_token (p->event);
7730         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7731                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7732                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7733                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7734
7735                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7736         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7737                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7738
7739                 token = m->token;
7740         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7741                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7742         } else {
7743                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7744                 MonoException *ex = mono_get_exception_not_implemented (msg);
7745                 g_free (msg);
7746                 mono_raise_exception (ex);
7747         }
7748
7749         return token;
7750 }
7751
7752 static void*
7753 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7754 {
7755         int slen, type = t->type;
7756         MonoClass *tklass = t->data.klass;
7757
7758 handle_enum:
7759         switch (type) {
7760         case MONO_TYPE_U1:
7761         case MONO_TYPE_I1:
7762         case MONO_TYPE_BOOLEAN: {
7763                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7764                 *bval = *p;
7765                 *end = p + 1;
7766                 return bval;
7767         }
7768         case MONO_TYPE_CHAR:
7769         case MONO_TYPE_U2:
7770         case MONO_TYPE_I2: {
7771                 guint16 *val = g_malloc (sizeof (guint16));
7772                 *val = read16 (p);
7773                 *end = p + 2;
7774                 return val;
7775         }
7776 #if SIZEOF_VOID_P == 4
7777         case MONO_TYPE_U:
7778         case MONO_TYPE_I:
7779 #endif
7780         case MONO_TYPE_R4:
7781         case MONO_TYPE_U4:
7782         case MONO_TYPE_I4: {
7783                 guint32 *val = g_malloc (sizeof (guint32));
7784                 *val = read32 (p);
7785                 *end = p + 4;
7786                 return val;
7787         }
7788 #if SIZEOF_VOID_P == 8
7789         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7790         case MONO_TYPE_I:
7791 #endif
7792         case MONO_TYPE_U8:
7793         case MONO_TYPE_I8: {
7794                 guint64 *val = g_malloc (sizeof (guint64));
7795                 *val = read64 (p);
7796                 *end = p + 8;
7797                 return val;
7798         }
7799         case MONO_TYPE_R8: {
7800                 double *val = g_malloc (sizeof (double));
7801                 readr8 (p, val);
7802                 *end = p + 8;
7803                 return val;
7804         }
7805         case MONO_TYPE_VALUETYPE:
7806                 if (t->data.klass->enumtype) {
7807                         type = mono_class_enum_basetype (t->data.klass)->type;
7808                         goto handle_enum;
7809                 } else {
7810                         MonoClass *k =  t->data.klass;
7811                         
7812                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7813                                 guint64 *val = g_malloc (sizeof (guint64));
7814                                 *val = read64 (p);
7815                                 *end = p + 8;
7816                                 return val;
7817                         }
7818                 }
7819                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7820                 break;
7821                 
7822         case MONO_TYPE_STRING:
7823                 if (*p == (char)0xFF) {
7824                         *end = p + 1;
7825                         return NULL;
7826                 }
7827                 slen = mono_metadata_decode_value (p, &p);
7828                 *end = p + slen;
7829                 return mono_string_new_len (mono_domain_get (), p, slen);
7830         case MONO_TYPE_CLASS: {
7831                 char *n;
7832                 MonoType *t;
7833                 if (*p == (char)0xFF) {
7834                         *end = p + 1;
7835                         return NULL;
7836                 }
7837 handle_type:
7838                 slen = mono_metadata_decode_value (p, &p);
7839                 n = g_memdup (p, slen + 1);
7840                 n [slen] = 0;
7841                 t = mono_reflection_type_from_name (n, image);
7842                 if (!t)
7843                         g_warning ("Cannot load type '%s'", n);
7844                 g_free (n);
7845                 *end = p + slen;
7846                 if (t)
7847                         return mono_type_get_object (mono_domain_get (), t);
7848                 else
7849                         return NULL;
7850         }
7851         case MONO_TYPE_OBJECT: {
7852                 char subt = *p++;
7853                 MonoObject *obj;
7854                 MonoClass *subc = NULL;
7855                 void *val;
7856
7857                 if (subt == 0x50) {
7858                         goto handle_type;
7859                 } else if (subt == 0x0E) {
7860                         type = MONO_TYPE_STRING;
7861                         goto handle_enum;
7862                 } else if (subt == 0x1D) {
7863                         MonoType simple_type = {{0}};
7864                         int etype = *p;
7865                         p ++;
7866
7867                         type = MONO_TYPE_SZARRAY;
7868                         if (etype == 0x50) {
7869                                 tklass = mono_defaults.systemtype_class;
7870                         } else {
7871                                 if (etype == 0x51)
7872                                         /* See Partition II, Appendix B3 */
7873                                         etype = MONO_TYPE_OBJECT;
7874                                 simple_type.type = etype;
7875                                 tklass = mono_class_from_mono_type (&simple_type);
7876                         }
7877                         goto handle_enum;
7878                 } else if (subt == 0x55) {
7879                         char *n;
7880                         MonoType *t;
7881                         slen = mono_metadata_decode_value (p, &p);
7882                         n = g_memdup (p, slen + 1);
7883                         n [slen] = 0;
7884                         t = mono_reflection_type_from_name (n, image);
7885                         if (!t)
7886                                 g_error ("Cannot load type '%s'", n);
7887                         g_free (n);
7888                         p += slen;
7889                         subc = mono_class_from_mono_type (t);
7890                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7891                         MonoType simple_type = {{0}};
7892                         simple_type.type = subt;
7893                         subc = mono_class_from_mono_type (&simple_type);
7894                 } else {
7895                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7896                 }
7897                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7898                 obj = mono_object_new (mono_domain_get (), subc);
7899                 g_assert (!subc->has_references);
7900                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7901                 g_free (val);
7902                 return obj;
7903         }
7904         case MONO_TYPE_SZARRAY: {
7905                 MonoArray *arr;
7906                 guint32 i, alen, basetype;
7907                 alen = read32 (p);
7908                 p += 4;
7909                 if (alen == 0xffffffff) {
7910                         *end = p;
7911                         return NULL;
7912                 }
7913                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7914                 basetype = tklass->byval_arg.type;
7915                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7916                         basetype = mono_class_enum_basetype (tklass)->type;
7917                 switch (basetype)
7918                 {
7919                         case MONO_TYPE_U1:
7920                         case MONO_TYPE_I1:
7921                         case MONO_TYPE_BOOLEAN:
7922                                 for (i = 0; i < alen; i++) {
7923                                         MonoBoolean val = *p++;
7924                                         mono_array_set (arr, MonoBoolean, i, val);
7925                                 }
7926                                 break;
7927                         case MONO_TYPE_CHAR:
7928                         case MONO_TYPE_U2:
7929                         case MONO_TYPE_I2:
7930                                 for (i = 0; i < alen; i++) {
7931                                         guint16 val = read16 (p);
7932                                         mono_array_set (arr, guint16, i, val);
7933                                         p += 2;
7934                                 }
7935                                 break;
7936                         case MONO_TYPE_R4:
7937                         case MONO_TYPE_U4:
7938                         case MONO_TYPE_I4:
7939                                 for (i = 0; i < alen; i++) {
7940                                         guint32 val = read32 (p);
7941                                         mono_array_set (arr, guint32, i, val);
7942                                         p += 4;
7943                                 }
7944                                 break;
7945                         case MONO_TYPE_R8:
7946                                 for (i = 0; i < alen; i++) {
7947                                         double val;
7948                                         readr8 (p, &val);
7949                                         mono_array_set (arr, double, i, val);
7950                                         p += 8;
7951                                 }
7952                                 break;
7953                         case MONO_TYPE_U8:
7954                         case MONO_TYPE_I8:
7955                                 for (i = 0; i < alen; i++) {
7956                                         guint64 val = read64 (p);
7957                                         mono_array_set (arr, guint64, i, val);
7958                                         p += 8;
7959                                 }
7960                                 break;
7961                         case MONO_TYPE_CLASS:
7962                         case MONO_TYPE_OBJECT:
7963                         case MONO_TYPE_STRING:
7964                                 for (i = 0; i < alen; i++) {
7965                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7966                                         mono_array_setref (arr, i, item);
7967                                 }
7968                                 break;
7969                         default:
7970                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7971                 }
7972                 *end=p;
7973                 return arr;
7974         }
7975         default:
7976                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7977         }
7978         return NULL;
7979 }
7980
7981 static MonoObject*
7982 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7983 {
7984         static MonoClass *klass;
7985         static MonoMethod *ctor;
7986         MonoObject *retval;
7987         void *params [2], *unboxed;
7988
7989         if (!klass)
7990                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7991         if (!ctor)
7992                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7993         
7994         params [0] = mono_type_get_object (mono_domain_get (), t);
7995         params [1] = val;
7996         retval = mono_object_new (mono_domain_get (), klass);
7997         unboxed = mono_object_unbox (retval);
7998         mono_runtime_invoke (ctor, unboxed, params, NULL);
7999
8000         return retval;
8001 }
8002
8003 static MonoObject*
8004 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8005 {
8006         static MonoClass *klass;
8007         static MonoMethod *ctor;
8008         MonoObject *retval;
8009         void *unboxed, *params [2];
8010
8011         if (!klass)
8012                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8013         if (!ctor)
8014                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8015
8016         params [0] = minfo;
8017         params [1] = typedarg;
8018         retval = mono_object_new (mono_domain_get (), klass);
8019         unboxed = mono_object_unbox (retval);
8020         mono_runtime_invoke (ctor, unboxed, params, NULL);
8021
8022         return retval;
8023 }
8024
8025 static gboolean
8026 type_is_reference (MonoType *type)
8027 {
8028         switch (type->type) {
8029         case MONO_TYPE_BOOLEAN:
8030         case MONO_TYPE_CHAR:
8031         case MONO_TYPE_U:
8032         case MONO_TYPE_I:
8033         case MONO_TYPE_U1:
8034         case MONO_TYPE_I1:
8035         case MONO_TYPE_U2:
8036         case MONO_TYPE_I2:
8037         case MONO_TYPE_U4:
8038         case MONO_TYPE_I4:
8039         case MONO_TYPE_U8:
8040         case MONO_TYPE_I8:
8041         case MONO_TYPE_R8:
8042         case MONO_TYPE_R4:
8043         case MONO_TYPE_VALUETYPE:
8044                 return FALSE;
8045         default:
8046                 return TRUE;
8047         }
8048 }
8049
8050 static void
8051 free_param_data (MonoMethodSignature *sig, void **params) {
8052         int i;
8053         for (i = 0; i < sig->param_count; ++i) {
8054                 if (!type_is_reference (sig->params [i]))
8055                         g_free (params [i]);
8056         }
8057 }
8058
8059 /*
8060  * Find the field index in the metadata FieldDef table.
8061  */
8062 static guint32
8063 find_field_index (MonoClass *klass, MonoClassField *field) {
8064         int i;
8065
8066         for (i = 0; i < klass->field.count; ++i) {
8067                 if (field == &klass->fields [i])
8068                         return klass->field.first + 1 + i;
8069         }
8070         return 0;
8071 }
8072
8073 /*
8074  * Find the property index in the metadata Property table.
8075  */
8076 static guint32
8077 find_property_index (MonoClass *klass, MonoProperty *property) {
8078         int i;
8079
8080         for (i = 0; i < klass->ext->property.count; ++i) {
8081                 if (property == &klass->ext->properties [i])
8082                         return klass->ext->property.first + 1 + i;
8083         }
8084         return 0;
8085 }
8086
8087 /*
8088  * Find the event index in the metadata Event table.
8089  */
8090 static guint32
8091 find_event_index (MonoClass *klass, MonoEvent *event) {
8092         int i;
8093
8094         for (i = 0; i < klass->ext->event.count; ++i) {
8095                 if (event == &klass->ext->events [i])
8096                         return klass->ext->event.first + 1 + i;
8097         }
8098         return 0;
8099 }
8100
8101 static MonoObject*
8102 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8103 {
8104         const char *p = (const char*)data;
8105         const char *named;
8106         guint32 i, j, num_named;
8107         MonoObject *attr;
8108         void *params_buf [32];
8109         void **params;
8110         MonoMethodSignature *sig;
8111
8112         mono_error_init (error);
8113
8114         mono_class_init (method->klass);
8115
8116         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8117                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8118                 return NULL;
8119         }
8120
8121         if (len == 0) {
8122                 attr = mono_object_new (mono_domain_get (), method->klass);
8123                 mono_runtime_invoke (method, attr, NULL, NULL);
8124                 return attr;
8125         }
8126
8127         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8128                 return NULL;
8129
8130         /*g_print ("got attr %s\n", method->klass->name);*/
8131
8132         sig = mono_method_signature (method);
8133         if (sig->param_count < 32)
8134                 params = params_buf;
8135         else
8136                 /* Allocate using GC so it gets GC tracking */
8137                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8138
8139         /* skip prolog */
8140         p += 2;
8141         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8142                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8143         }
8144
8145         named = p;
8146         attr = mono_object_new (mono_domain_get (), method->klass);
8147         mono_runtime_invoke (method, attr, params, NULL);
8148         free_param_data (method->signature, params);
8149         num_named = read16 (named);
8150         named += 2;
8151         for (j = 0; j < num_named; j++) {
8152                 gint name_len;
8153                 char *name, named_type, data_type;
8154                 named_type = *named++;
8155                 data_type = *named++; /* type of data */
8156                 if (data_type == MONO_TYPE_SZARRAY)
8157                         data_type = *named++;
8158                 if (data_type == MONO_TYPE_ENUM) {
8159                         gint type_len;
8160                         char *type_name;
8161                         type_len = mono_metadata_decode_blob_size (named, &named);
8162                         type_name = g_malloc (type_len + 1);
8163                         memcpy (type_name, named, type_len);
8164                         type_name [type_len] = 0;
8165                         named += type_len;
8166                         /* FIXME: lookup the type and check type consistency */
8167                         g_free (type_name);
8168                 }
8169                 name_len = mono_metadata_decode_blob_size (named, &named);
8170                 name = g_malloc (name_len + 1);
8171                 memcpy (name, named, name_len);
8172                 name [name_len] = 0;
8173                 named += name_len;
8174                 if (named_type == 0x53) {
8175                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8176                         void *val = load_cattr_value (image, field->type, named, &named);
8177                         mono_field_set_value (attr, field, val);
8178                         if (!type_is_reference (field->type))
8179                                 g_free (val);
8180                 } else if (named_type == 0x54) {
8181                         MonoProperty *prop;
8182                         void *pparams [1];
8183                         MonoType *prop_type;
8184
8185                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8186                         /* can we have more that 1 arg in a custom attr named property? */
8187                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8188                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8189                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8190                         mono_property_set_value (prop, attr, pparams, NULL);
8191                         if (!type_is_reference (prop_type))
8192                                 g_free (pparams [0]);
8193                 }
8194                 g_free (name);
8195         }
8196
8197         if (params != params_buf)
8198                 mono_gc_free_fixed (params);
8199
8200         return attr;
8201 }
8202         
8203 /*
8204  * mono_reflection_create_custom_attr_data_args:
8205  *
8206  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8207  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8208  * NAMED_ARG_INFO will contain information about the named arguments.
8209  */
8210 void
8211 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)
8212 {
8213         MonoArray *typedargs, *namedargs;
8214         MonoClass *attrklass;
8215         MonoDomain *domain;
8216         const char *p = (const char*)data;
8217         const char *named;
8218         guint32 i, j, num_named;
8219         CattrNamedArg *arginfo = NULL;
8220
8221         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8222                 return;
8223
8224         mono_class_init (method->klass);
8225
8226         *typed_args = NULL;
8227         *named_args = NULL;
8228         *named_arg_info = NULL;
8229         
8230         domain = mono_domain_get ();
8231
8232         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8233                 return;
8234
8235         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8236         
8237         /* skip prolog */
8238         p += 2;
8239         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8240                 MonoObject *obj;
8241                 void *val;
8242
8243                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8244                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8245                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8246                 mono_array_setref (typedargs, i, obj);
8247
8248                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8249                         g_free (val);
8250         }
8251
8252         named = p;
8253         num_named = read16 (named);
8254         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8255         named += 2;
8256         attrklass = method->klass;
8257
8258         arginfo = g_new0 (CattrNamedArg, num_named);
8259         *named_arg_info = arginfo;
8260
8261         for (j = 0; j < num_named; j++) {
8262                 gint name_len;
8263                 char *name, named_type, data_type;
8264                 named_type = *named++;
8265                 data_type = *named++; /* type of data */
8266                 if (data_type == MONO_TYPE_SZARRAY)
8267                         data_type = *named++;
8268                 if (data_type == MONO_TYPE_ENUM) {
8269                         gint type_len;
8270                         char *type_name;
8271                         type_len = mono_metadata_decode_blob_size (named, &named);
8272                         type_name = g_malloc (type_len + 1);
8273                         memcpy (type_name, named, type_len);
8274                         type_name [type_len] = 0;
8275                         named += type_len;
8276                         /* FIXME: lookup the type and check type consistency */
8277                         g_free (type_name);
8278                 }
8279                 name_len = mono_metadata_decode_blob_size (named, &named);
8280                 name = g_malloc (name_len + 1);
8281                 memcpy (name, named, name_len);
8282                 name [name_len] = 0;
8283                 named += name_len;
8284                 if (named_type == 0x53) {
8285                         MonoObject *obj;
8286                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8287                         void *val;
8288
8289                         arginfo [j].type = field->type;
8290                         arginfo [j].field = field;
8291
8292                         val = load_cattr_value (image, field->type, named, &named);
8293                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8294                         mono_array_setref (namedargs, j, obj);
8295                         if (!type_is_reference (field->type))
8296                                 g_free (val);
8297                 } else if (named_type == 0x54) {
8298                         MonoObject *obj;
8299                         MonoType *prop_type;
8300                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8301                         void *val;
8302
8303                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8304                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8305
8306                         arginfo [j].type = prop_type;
8307                         arginfo [j].prop = prop;
8308
8309                         val = load_cattr_value (image, prop_type, named, &named);
8310                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8311                         mono_array_setref (namedargs, j, obj);
8312                         if (!type_is_reference (prop_type))
8313                                 g_free (val);
8314                 }
8315                 g_free (name);
8316         }
8317
8318         *typed_args = typedargs;
8319         *named_args = namedargs;
8320 }
8321
8322 void
8323 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8324 {
8325         MonoDomain *domain;
8326         MonoArray *typedargs, *namedargs;
8327         MonoImage *image;
8328         MonoMethod *method;
8329         CattrNamedArg *arginfo;
8330         int i;
8331
8332         *ctor_args = NULL;
8333         *named_args = NULL;
8334
8335         if (len == 0)
8336                 return;
8337
8338         image = assembly->assembly->image;
8339         method = ref_method->method;
8340         domain = mono_object_domain (ref_method);
8341
8342         if (!mono_class_init (method->klass))
8343                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8344
8345         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8346         if (mono_loader_get_last_error ())
8347                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8348
8349         if (!typedargs || !namedargs)
8350                 return;
8351
8352         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8353                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8354                 MonoObject *typedarg;
8355
8356                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8357                 mono_array_setref (typedargs, i, typedarg);
8358         }
8359
8360         for (i = 0; i < mono_array_length (namedargs); ++i) {
8361                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8362                 MonoObject *typedarg, *namedarg, *minfo;
8363
8364                 if (arginfo [i].prop)
8365                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8366                 else
8367                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8368
8369                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8370                 namedarg = create_cattr_named_arg (minfo, typedarg);
8371
8372                 mono_array_setref (namedargs, i, namedarg);
8373         }
8374
8375         *ctor_args = typedargs;
8376         *named_args = namedargs;
8377 }
8378
8379 static MonoObject*
8380 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8381 {
8382         static MonoMethod *ctor;
8383         MonoDomain *domain;
8384         MonoObject *attr;
8385         void *params [4];
8386
8387         g_assert (image->assembly);
8388
8389         if (!ctor)
8390                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8391
8392         domain = mono_domain_get ();
8393         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8394         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8395         params [1] = mono_assembly_get_object (domain, image->assembly);
8396         params [2] = (gpointer)&cattr->data;
8397         params [3] = &cattr->data_size;
8398         mono_runtime_invoke (ctor, attr, params, NULL);
8399         return attr;
8400 }
8401
8402 static MonoArray*
8403 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8404 {
8405         MonoArray *result;
8406         MonoObject *attr;
8407         int i, n;
8408
8409         mono_error_init (error);
8410
8411         n = 0;
8412         for (i = 0; i < cinfo->num_attrs; ++i) {
8413                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8414                         n ++;
8415         }
8416
8417         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8418         n = 0;
8419         for (i = 0; i < cinfo->num_attrs; ++i) {
8420                 if (!cinfo->attrs [i].ctor)
8421                         /* The cattr type is not finished yet */
8422                         /* We should include the type name but cinfo doesn't contain it */
8423                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8424                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8425                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8426                         if (!mono_error_ok (error))
8427                                 return result;
8428                         mono_array_setref (result, n, attr);
8429                         n ++;
8430                 }
8431         }
8432         return result;
8433 }
8434
8435 MonoArray*
8436 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8437 {
8438         MonoError error;
8439
8440         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8441 }
8442
8443 static MonoArray*
8444 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8445 {
8446         MonoArray *result;
8447         MonoObject *attr;
8448         int i;
8449         
8450         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8451         for (i = 0; i < cinfo->num_attrs; ++i) {
8452                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8453                 mono_array_setref (result, i, attr);
8454         }
8455         return result;
8456 }
8457
8458 /**
8459  * mono_custom_attrs_from_index:
8460  *
8461  * Returns: NULL if no attributes are found or if a loading error occurs.
8462  */
8463 MonoCustomAttrInfo*
8464 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8465 {
8466         guint32 mtoken, i, len;
8467         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8468         MonoTableInfo *ca;
8469         MonoCustomAttrInfo *ainfo;
8470         GList *tmp, *list = NULL;
8471         const char *data;
8472
8473         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8474
8475         i = mono_metadata_custom_attrs_from_index (image, idx);
8476         if (!i)
8477                 return NULL;
8478         i --;
8479         while (i < ca->rows) {
8480                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8481                         break;
8482                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8483                 ++i;
8484         }
8485         len = g_list_length (list);
8486         if (!len)
8487                 return NULL;
8488         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8489         ainfo->num_attrs = len;
8490         ainfo->image = image;
8491         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8492                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8493                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8494                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8495                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8496                         mtoken |= MONO_TOKEN_METHOD_DEF;
8497                         break;
8498                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8499                         mtoken |= MONO_TOKEN_MEMBER_REF;
8500                         break;
8501                 default:
8502                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8503                         break;
8504                 }
8505                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8506                 if (!ainfo->attrs [i].ctor) {
8507                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8508                         g_list_free (list);
8509                         g_free (ainfo);
8510                         return NULL;
8511                 }
8512
8513                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8514                         /*FIXME raising an exception here doesn't make any sense*/
8515                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8516                         g_list_free (list);
8517                         g_free (ainfo);
8518                         return NULL;
8519                 }
8520                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8521                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8522                 ainfo->attrs [i].data = (guchar*)data;
8523         }
8524         g_list_free (list);
8525
8526         return ainfo;
8527 }
8528
8529 MonoCustomAttrInfo*
8530 mono_custom_attrs_from_method (MonoMethod *method)
8531 {
8532         guint32 idx;
8533
8534         /*
8535          * An instantiated method has the same cattrs as the generic method definition.
8536          *
8537          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8538          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8539          */
8540         if (method->is_inflated)
8541                 method = ((MonoMethodInflated *) method)->declaring;
8542         
8543         if (method->dynamic || method->klass->image->dynamic)
8544                 return lookup_custom_attr (method->klass->image, method);
8545
8546         if (!method->token)
8547                 /* Synthetic methods */
8548                 return NULL;
8549
8550         idx = mono_method_get_index (method);
8551         idx <<= MONO_CUSTOM_ATTR_BITS;
8552         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8553         return mono_custom_attrs_from_index (method->klass->image, idx);
8554 }
8555
8556 MonoCustomAttrInfo*
8557 mono_custom_attrs_from_class (MonoClass *klass)
8558 {
8559         guint32 idx;
8560
8561         if (klass->generic_class)
8562                 klass = klass->generic_class->container_class;
8563
8564         if (klass->image->dynamic)
8565                 return lookup_custom_attr (klass->image, klass);
8566
8567         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8568                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8569                 idx <<= MONO_CUSTOM_ATTR_BITS;
8570                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8571         } else {
8572                 idx = mono_metadata_token_index (klass->type_token);
8573                 idx <<= MONO_CUSTOM_ATTR_BITS;
8574                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8575         }
8576         return mono_custom_attrs_from_index (klass->image, idx);
8577 }
8578
8579 MonoCustomAttrInfo*
8580 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8581 {
8582         guint32 idx;
8583         
8584         if (assembly->image->dynamic)
8585                 return lookup_custom_attr (assembly->image, assembly);
8586         idx = 1; /* there is only one assembly */
8587         idx <<= MONO_CUSTOM_ATTR_BITS;
8588         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8589         return mono_custom_attrs_from_index (assembly->image, idx);
8590 }
8591
8592 static MonoCustomAttrInfo*
8593 mono_custom_attrs_from_module (MonoImage *image)
8594 {
8595         guint32 idx;
8596         
8597         if (image->dynamic)
8598                 return lookup_custom_attr (image, image);
8599         idx = 1; /* there is only one module */
8600         idx <<= MONO_CUSTOM_ATTR_BITS;
8601         idx |= MONO_CUSTOM_ATTR_MODULE;
8602         return mono_custom_attrs_from_index (image, idx);
8603 }
8604
8605 MonoCustomAttrInfo*
8606 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8607 {
8608         guint32 idx;
8609         
8610         if (klass->image->dynamic) {
8611                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8612                 return lookup_custom_attr (klass->image, property);
8613         }
8614         idx = find_property_index (klass, property);
8615         idx <<= MONO_CUSTOM_ATTR_BITS;
8616         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8617         return mono_custom_attrs_from_index (klass->image, idx);
8618 }
8619
8620 MonoCustomAttrInfo*
8621 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8622 {
8623         guint32 idx;
8624         
8625         if (klass->image->dynamic) {
8626                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8627                 return lookup_custom_attr (klass->image, event);
8628         }
8629         idx = find_event_index (klass, event);
8630         idx <<= MONO_CUSTOM_ATTR_BITS;
8631         idx |= MONO_CUSTOM_ATTR_EVENT;
8632         return mono_custom_attrs_from_index (klass->image, idx);
8633 }
8634
8635 MonoCustomAttrInfo*
8636 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8637 {
8638         guint32 idx;
8639         if (klass->image->dynamic) {
8640                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8641                 return lookup_custom_attr (klass->image, field);
8642         }
8643         idx = find_field_index (klass, field);
8644         idx <<= MONO_CUSTOM_ATTR_BITS;
8645         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8646         return mono_custom_attrs_from_index (klass->image, idx);
8647 }
8648
8649 MonoCustomAttrInfo*
8650 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8651 {
8652         MonoTableInfo *ca;
8653         guint32 i, idx, method_index;
8654         guint32 param_list, param_last, param_pos, found;
8655         MonoImage *image;
8656         MonoReflectionMethodAux *aux;
8657
8658         /*
8659          * An instantiated method has the same cattrs as the generic method definition.
8660          *
8661          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8662          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8663          */
8664         if (method->is_inflated)
8665                 method = ((MonoMethodInflated *) method)->declaring;
8666
8667         if (method->klass->image->dynamic) {
8668                 MonoCustomAttrInfo *res, *ainfo;
8669                 int size;
8670
8671                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8672                 if (!aux || !aux->param_cattr)
8673                         return NULL;
8674
8675                 /* Need to copy since it will be freed later */
8676                 ainfo = aux->param_cattr [param];
8677                 if (!ainfo)
8678                         return NULL;
8679                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8680                 res = g_malloc0 (size);
8681                 memcpy (res, ainfo, size);
8682                 return res;
8683         }
8684
8685         image = method->klass->image;
8686         method_index = mono_method_get_index (method);
8687         if (!method_index)
8688                 return NULL;
8689         ca = &image->tables [MONO_TABLE_METHOD];
8690
8691         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8692         if (method_index == ca->rows) {
8693                 ca = &image->tables [MONO_TABLE_PARAM];
8694                 param_last = ca->rows + 1;
8695         } else {
8696                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8697                 ca = &image->tables [MONO_TABLE_PARAM];
8698         }
8699         found = FALSE;
8700         for (i = param_list; i < param_last; ++i) {
8701                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8702                 if (param_pos == param) {
8703                         found = TRUE;
8704                         break;
8705                 }
8706         }
8707         if (!found)
8708                 return NULL;
8709         idx = i;
8710         idx <<= MONO_CUSTOM_ATTR_BITS;
8711         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8712         return mono_custom_attrs_from_index (image, idx);
8713 }
8714
8715 gboolean
8716 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8717 {
8718         int i;
8719         MonoClass *klass;
8720         for (i = 0; i < ainfo->num_attrs; ++i) {
8721                 klass = ainfo->attrs [i].ctor->klass;
8722                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8723                         return TRUE;
8724         }
8725         return FALSE;
8726 }
8727
8728 MonoObject*
8729 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8730 {
8731         int i, attr_index;
8732         MonoClass *klass;
8733         MonoArray *attrs;
8734
8735         attr_index = -1;
8736         for (i = 0; i < ainfo->num_attrs; ++i) {
8737                 klass = ainfo->attrs [i].ctor->klass;
8738                 if (mono_class_has_parent (klass, attr_klass)) {
8739                         attr_index = i;
8740                         break;
8741                 }
8742         }
8743         if (attr_index == -1)
8744                 return NULL;
8745
8746         attrs = mono_custom_attrs_construct (ainfo);
8747         if (attrs)
8748                 return mono_array_get (attrs, MonoObject*, attr_index);
8749         else
8750                 return NULL;
8751 }
8752
8753 /*
8754  * mono_reflection_get_custom_attrs_info:
8755  * @obj: a reflection object handle
8756  *
8757  * Return the custom attribute info for attributes defined for the
8758  * reflection handle @obj. The objects.
8759  *
8760  * FIXME this function leaks like a sieve for SRE objects.
8761  */
8762 MonoCustomAttrInfo*
8763 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8764 {
8765         MonoClass *klass;
8766         MonoCustomAttrInfo *cinfo = NULL;
8767         
8768         klass = obj->vtable->klass;
8769         if (klass == mono_defaults.monotype_class) {
8770                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8771                 klass = mono_class_from_mono_type (type);
8772                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8773                 cinfo = mono_custom_attrs_from_class (klass);
8774         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8775                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8776                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8777         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8778                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8779                 cinfo = mono_custom_attrs_from_module (module->image);
8780         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8781                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8782                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8783         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8784                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8785                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8786         } else if (strcmp ("MonoField", klass->name) == 0) {
8787                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8788                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8789         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8790                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8791                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8792         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8793                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8794                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8795         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8796                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8797                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8798                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8799                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8800                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8801                 } else if (is_sr_mono_property (member_class)) {
8802                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8803                         MonoMethod *method;
8804                         if (!(method = prop->property->get))
8805                                 method = prop->property->set;
8806                         g_assert (method);
8807
8808                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8809                 } 
8810 #ifndef DISABLE_REFLECTION_EMIT
8811                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8812                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8813                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8814                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8815                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8816                         MonoMethod *method = NULL;
8817                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8818                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8819                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8820                                 method = ((MonoReflectionMethod *)c->cb)->method;
8821                         else
8822                                 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8823
8824                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8825                 } 
8826 #endif
8827                 else {
8828                         char *type_name = mono_type_get_full_name (member_class);
8829                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8830                         MonoException *ex = mono_get_exception_not_supported  (msg);
8831                         g_free (type_name);
8832                         g_free (msg);
8833                         mono_raise_exception (ex);
8834                 }
8835         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8836                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8837                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8838         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8839                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8840                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8841         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8842                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8843                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8844         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8845                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8846                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8847         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8848                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8849                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8850         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8851                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8852                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8853         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8854                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8855                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8856         } else { /* handle other types here... */
8857                 g_error ("get custom attrs not yet supported for %s", klass->name);
8858         }
8859
8860         return cinfo;
8861 }
8862
8863 /*
8864  * mono_reflection_get_custom_attrs_by_type:
8865  * @obj: a reflection object handle
8866  *
8867  * Return an array with all the custom attributes defined of the
8868  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8869  * of that type are returned. The objects are fully build. Return NULL if a loading error
8870  * occurs.
8871  */
8872 MonoArray*
8873 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8874 {
8875         MonoArray *result;
8876         MonoCustomAttrInfo *cinfo;
8877
8878         mono_error_init (error);
8879
8880         cinfo = mono_reflection_get_custom_attrs_info (obj);
8881         if (cinfo) {
8882                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8883                 if (!cinfo->cached)
8884                         mono_custom_attrs_free (cinfo);
8885         } else {
8886                 if (mono_loader_get_last_error ())
8887                         return NULL;
8888                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8889         }
8890
8891         return result;
8892 }
8893
8894 /*
8895  * mono_reflection_get_custom_attrs:
8896  * @obj: a reflection object handle
8897  *
8898  * Return an array with all the custom attributes defined of the
8899  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8900  * occurs.
8901  */
8902 MonoArray*
8903 mono_reflection_get_custom_attrs (MonoObject *obj)
8904 {
8905         MonoError error;
8906
8907         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8908 }
8909
8910 /*
8911  * mono_reflection_get_custom_attrs_data:
8912  * @obj: a reflection obj handle
8913  *
8914  * Returns an array of System.Reflection.CustomAttributeData,
8915  * which include information about attributes reflected on
8916  * types loaded using the Reflection Only methods
8917  */
8918 MonoArray*
8919 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8920 {
8921         MonoArray *result;
8922         MonoCustomAttrInfo *cinfo;
8923
8924         cinfo = mono_reflection_get_custom_attrs_info (obj);
8925         if (cinfo) {
8926                 result = mono_custom_attrs_data_construct (cinfo);
8927                 if (!cinfo->cached)
8928                         mono_custom_attrs_free (cinfo);
8929         } else
8930                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8931
8932         return result;
8933 }
8934
8935 static MonoReflectionType*
8936 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8937 {
8938         static MonoMethod *method_get_underlying_system_type = NULL;
8939         MonoMethod *usertype_method;
8940
8941         if (!method_get_underlying_system_type)
8942                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8943         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8944         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8945 }
8946
8947
8948 static gboolean
8949 is_corlib_type (MonoClass *class)
8950 {
8951         return class->image == mono_defaults.corlib;
8952 }
8953
8954 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8955         static MonoClass *cached_class; \
8956         if (cached_class) \
8957                 return cached_class == _class; \
8958         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8959                 cached_class = _class; \
8960                 return TRUE; \
8961         } \
8962         return FALSE; \
8963 } while (0) \
8964
8965
8966 #ifndef DISABLE_REFLECTION_EMIT
8967 static gboolean
8968 is_sre_array (MonoClass *class)
8969 {
8970         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8971 }
8972
8973 static gboolean
8974 is_sre_byref (MonoClass *class)
8975 {
8976         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8977 }
8978
8979 static gboolean
8980 is_sre_pointer (MonoClass *class)
8981 {
8982         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8983 }
8984
8985 static gboolean
8986 is_sre_generic_instance (MonoClass *class)
8987 {
8988         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8989 }
8990
8991 static gboolean
8992 is_sre_type_builder (MonoClass *class)
8993 {
8994         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8995 }
8996
8997 static gboolean
8998 is_sre_method_builder (MonoClass *class)
8999 {
9000         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9001 }
9002
9003 static gboolean
9004 is_sre_ctor_builder (MonoClass *class)
9005 {
9006         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9007 }
9008
9009 static gboolean
9010 is_sre_field_builder (MonoClass *class)
9011 {
9012         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9013 }
9014
9015 static gboolean
9016 is_sre_method_on_tb_inst (MonoClass *class)
9017 {
9018         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9019 }
9020
9021 static gboolean
9022 is_sre_ctor_on_tb_inst (MonoClass *class)
9023 {
9024         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9025 }
9026
9027 MonoType*
9028 mono_reflection_type_get_handle (MonoReflectionType* ref)
9029 {
9030         MonoClass *class;
9031         if (!ref)
9032                 return NULL;
9033         if (ref->type)
9034                 return ref->type;
9035
9036         if (is_usertype (ref)) {
9037                 ref = mono_reflection_type_get_underlying_system_type (ref);
9038                 if (ref == NULL || is_usertype (ref))
9039                         return NULL;
9040                 if (ref->type)
9041                         return ref->type;
9042         }
9043
9044         class = mono_object_class (ref);
9045
9046         if (is_sre_array (class)) {
9047                 MonoType *res;
9048                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9049                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9050                 g_assert (base);
9051                 if (sre_array->rank == 0) //single dimentional array
9052                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9053                 else
9054                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9055                 sre_array->type.type = res;
9056                 return res;
9057         } else if (is_sre_byref (class)) {
9058                 MonoType *res;
9059                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9060                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9061                 g_assert (base);
9062                 res = &mono_class_from_mono_type (base)->this_arg;
9063                 sre_byref->type.type = res;
9064                 return res;
9065         } else if (is_sre_pointer (class)) {
9066                 MonoType *res;
9067                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9068                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9069                 g_assert (base);
9070                 res = &mono_ptr_class_get (base)->byval_arg;
9071                 sre_pointer->type.type = res;
9072                 return res;
9073         } else if (is_sre_generic_instance (class)) {
9074                 MonoType *res, **types;
9075                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9076                 int i, count;
9077
9078                 count = mono_array_length (gclass->type_arguments);
9079                 types = g_new0 (MonoType*, count);
9080                 for (i = 0; i < count; ++i) {
9081                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9082                         types [i] = mono_reflection_type_get_handle (t);
9083                         if (!types[i]) {
9084                                 g_free (types);
9085                                 return NULL;
9086                         }
9087                 }
9088
9089                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9090                 g_free (types);
9091                 g_assert (res);
9092                 gclass->type.type = res;
9093                 return res;
9094         }
9095
9096         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9097         return NULL;
9098 }
9099
9100
9101
9102 void
9103 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9104 {
9105         mono_reflection_type_get_handle (type);
9106 }
9107
9108 void
9109 mono_reflection_register_with_runtime (MonoReflectionType *type)
9110 {
9111         MonoType *res = mono_reflection_type_get_handle (type);
9112         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9113         MonoClass *class;
9114
9115         if (!res)
9116                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9117
9118         class = mono_class_from_mono_type (res);
9119
9120         mono_loader_lock (); /*same locking as mono_type_get_object*/
9121         mono_domain_lock (domain);
9122
9123         if (!class->image->dynamic) {
9124                 mono_class_setup_supertypes (class);
9125         } else {
9126                 if (!domain->type_hash)
9127                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9128                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9129                 mono_g_hash_table_insert (domain->type_hash, res, type);
9130         }
9131         mono_domain_unlock (domain);
9132         mono_loader_unlock ();
9133 }
9134
9135 /**
9136  * LOCKING: Assumes the loader lock is held.
9137  */
9138 static MonoMethodSignature*
9139 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9140         MonoMethodSignature *sig;
9141         int count, i;
9142
9143         count = parameters? mono_array_length (parameters): 0;
9144
9145         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9146         sig->param_count = count;
9147         sig->sentinelpos = -1; /* FIXME */
9148         for (i = 0; i < count; ++i)
9149                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9150         return sig;
9151 }
9152
9153 /**
9154  * LOCKING: Assumes the loader lock is held.
9155  */
9156 static MonoMethodSignature*
9157 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9158         MonoMethodSignature *sig;
9159
9160         sig = parameters_to_signature (image, ctor->parameters);
9161         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9162         sig->ret = &mono_defaults.void_class->byval_arg;
9163         return sig;
9164 }
9165
9166 /**
9167  * LOCKING: Assumes the loader lock is held.
9168  */
9169 static MonoMethodSignature*
9170 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9171         MonoMethodSignature *sig;
9172
9173         sig = parameters_to_signature (image, method->parameters);
9174         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9175         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9176         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9177         return sig;
9178 }
9179
9180 static MonoMethodSignature*
9181 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9182         MonoMethodSignature *sig;
9183
9184         sig = parameters_to_signature (NULL, method->parameters);
9185         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9186         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9187         sig->generic_param_count = 0;
9188         return sig;
9189 }
9190
9191 static void
9192 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9193 {
9194         MonoClass *klass = mono_object_class (prop);
9195         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9196                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9197                 *name = mono_string_to_utf8 (pb->name);
9198                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9199         } else {
9200                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9201                 *name = g_strdup (p->property->name);
9202                 if (p->property->get)
9203                         *type = mono_method_signature (p->property->get)->ret;
9204                 else
9205                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9206         }
9207 }
9208
9209 static void
9210 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9211 {
9212         MonoClass *klass = mono_object_class (field);
9213         if (strcmp (klass->name, "FieldBuilder") == 0) {
9214                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9215                 *name = mono_string_to_utf8 (fb->name);
9216                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9217         } else {
9218                 MonoReflectionField *f = (MonoReflectionField *)field;
9219                 *name = g_strdup (mono_field_get_name (f->field));
9220                 *type = f->field->type;
9221         }
9222 }
9223
9224 #else /* DISABLE_REFLECTION_EMIT */
9225
9226 void
9227 mono_reflection_register_with_runtime (MonoReflectionType *type)
9228 {
9229         /* This is empty */
9230 }
9231
9232 static gboolean
9233 is_sre_type_builder (MonoClass *class)
9234 {
9235         return FALSE;
9236 }
9237
9238 static gboolean
9239 is_sre_generic_instance (MonoClass *class)
9240 {
9241         return FALSE;
9242 }
9243
9244 static void
9245 init_type_builder_generics (MonoObject *type)
9246 {
9247 }
9248
9249 #endif /* !DISABLE_REFLECTION_EMIT */
9250
9251
9252 static gboolean
9253 is_sr_mono_field (MonoClass *class)
9254 {
9255         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9256 }
9257
9258 static gboolean
9259 is_sr_mono_property (MonoClass *class)
9260 {
9261         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9262 }
9263
9264 static gboolean
9265 is_sr_mono_method (MonoClass *class)
9266 {
9267         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9268 }
9269
9270 static gboolean
9271 is_sr_mono_cmethod (MonoClass *class)
9272 {
9273         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9274 }
9275
9276 static gboolean
9277 is_sr_mono_generic_method (MonoClass *class)
9278 {
9279         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9280 }
9281
9282 static gboolean
9283 is_sr_mono_generic_cmethod (MonoClass *class)
9284 {
9285         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9286 }
9287
9288 gboolean
9289 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9290 {
9291         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9292 }
9293
9294 static gboolean
9295 is_usertype (MonoReflectionType *ref)
9296 {
9297         MonoClass *class = mono_object_class (ref);
9298         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9299 }
9300
9301 static MonoReflectionType*
9302 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9303 {
9304         if (!type || type->type)
9305                 return type;
9306
9307         if (is_usertype (type)) {
9308                 type = mono_reflection_type_get_underlying_system_type (type);
9309                 if (is_usertype (type))
9310                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9311         }
9312
9313         return type;
9314 }
9315 /*
9316  * Encode a value in a custom attribute stream of bytes.
9317  * The value to encode is either supplied as an object in argument val
9318  * (valuetypes are boxed), or as a pointer to the data in the
9319  * argument argval.
9320  * @type represents the type of the value
9321  * @buffer is the start of the buffer
9322  * @p the current position in the buffer
9323  * @buflen contains the size of the buffer and is used to return the new buffer size
9324  * if this needs to be realloced.
9325  * @retbuffer and @retp return the start and the position of the buffer
9326  */
9327 static void
9328 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9329 {
9330         MonoTypeEnum simple_type;
9331         
9332         if ((p-buffer) + 10 >= *buflen) {
9333                 char *newbuf;
9334                 *buflen *= 2;
9335                 newbuf = g_realloc (buffer, *buflen);
9336                 p = newbuf + (p-buffer);
9337                 buffer = newbuf;
9338         }
9339         if (!argval)
9340                 argval = ((char*)arg + sizeof (MonoObject));
9341         simple_type = type->type;
9342 handle_enum:
9343         switch (simple_type) {
9344         case MONO_TYPE_BOOLEAN:
9345         case MONO_TYPE_U1:
9346         case MONO_TYPE_I1:
9347                 *p++ = *argval;
9348                 break;
9349         case MONO_TYPE_CHAR:
9350         case MONO_TYPE_U2:
9351         case MONO_TYPE_I2:
9352                 swap_with_size (p, argval, 2, 1);
9353                 p += 2;
9354                 break;
9355         case MONO_TYPE_U4:
9356         case MONO_TYPE_I4:
9357         case MONO_TYPE_R4:
9358                 swap_with_size (p, argval, 4, 1);
9359                 p += 4;
9360                 break;
9361         case MONO_TYPE_R8:
9362 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9363                 p [0] = argval [4];
9364                 p [1] = argval [5];
9365                 p [2] = argval [6];
9366                 p [3] = argval [7];
9367                 p [4] = argval [0];
9368                 p [5] = argval [1];
9369                 p [6] = argval [2];
9370                 p [7] = argval [3];
9371 #else
9372                 swap_with_size (p, argval, 8, 1);
9373 #endif
9374                 p += 8;
9375                 break;
9376         case MONO_TYPE_U8:
9377         case MONO_TYPE_I8:
9378                 swap_with_size (p, argval, 8, 1);
9379                 p += 8;
9380                 break;
9381         case MONO_TYPE_VALUETYPE:
9382                 if (type->data.klass->enumtype) {
9383                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9384                         goto handle_enum;
9385                 } else {
9386                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9387                 }
9388                 break;
9389         case MONO_TYPE_STRING: {
9390                 char *str;
9391                 guint32 slen;
9392                 if (!arg) {
9393                         *p++ = 0xFF;
9394                         break;
9395                 }
9396                 str = mono_string_to_utf8 ((MonoString*)arg);
9397                 slen = strlen (str);
9398                 if ((p-buffer) + 10 + slen >= *buflen) {
9399                         char *newbuf;
9400                         *buflen *= 2;
9401                         *buflen += slen;
9402                         newbuf = g_realloc (buffer, *buflen);
9403                         p = newbuf + (p-buffer);
9404                         buffer = newbuf;
9405                 }
9406                 mono_metadata_encode_value (slen, p, &p);
9407                 memcpy (p, str, slen);
9408                 p += slen;
9409                 g_free (str);
9410                 break;
9411         }
9412         case MONO_TYPE_CLASS: {
9413                 char *str;
9414                 guint32 slen;
9415                 if (!arg) {
9416                         *p++ = 0xFF;
9417                         break;
9418                 }
9419 handle_type:
9420                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9421                 slen = strlen (str);
9422                 if ((p-buffer) + 10 + slen >= *buflen) {
9423                         char *newbuf;
9424                         *buflen *= 2;
9425                         *buflen += slen;
9426                         newbuf = g_realloc (buffer, *buflen);
9427                         p = newbuf + (p-buffer);
9428                         buffer = newbuf;
9429                 }
9430                 mono_metadata_encode_value (slen, p, &p);
9431                 memcpy (p, str, slen);
9432                 p += slen;
9433                 g_free (str);
9434                 break;
9435         }
9436         case MONO_TYPE_SZARRAY: {
9437                 int len, i;
9438                 MonoClass *eclass, *arg_eclass;
9439
9440                 if (!arg) {
9441                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9442                         break;
9443                 }
9444                 len = mono_array_length ((MonoArray*)arg);
9445                 *p++ = len & 0xff;
9446                 *p++ = (len >> 8) & 0xff;
9447                 *p++ = (len >> 16) & 0xff;
9448                 *p++ = (len >> 24) & 0xff;
9449                 *retp = p;
9450                 *retbuffer = buffer;
9451                 eclass = type->data.klass;
9452                 arg_eclass = mono_object_class (arg)->element_class;
9453
9454                 if (!eclass) {
9455                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9456                         eclass = mono_defaults.object_class;
9457                 }
9458                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9459                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9460                         int elsize = mono_class_array_element_size (arg_eclass);
9461                         for (i = 0; i < len; ++i) {
9462                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9463                                 elptr += elsize;
9464                         }
9465                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9466                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9467                         int elsize = mono_class_array_element_size (eclass);
9468                         for (i = 0; i < len; ++i) {
9469                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9470                                 elptr += elsize;
9471                         }
9472                 } else {
9473                         for (i = 0; i < len; ++i) {
9474                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9475                         }
9476                 }
9477                 break;
9478         }
9479         case MONO_TYPE_OBJECT: {
9480                 MonoClass *klass;
9481                 char *str;
9482                 guint32 slen;
9483
9484                 /*
9485                  * The parameter type is 'object' but the type of the actual
9486                  * argument is not. So we have to add type information to the blob
9487                  * too. This is completely undocumented in the spec.
9488                  */
9489
9490                 if (arg == NULL) {
9491                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9492                         *p++ = 0xFF;
9493                         break;
9494                 }
9495                 
9496                 klass = mono_object_class (arg);
9497
9498                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9499                         *p++ = 0x50;
9500                         goto handle_type;
9501                 } else if (klass->enumtype) {
9502                         *p++ = 0x55;
9503                 } else if (klass == mono_defaults.string_class) {
9504                         simple_type = MONO_TYPE_STRING;
9505                         *p++ = 0x0E;
9506                         goto handle_enum;
9507                 } else if (klass->rank == 1) {
9508                         *p++ = 0x1D;
9509                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9510                                 /* See Partition II, Appendix B3 */
9511                                 *p++ = 0x51;
9512                         else
9513                                 *p++ = klass->element_class->byval_arg.type;
9514                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9515                         break;
9516                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9517                         *p++ = simple_type = klass->byval_arg.type;
9518                         goto handle_enum;
9519                 } else {
9520                         g_error ("unhandled type in custom attr");
9521                 }
9522                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9523                 slen = strlen (str);
9524                 if ((p-buffer) + 10 + slen >= *buflen) {
9525                         char *newbuf;
9526                         *buflen *= 2;
9527                         *buflen += slen;
9528                         newbuf = g_realloc (buffer, *buflen);
9529                         p = newbuf + (p-buffer);
9530                         buffer = newbuf;
9531                 }
9532                 mono_metadata_encode_value (slen, p, &p);
9533                 memcpy (p, str, slen);
9534                 p += slen;
9535                 g_free (str);
9536                 simple_type = mono_class_enum_basetype (klass)->type;
9537                 goto handle_enum;
9538         }
9539         default:
9540                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9541         }
9542         *retp = p;
9543         *retbuffer = buffer;
9544 }
9545
9546 static void
9547 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9548 {
9549         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9550                 char *str = type_get_qualified_name (type, NULL);
9551                 int slen = strlen (str);
9552
9553                 *p++ = 0x55;
9554                 /*
9555                  * This seems to be optional...
9556                  * *p++ = 0x80;
9557                  */
9558                 mono_metadata_encode_value (slen, p, &p);
9559                 memcpy (p, str, slen);
9560                 p += slen;
9561                 g_free (str);
9562         } else if (type->type == MONO_TYPE_OBJECT) {
9563                 *p++ = 0x51;
9564         } else if (type->type == MONO_TYPE_CLASS) {
9565                 /* it should be a type: encode_cattr_value () has the check */
9566                 *p++ = 0x50;
9567         } else {
9568                 mono_metadata_encode_value (type->type, p, &p);
9569                 if (type->type == MONO_TYPE_SZARRAY)
9570                         /* See the examples in Partition VI, Annex B */
9571                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9572         }
9573
9574         *retp = p;
9575 }
9576
9577 #ifndef DISABLE_REFLECTION_EMIT
9578 static void
9579 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9580 {
9581         int len;
9582         /* Preallocate a large enough buffer */
9583         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9584                 char *str = type_get_qualified_name (type, NULL);
9585                 len = strlen (str);
9586                 g_free (str);
9587         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9588                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9589                 len = strlen (str);
9590                 g_free (str);
9591         } else {
9592                 len = 0;
9593         }
9594         len += strlen (name);
9595
9596         if ((p-buffer) + 20 + len >= *buflen) {
9597                 char *newbuf;
9598                 *buflen *= 2;
9599                 *buflen += len;
9600                 newbuf = g_realloc (buffer, *buflen);
9601                 p = newbuf + (p-buffer);
9602                 buffer = newbuf;
9603         }
9604
9605         encode_field_or_prop_type (type, p, &p);
9606
9607         len = strlen (name);
9608         mono_metadata_encode_value (len, p, &p);
9609         memcpy (p, name, len);
9610         p += len;
9611         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9612         *retp = p;
9613         *retbuffer = buffer;
9614 }
9615
9616 /*
9617  * mono_reflection_get_custom_attrs_blob:
9618  * @ctor: custom attribute constructor
9619  * @ctorArgs: arguments o the constructor
9620  * @properties:
9621  * @propValues:
9622  * @fields:
9623  * @fieldValues:
9624  * 
9625  * Creates the blob of data that needs to be saved in the metadata and that represents
9626  * the custom attributed described by @ctor, @ctorArgs etc.
9627  * Returns: a Byte array representing the blob of data.
9628  */
9629 MonoArray*
9630 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9631 {
9632         MonoArray *result;
9633         MonoMethodSignature *sig;
9634         MonoObject *arg;
9635         char *buffer, *p;
9636         guint32 buflen, i;
9637
9638         MONO_ARCH_SAVE_REGS;
9639
9640         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9641                 /* sig is freed later so allocate it in the heap */
9642                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9643         } else {
9644                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9645         }
9646
9647         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9648         buflen = 256;
9649         p = buffer = g_malloc (buflen);
9650         /* write the prolog */
9651         *p++ = 1;
9652         *p++ = 0;
9653         for (i = 0; i < sig->param_count; ++i) {
9654                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9655                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9656         }
9657         i = 0;
9658         if (properties)
9659                 i += mono_array_length (properties);
9660         if (fields)
9661                 i += mono_array_length (fields);
9662         *p++ = i & 0xff;
9663         *p++ = (i >> 8) & 0xff;
9664         if (properties) {
9665                 MonoObject *prop;
9666                 for (i = 0; i < mono_array_length (properties); ++i) {
9667                         MonoType *ptype;
9668                         char *pname;
9669
9670                         prop = mono_array_get (properties, gpointer, i);
9671                         get_prop_name_and_type (prop, &pname, &ptype);
9672                         *p++ = 0x54; /* PROPERTY signature */
9673                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9674                         g_free (pname);
9675                 }
9676         }
9677
9678         if (fields) {
9679                 MonoObject *field;
9680                 for (i = 0; i < mono_array_length (fields); ++i) {
9681                         MonoType *ftype;
9682                         char *fname;
9683
9684                         field = mono_array_get (fields, gpointer, i);
9685                         get_field_name_and_type (field, &fname, &ftype);
9686                         *p++ = 0x53; /* FIELD signature */
9687                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9688                         g_free (fname);
9689                 }
9690         }
9691
9692         g_assert (p - buffer <= buflen);
9693         buflen = p - buffer;
9694         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9695         p = mono_array_addr (result, char, 0);
9696         memcpy (p, buffer, buflen);
9697         g_free (buffer);
9698         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9699                 g_free (sig);
9700         return result;
9701 }
9702
9703 /*
9704  * mono_reflection_setup_internal_class:
9705  * @tb: a TypeBuilder object
9706  *
9707  * Creates a MonoClass that represents the TypeBuilder.
9708  * This is a trick that lets us simplify a lot of reflection code
9709  * (and will allow us to support Build and Run assemblies easier).
9710  */
9711 void
9712 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9713 {
9714         MonoError error;
9715         MonoClass *klass, *parent;
9716
9717         MONO_ARCH_SAVE_REGS;
9718
9719         RESOLVE_TYPE (tb->parent);
9720
9721         mono_loader_lock ();
9722
9723         if (tb->parent) {
9724                 /* check so we can compile corlib correctly */
9725                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9726                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9727                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9728                 } else {
9729                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9730                 }
9731         } else {
9732                 parent = NULL;
9733         }
9734         
9735         /* the type has already being created: it means we just have to change the parent */
9736         if (tb->type.type) {
9737                 klass = mono_class_from_mono_type (tb->type.type);
9738                 klass->parent = NULL;
9739                 /* fool mono_class_setup_parent */
9740                 klass->supertypes = NULL;
9741                 mono_class_setup_parent (klass, parent);
9742                 mono_class_setup_mono_type (klass);
9743                 mono_loader_unlock ();
9744                 return;
9745         }
9746
9747         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9748
9749         klass->image = &tb->module->dynamic_image->image;
9750
9751         klass->inited = 1; /* we lie to the runtime */
9752         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9753         if (!mono_error_ok (&error))
9754                 goto failure;
9755         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9756         if (!mono_error_ok (&error))
9757                 goto failure;
9758         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9759         klass->flags = tb->attrs;
9760         
9761         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9762
9763         klass->element_class = klass;
9764
9765         if (mono_class_get_ref_info (klass) == NULL) {
9766
9767                 mono_class_set_ref_info (klass, tb);
9768
9769                 /* Put into cache so mono_class_get () will find it.
9770                 Skip nested types as those should not be available on the global scope. */
9771                 if (!tb->nesting_type) {
9772                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9773                 } else {
9774                         klass->image->reflection_info_unregister_classes =
9775                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9776                 }
9777         } else {
9778                 g_assert (mono_class_get_ref_info (klass) == tb);
9779         }
9780
9781         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9782                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9783
9784         if (parent != NULL) {
9785                 mono_class_setup_parent (klass, parent);
9786         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9787                 const char *old_n = klass->name;
9788                 /* trick to get relative numbering right when compiling corlib */
9789                 klass->name = "BuildingObject";
9790                 mono_class_setup_parent (klass, mono_defaults.object_class);
9791                 klass->name = old_n;
9792         }
9793
9794         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9795                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9796                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9797                 klass->instance_size = sizeof (MonoObject);
9798                 klass->size_inited = 1;
9799                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9800         }
9801
9802         mono_class_setup_mono_type (klass);
9803
9804         mono_class_setup_supertypes (klass);
9805
9806         /*
9807          * FIXME: handle interfaces.
9808          */
9809
9810         tb->type.type = &klass->byval_arg;
9811
9812         if (tb->nesting_type) {
9813                 g_assert (tb->nesting_type->type);
9814                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9815         }
9816
9817         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9818
9819         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9820         
9821         mono_loader_unlock ();
9822         return;
9823
9824 failure:
9825         mono_loader_unlock ();
9826         mono_error_raise_exception (&error);
9827 }
9828
9829 /*
9830  * mono_reflection_setup_generic_class:
9831  * @tb: a TypeBuilder object
9832  *
9833  * Setup the generic class before adding the first generic parameter.
9834  */
9835 void
9836 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9837 {
9838 }
9839
9840 /*
9841  * mono_reflection_create_generic_class:
9842  * @tb: a TypeBuilder object
9843  *
9844  * Creates the generic class after all generic parameters have been added.
9845  */
9846 void
9847 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9848 {
9849         MonoClass *klass;
9850         int count, i;
9851
9852         MONO_ARCH_SAVE_REGS;
9853
9854         klass = mono_class_from_mono_type (tb->type.type);
9855
9856         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9857
9858         if (klass->generic_container || (count == 0))
9859                 return;
9860
9861         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9862
9863         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9864
9865         klass->generic_container->owner.klass = klass;
9866         klass->generic_container->type_argc = count;
9867         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9868
9869         klass->is_generic = 1;
9870
9871         for (i = 0; i < count; i++) {
9872                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9873                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9874                 klass->generic_container->type_params [i] = *param;
9875                 /*Make sure we are a diferent type instance */
9876                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9877                 klass->generic_container->type_params [i].info.pklass = NULL;
9878                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9879
9880                 g_assert (klass->generic_container->type_params [i].param.owner);
9881         }
9882
9883         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9884 }
9885
9886 /*
9887  * mono_reflection_create_internal_class:
9888  * @tb: a TypeBuilder object
9889  *
9890  * Actually create the MonoClass that is associated with the TypeBuilder.
9891  */
9892 void
9893 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9894 {
9895         MonoClass *klass;
9896
9897         MONO_ARCH_SAVE_REGS;
9898
9899         klass = mono_class_from_mono_type (tb->type.type);
9900
9901         mono_loader_lock ();
9902         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9903                 MonoReflectionFieldBuilder *fb;
9904                 MonoClass *ec;
9905                 MonoType *enum_basetype;
9906
9907                 g_assert (tb->fields != NULL);
9908                 g_assert (mono_array_length (tb->fields) >= 1);
9909
9910                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9911
9912                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9913                         mono_loader_unlock ();
9914                         return;
9915                 }
9916
9917                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9918                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9919                 if (!klass->element_class)
9920                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9921
9922                 /*
9923                  * get the element_class from the current corlib.
9924                  */
9925                 ec = default_class_from_mono_type (enum_basetype);
9926                 klass->instance_size = ec->instance_size;
9927                 klass->size_inited = 1;
9928                 /* 
9929                  * this is almost safe to do with enums and it's needed to be able
9930                  * to create objects of the enum type (for use in SetConstant).
9931                  */
9932                 /* FIXME: Does this mean enums can't have method overrides ? */
9933                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9934         }
9935         mono_loader_unlock ();
9936 }
9937
9938 static MonoMarshalSpec*
9939 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9940                                                                 MonoReflectionMarshal *minfo)
9941 {
9942         MonoMarshalSpec *res;
9943
9944         res = image_g_new0 (image, MonoMarshalSpec, 1);
9945         res->native = minfo->type;
9946
9947         switch (minfo->type) {
9948         case MONO_NATIVE_LPARRAY:
9949                 res->data.array_data.elem_type = minfo->eltype;
9950                 if (minfo->has_size) {
9951                         res->data.array_data.param_num = minfo->param_num;
9952                         res->data.array_data.num_elem = minfo->count;
9953                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9954                 }
9955                 else {
9956                         res->data.array_data.param_num = -1;
9957                         res->data.array_data.num_elem = -1;
9958                         res->data.array_data.elem_mult = -1;
9959                 }
9960                 break;
9961
9962         case MONO_NATIVE_BYVALTSTR:
9963         case MONO_NATIVE_BYVALARRAY:
9964                 res->data.array_data.num_elem = minfo->count;
9965                 break;
9966
9967         case MONO_NATIVE_CUSTOM:
9968                 if (minfo->marshaltyperef)
9969                         res->data.custom_data.custom_name =
9970                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9971                 if (minfo->mcookie)
9972                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9973                 break;
9974
9975         default:
9976                 break;
9977         }
9978
9979         return res;
9980 }
9981 #endif /* !DISABLE_REFLECTION_EMIT */
9982
9983 MonoReflectionMarshal*
9984 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9985                                                                                    MonoMarshalSpec *spec)
9986 {
9987         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9988         MonoReflectionMarshal *minfo;
9989         MonoType *mtype;
9990
9991         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9992                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9993                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9994                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9995         }
9996
9997         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9998         minfo->type = spec->native;
9999
10000         switch (minfo->type) {
10001         case MONO_NATIVE_LPARRAY:
10002                 minfo->eltype = spec->data.array_data.elem_type;
10003                 minfo->count = spec->data.array_data.num_elem;
10004                 minfo->param_num = spec->data.array_data.param_num;
10005                 break;
10006
10007         case MONO_NATIVE_BYVALTSTR:
10008         case MONO_NATIVE_BYVALARRAY:
10009                 minfo->count = spec->data.array_data.num_elem;
10010                 break;
10011
10012         case MONO_NATIVE_CUSTOM:
10013                 if (spec->data.custom_data.custom_name) {
10014                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10015                         if (mtype)
10016                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10017
10018                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10019                 }
10020                 if (spec->data.custom_data.cookie)
10021                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10022                 break;
10023
10024         default:
10025                 break;
10026         }
10027
10028         return minfo;
10029 }
10030
10031 #ifndef DISABLE_REFLECTION_EMIT
10032 static MonoMethod*
10033 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10034                                          ReflectionMethodBuilder *rmb,
10035                                          MonoMethodSignature *sig)
10036 {
10037         MonoError error;
10038         MonoMethod *m;
10039         MonoMethodWrapper *wrapperm;
10040         MonoMarshalSpec **specs;
10041         MonoReflectionMethodAux *method_aux;
10042         MonoImage *image;
10043         gboolean dynamic;
10044         int i;
10045
10046         mono_error_init (&error);
10047         /*
10048          * Methods created using a MethodBuilder should have their memory allocated
10049          * inside the image mempool, while dynamic methods should have their memory
10050          * malloc'd.
10051          */
10052         dynamic = rmb->refs != NULL;
10053         image = dynamic ? NULL : klass->image;
10054
10055         if (!dynamic)
10056                 g_assert (!klass->generic_class);
10057
10058         mono_loader_lock ();
10059
10060         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10061                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10062                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10063         else
10064                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10065
10066         wrapperm = (MonoMethodWrapper*)m;
10067
10068         m->dynamic = dynamic;
10069         m->slot = -1;
10070         m->flags = rmb->attrs;
10071         m->iflags = rmb->iattrs;
10072         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10073         m->klass = klass;
10074         m->signature = sig;
10075         m->sre_method = TRUE;
10076         m->skip_visibility = rmb->skip_visibility;
10077         if (rmb->table_idx)
10078                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10079
10080         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10081                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10082                         m->string_ctor = 1;
10083
10084                 m->signature->pinvoke = 1;
10085         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10086                 m->signature->pinvoke = 1;
10087
10088                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10089
10090                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10091                 g_assert (mono_error_ok (&error));
10092                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10093                 g_assert (mono_error_ok (&error));
10094                 
10095                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10096
10097                 if (klass->image->dynamic)
10098                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10099
10100                 mono_loader_unlock ();
10101
10102                 return m;
10103         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10104                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10105                 MonoMethodHeader *header;
10106                 guint32 code_size;
10107                 gint32 max_stack, i;
10108                 gint32 num_locals = 0;
10109                 gint32 num_clauses = 0;
10110                 guint8 *code;
10111
10112                 if (rmb->ilgen) {
10113                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10114                         code_size = rmb->ilgen->code_len;
10115                         max_stack = rmb->ilgen->max_stack;
10116                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10117                         if (rmb->ilgen->ex_handlers)
10118                                 num_clauses = method_count_clauses (rmb->ilgen);
10119                 } else {
10120                         if (rmb->code) {
10121                                 code = mono_array_addr (rmb->code, guint8, 0);
10122                                 code_size = mono_array_length (rmb->code);
10123                                 /* we probably need to run a verifier on the code... */
10124                                 max_stack = 8; 
10125                         }
10126                         else {
10127                                 code = NULL;
10128                                 code_size = 0;
10129                                 max_stack = 8;
10130                         }
10131                 }
10132
10133                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10134                 header->code_size = code_size;
10135                 header->code = image_g_malloc (image, code_size);
10136                 memcpy ((char*)header->code, code, code_size);
10137                 header->max_stack = max_stack;
10138                 header->init_locals = rmb->init_locals;
10139                 header->num_locals = num_locals;
10140
10141                 for (i = 0; i < num_locals; ++i) {
10142                         MonoReflectionLocalBuilder *lb = 
10143                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10144
10145                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10146                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10147                 }
10148
10149                 header->num_clauses = num_clauses;
10150                 if (num_clauses) {
10151                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10152                                  rmb->ilgen, num_clauses);
10153                 }
10154
10155                 wrapperm->header = header;
10156         }
10157
10158         if (rmb->generic_params) {
10159                 int count = mono_array_length (rmb->generic_params);
10160                 MonoGenericContainer *container = rmb->generic_container;
10161
10162                 g_assert (container);
10163
10164                 container->type_argc = count;
10165                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10166                 container->owner.method = m;
10167
10168                 m->is_generic = TRUE;
10169                 mono_method_set_generic_container (m, container);
10170
10171                 for (i = 0; i < count; i++) {
10172                         MonoReflectionGenericParam *gp =
10173                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10174                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10175                         container->type_params [i] = *param;
10176                 }
10177
10178                 /*
10179                  * The method signature might have pointers to generic parameters that belong to other methods.
10180                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10181                  * generic parameters.
10182                  */
10183                 for (i = 0; i < m->signature->param_count; ++i) {
10184                         MonoType *t = m->signature->params [i];
10185                         if (t->type == MONO_TYPE_MVAR) {
10186                                 MonoGenericParam *gparam =  t->data.generic_param;
10187                                 if (gparam->num < count) {
10188                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10189                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10190                                 }
10191
10192                         }
10193                 }
10194
10195                 if (klass->generic_container) {
10196                         container->parent = klass->generic_container;
10197                         container->context.class_inst = klass->generic_container->context.class_inst;
10198                 }
10199                 container->context.method_inst = mono_get_shared_generic_inst (container);
10200         }
10201
10202         if (rmb->refs) {
10203                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10204                 int i;
10205                 void **data;
10206
10207                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10208
10209                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10210                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10211                 for (i = 0; i < rmb->nrefs; ++i)
10212                         data [i + 1] = rmb->refs [i];
10213         }
10214
10215         method_aux = NULL;
10216
10217         /* Parameter info */
10218         if (rmb->pinfo) {
10219                 if (!method_aux)
10220                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10221                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10222                 for (i = 0; i <= m->signature->param_count; ++i) {
10223                         MonoReflectionParamBuilder *pb;
10224                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10225                                 if ((i > 0) && (pb->attrs)) {
10226                                         /* Make a copy since it might point to a shared type structure */
10227                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10228                                         m->signature->params [i - 1]->attrs = pb->attrs;
10229                                 }
10230
10231                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10232                                         MonoDynamicImage *assembly;
10233                                         guint32 idx, def_type, len;
10234                                         char *p;
10235                                         const char *p2;
10236
10237                                         if (!method_aux->param_defaults) {
10238                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10239                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10240                                         }
10241                                         assembly = (MonoDynamicImage*)klass->image;
10242                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10243                                         /* Copy the data from the blob since it might get realloc-ed */
10244                                         p = assembly->blob.data + idx;
10245                                         len = mono_metadata_decode_blob_size (p, &p2);
10246                                         len += p2 - p;
10247                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10248                                         method_aux->param_default_types [i] = def_type;
10249                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10250                                 }
10251
10252                                 if (pb->name) {
10253                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10254                                         g_assert (mono_error_ok (&error));
10255                                 }
10256                                 if (pb->cattrs) {
10257                                         if (!method_aux->param_cattr)
10258                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10259                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10260                                 }
10261                         }
10262                 }
10263         }
10264
10265         /* Parameter marshalling */
10266         specs = NULL;
10267         if (rmb->pinfo)         
10268                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10269                         MonoReflectionParamBuilder *pb;
10270                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10271                                 if (pb->marshal_info) {
10272                                         if (specs == NULL)
10273                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10274                                         specs [pb->position] = 
10275                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10276                                 }
10277                         }
10278                 }
10279         if (specs != NULL) {
10280                 if (!method_aux)
10281                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10282                 method_aux->param_marshall = specs;
10283         }
10284
10285         if (klass->image->dynamic && method_aux)
10286                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10287
10288         mono_loader_unlock ();
10289
10290         return m;
10291 }       
10292
10293 static MonoMethod*
10294 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10295 {
10296         ReflectionMethodBuilder rmb;
10297         MonoMethodSignature *sig;
10298
10299         mono_loader_lock ();
10300         sig = ctor_builder_to_signature (klass->image, mb);
10301         mono_loader_unlock ();
10302
10303         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10304
10305         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10306         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10307
10308         /* If we are in a generic class, we might be called multiple times from inflate_method */
10309         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10310                 /* ilgen is no longer needed */
10311                 mb->ilgen = NULL;
10312         }
10313
10314         return mb->mhandle;
10315 }
10316
10317 static MonoMethod*
10318 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10319 {
10320         ReflectionMethodBuilder rmb;
10321         MonoMethodSignature *sig;
10322
10323         mono_loader_lock ();
10324         sig = method_builder_to_signature (klass->image, mb);
10325         mono_loader_unlock ();
10326
10327         reflection_methodbuilder_from_method_builder (&rmb, mb);
10328
10329         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10330         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10331
10332         /* If we are in a generic class, we might be called multiple times from inflate_method */
10333         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10334                 /* ilgen is no longer needed */
10335                 mb->ilgen = NULL;
10336         }
10337         return mb->mhandle;
10338 }
10339
10340 static MonoClassField*
10341 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10342 {
10343         MonoClassField *field;
10344         MonoType *custom;
10345         MonoError error;
10346
10347         field = g_new0 (MonoClassField, 1);
10348
10349         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10350         g_assert (mono_error_ok (&error));
10351         if (fb->attrs || fb->modreq || fb->modopt) {
10352                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10353                 field->type->attrs = fb->attrs;
10354
10355                 g_assert (klass->image->dynamic);
10356                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10357                 g_free (field->type);
10358                 field->type = mono_metadata_type_dup (klass->image, custom);
10359                 g_free (custom);
10360         } else {
10361                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10362         }
10363         if (fb->offset != -1)
10364                 field->offset = fb->offset;
10365         field->parent = klass;
10366         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10367
10368         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10369
10370         return field;
10371 }
10372 #endif
10373
10374 MonoType*
10375 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10376 {
10377         MonoClass *klass;
10378         MonoReflectionTypeBuilder *tb = NULL;
10379         gboolean is_dynamic = FALSE;
10380         MonoDomain *domain;
10381         MonoClass *geninst;
10382
10383         mono_loader_lock ();
10384
10385         domain = mono_object_domain (type);
10386
10387         if (is_sre_type_builder (mono_object_class (type))) {
10388                 tb = (MonoReflectionTypeBuilder *) type;
10389
10390                 is_dynamic = TRUE;
10391         } else if (is_sre_generic_instance (mono_object_class (type))) {
10392                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10393                 MonoReflectionType *gtd = rgi->generic_type;
10394
10395                 if (is_sre_type_builder (mono_object_class (gtd))) {
10396                         tb = (MonoReflectionTypeBuilder *)gtd;
10397                         is_dynamic = TRUE;
10398                 }
10399         }
10400
10401         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10402         if (tb && tb->generic_container)
10403                 mono_reflection_create_generic_class (tb);
10404
10405         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10406         if (!klass->generic_container) {
10407                 mono_loader_unlock ();
10408                 return NULL;
10409         }
10410
10411         if (klass->wastypebuilder) {
10412                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10413
10414                 is_dynamic = TRUE;
10415         }
10416
10417         mono_loader_unlock ();
10418
10419         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10420
10421         return &geninst->byval_arg;
10422 }
10423
10424 MonoClass*
10425 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10426 {
10427         MonoGenericClass *gclass;
10428         MonoGenericInst *inst;
10429
10430         g_assert (klass->generic_container);
10431
10432         inst = mono_metadata_get_generic_inst (type_argc, types);
10433         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10434
10435         return mono_generic_class_get_class (gclass);
10436 }
10437
10438 MonoReflectionMethod*
10439 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10440 {
10441         MonoClass *klass;
10442         MonoMethod *method, *inflated;
10443         MonoMethodInflated *imethod;
10444         MonoGenericContext tmp_context;
10445         MonoGenericInst *ginst;
10446         MonoType **type_argv;
10447         int count, i;
10448
10449         MONO_ARCH_SAVE_REGS;
10450
10451         /*FIXME but this no longer should happen*/
10452         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10453 #ifndef DISABLE_REFLECTION_EMIT
10454                 MonoReflectionMethodBuilder *mb = NULL;
10455                 MonoReflectionTypeBuilder *tb;
10456                 MonoClass *klass;
10457
10458                 mb = (MonoReflectionMethodBuilder *) rmethod;
10459                 tb = (MonoReflectionTypeBuilder *) mb->type;
10460                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10461
10462                 method = methodbuilder_to_mono_method (klass, mb);
10463 #else
10464                 g_assert_not_reached ();
10465                 method = NULL;
10466 #endif
10467         } else {
10468                 method = rmethod->method;
10469         }
10470
10471         klass = method->klass;
10472
10473         if (method->is_inflated)
10474                 method = ((MonoMethodInflated *) method)->declaring;
10475
10476         count = mono_method_signature (method)->generic_param_count;
10477         if (count != mono_array_length (types))
10478                 return NULL;
10479
10480         type_argv = g_new0 (MonoType *, count);
10481         for (i = 0; i < count; i++) {
10482                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10483                 type_argv [i] = mono_reflection_type_get_handle (garg);
10484         }
10485         ginst = mono_metadata_get_generic_inst (count, type_argv);
10486         g_free (type_argv);
10487
10488         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10489         tmp_context.method_inst = ginst;
10490
10491         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10492         imethod = (MonoMethodInflated *) inflated;
10493
10494         /*FIXME but I think this is no longer necessary*/
10495         if (method->klass->image->dynamic) {
10496                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10497                 /*
10498                  * This table maps metadata structures representing inflated methods/fields
10499                  * to the reflection objects representing their generic definitions.
10500                  */
10501                 mono_loader_lock ();
10502                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10503                 mono_loader_unlock ();
10504         }
10505
10506         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10507                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10508         
10509         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10510 }
10511
10512 #ifndef DISABLE_REFLECTION_EMIT
10513
10514 static MonoMethod *
10515 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10516 {
10517         MonoMethodInflated *imethod;
10518         MonoGenericContext *context;
10519         int i;
10520
10521         /*
10522          * With generic code sharing the klass might not be inflated.
10523          * This can happen because classes inflated with their own
10524          * type arguments are "normalized" to the uninflated class.
10525          */
10526         if (!klass->generic_class)
10527                 return method;
10528
10529         context = mono_class_get_context (klass);
10530
10531         if (klass->method.count && klass->methods) {
10532                 /* Find the already created inflated method */
10533                 for (i = 0; i < klass->method.count; ++i) {
10534                         g_assert (klass->methods [i]->is_inflated);
10535                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10536                                 break;
10537                 }
10538                 g_assert (i < klass->method.count);
10539                 imethod = (MonoMethodInflated*)klass->methods [i];
10540         } else {
10541                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10542         }
10543
10544         if (method->is_generic && method->klass->image->dynamic) {
10545                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10546
10547                 mono_loader_lock ();
10548                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10549                 mono_loader_unlock ();
10550         }
10551         return (MonoMethod *) imethod;
10552 }
10553
10554 static MonoMethod *
10555 inflate_method (MonoReflectionType *type, MonoObject *obj)
10556 {
10557         MonoMethod *method;
10558         MonoClass *gklass;
10559
10560         MonoClass *type_class = mono_object_class (type);
10561
10562         if (is_sre_generic_instance (type_class)) {
10563                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10564                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10565         } else if (is_sre_type_builder (type_class)) {
10566                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10567         } else if (type->type) {
10568                 gklass = mono_class_from_mono_type (type->type);
10569                 gklass = mono_class_get_generic_type_definition (gklass);
10570         } else {
10571                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10572         }
10573
10574         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10575                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10576                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10577                 else
10578                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10579         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10580                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10581         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10582                 method = ((MonoReflectionMethod *) obj)->method;
10583         else {
10584                 method = NULL; /* prevent compiler warning */
10585                 g_error ("can't handle type %s", obj->vtable->klass->name);
10586         }
10587
10588         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10589 }
10590
10591 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10592 void
10593 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10594                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10595                                           MonoArray *events)
10596 {
10597         MonoGenericClass *gclass;
10598         MonoDynamicGenericClass *dgclass;
10599         MonoClass *klass, *gklass;
10600         MonoType *gtype;
10601         int i;
10602
10603         MONO_ARCH_SAVE_REGS;
10604
10605         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10606         klass = mono_class_from_mono_type (gtype);
10607         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10608         gclass = gtype->data.generic_class;
10609
10610         if (!gclass->is_dynamic)
10611                 return;
10612
10613         dgclass = (MonoDynamicGenericClass *) gclass;
10614
10615         if (dgclass->initialized)
10616                 return;
10617
10618         gklass = gclass->container_class;
10619         mono_class_init (gklass);
10620
10621         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10622
10623         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10624         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10625         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10626
10627         for (i = 0; i < dgclass->count_fields; i++) {
10628                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10629                 MonoClassField *field, *inflated_field = NULL;
10630
10631                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10632                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10633                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10634                         field = ((MonoReflectionField *) obj)->field;
10635                 else {
10636                         field = NULL; /* prevent compiler warning */
10637                         g_assert_not_reached ();
10638                 }
10639
10640                 dgclass->fields [i] = *field;
10641                 dgclass->fields [i].parent = klass;
10642                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10643                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10644                 dgclass->field_generic_types [i] = field->type;
10645                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10646                 dgclass->field_objects [i] = obj;
10647
10648                 if (inflated_field) {
10649                         g_free (inflated_field);
10650                 } else {
10651                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10652                 }
10653         }
10654
10655         dgclass->initialized = TRUE;
10656 }
10657
10658 void
10659 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10660 {
10661         MonoDynamicGenericClass *dgclass;
10662         int i;
10663
10664         g_assert (gclass->is_dynamic);
10665
10666         dgclass = (MonoDynamicGenericClass *)gclass;
10667
10668         for (i = 0; i < dgclass->count_fields; ++i) {
10669                 MonoClassField *field = dgclass->fields + i;
10670                 mono_metadata_free_type (field->type);
10671                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10672         }
10673 }
10674
10675 static void
10676 fix_partial_generic_class (MonoClass *klass)
10677 {
10678         MonoClass *gklass = klass->generic_class->container_class;
10679         MonoDynamicGenericClass *dgclass;
10680         int i;
10681
10682         if (klass->wastypebuilder)
10683                 return;
10684
10685         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10686         if (klass->parent != gklass->parent) {
10687                 MonoError error;
10688                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10689                 if (mono_error_ok (&error)) {
10690                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10691                         mono_metadata_free_type (parent_type);
10692                         if (parent != klass->parent) {
10693                                 /*fool mono_class_setup_parent*/
10694                                 klass->supertypes = NULL;
10695                                 mono_class_setup_parent (klass, parent);
10696                         }
10697                 } else {
10698                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10699                         mono_error_cleanup (&error);
10700                         if (gklass->wastypebuilder)
10701                                 klass->wastypebuilder = TRUE;
10702                         return;
10703                 }
10704         }
10705
10706         if (!dgclass->initialized)
10707                 return;
10708
10709         if (klass->method.count != gklass->method.count) {
10710                 klass->method.count = gklass->method.count;
10711                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10712
10713                 for (i = 0; i < klass->method.count; i++) {
10714                         klass->methods [i] = mono_class_inflate_generic_method_full (
10715                                 gklass->methods [i], klass, mono_class_get_context (klass));
10716                 }
10717         }
10718
10719         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10720                 klass->interface_count = gklass->interface_count;
10721                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10722                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10723
10724                 for (i = 0; i < gklass->interface_count; ++i) {
10725                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10726                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10727                         mono_metadata_free_type (iface_type);
10728
10729                         ensure_runtime_vtable (klass->interfaces [i]);
10730                 }
10731                 klass->interfaces_inited = 1;
10732         }
10733
10734         if (klass->field.count != gklass->field.count) {
10735                 klass->field.count = gklass->field.count;
10736                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10737
10738                 for (i = 0; i < klass->field.count; i++) {
10739                         klass->fields [i] = gklass->fields [i];
10740                         klass->fields [i].parent = klass;
10741                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10742                 }
10743         }
10744
10745         /*We can only finish with this klass once it's parent has as well*/
10746         if (gklass->wastypebuilder)
10747                 klass->wastypebuilder = TRUE;
10748         return;
10749 }
10750
10751 static void
10752 ensure_generic_class_runtime_vtable (MonoClass *klass)
10753 {
10754         MonoClass *gklass = klass->generic_class->container_class;
10755
10756         ensure_runtime_vtable (gklass); 
10757
10758         fix_partial_generic_class (klass);
10759 }
10760
10761 static void
10762 ensure_runtime_vtable (MonoClass *klass)
10763 {
10764         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10765         int i, num, j;
10766
10767         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10768                 return;
10769         if (klass->parent)
10770                 ensure_runtime_vtable (klass->parent);
10771
10772         if (tb) {
10773                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10774                 num += tb->num_methods;
10775                 klass->method.count = num;
10776                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10777                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10778                 for (i = 0; i < num; ++i)
10779                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10780                 num = tb->num_methods;
10781                 j = i;
10782                 for (i = 0; i < num; ++i)
10783                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10784         
10785                 if (tb->interfaces) {
10786                         klass->interface_count = mono_array_length (tb->interfaces);
10787                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10788                         for (i = 0; i < klass->interface_count; ++i) {
10789                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10790                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10791                                 ensure_runtime_vtable (klass->interfaces [i]);
10792                         }
10793                         klass->interfaces_inited = 1;
10794                 }
10795         } else if (klass->generic_class){
10796                 ensure_generic_class_runtime_vtable (klass);
10797         }
10798
10799         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10800                 int slot_num = 0;
10801                 for (i = 0; i < klass->method.count; ++i) {
10802                         MonoMethod *im = klass->methods [i];
10803                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10804                                 im->slot = slot_num++;
10805                 }
10806                 
10807                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10808                 mono_class_setup_interface_offsets (klass);
10809                 mono_class_setup_interface_id (klass);
10810         }
10811
10812         /*
10813          * The generic vtable is needed even if image->run is not set since some
10814          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10815          * method->slot being defined.
10816          */
10817
10818         /* 
10819          * tb->methods could not be freed since it is used for determining 
10820          * overrides during dynamic vtable construction.
10821          */
10822 }
10823
10824 static MonoMethod*
10825 mono_reflection_method_get_handle (MonoObject *method)
10826 {
10827         MonoClass *class = mono_object_class (method);
10828         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10829                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10830                 return sr_method->method;
10831         }
10832         if (is_sre_method_builder (class)) {
10833                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10834                 return mb->mhandle;
10835         }
10836         if (is_sre_method_on_tb_inst (class)) {
10837                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10838                 MonoMethod *result;
10839                 /*FIXME move this to a proper method and unify with resolve_object*/
10840                 if (m->method_args) {
10841                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10842                 } else {
10843                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10844                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10845                         MonoMethod *mono_method;
10846
10847                         if (is_sre_method_builder (mono_object_class (m->mb)))
10848                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10849                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10850                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10851                         else
10852                                 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
10853
10854                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10855                 }
10856                 return result;
10857         }
10858
10859         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10860         return NULL;
10861 }
10862
10863 void
10864 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10865 {
10866         MonoReflectionTypeBuilder *tb;
10867         int i, onum;
10868
10869         *overrides = NULL;
10870         *num_overrides = 0;
10871
10872         g_assert (klass->image->dynamic);
10873
10874         if (!mono_class_get_ref_info (klass))
10875                 return;
10876
10877         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10878
10879         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10880
10881         onum = 0;
10882         if (tb->methods) {
10883                 for (i = 0; i < tb->num_methods; ++i) {
10884                         MonoReflectionMethodBuilder *mb = 
10885                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10886                         if (mb->override_method)
10887                                 onum ++;
10888                 }
10889         }
10890
10891         if (onum) {
10892                 *overrides = g_new0 (MonoMethod*, onum * 2);
10893
10894                 onum = 0;
10895                 for (i = 0; i < tb->num_methods; ++i) {
10896                         MonoReflectionMethodBuilder *mb = 
10897                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10898                         if (mb->override_method) {
10899                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10900                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10901
10902                                 g_assert (mb->mhandle);
10903
10904                                 onum ++;
10905                         }
10906                 }
10907         }
10908
10909         *num_overrides = onum;
10910 }
10911
10912 static void
10913 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10914 {
10915         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10916         MonoReflectionFieldBuilder *fb;
10917         MonoClassField *field;
10918         MonoImage *image = klass->image;
10919         const char *p, *p2;
10920         int i;
10921         guint32 len, idx, real_size = 0;
10922
10923         klass->field.count = tb->num_fields;
10924         klass->field.first = 0;
10925
10926         mono_error_init (error);
10927
10928         if (tb->class_size) {
10929                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10930                 klass->packing_size = tb->packing_size;
10931                 real_size = klass->instance_size + tb->class_size;
10932         }
10933
10934         if (!klass->field.count) {
10935                 klass->instance_size = MAX (klass->instance_size, real_size);
10936                 return;
10937         }
10938         
10939         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10940         mono_class_alloc_ext (klass);
10941         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10942         /*
10943         This is, guess what, a hack.
10944         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10945         On the static path no field class is resolved, only types are built. This is the right thing to do
10946         but we suck.
10947         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10948         */
10949         klass->size_inited = 1;
10950
10951         for (i = 0; i < klass->field.count; ++i) {
10952                 fb = mono_array_get (tb->fields, gpointer, i);
10953                 field = &klass->fields [i];
10954                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10955                 if (!mono_error_ok (error))
10956                         return;
10957                 if (fb->attrs) {
10958                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10959                         field->type->attrs = fb->attrs;
10960                 } else {
10961                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10962                 }
10963                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10964                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10965                 if (fb->offset != -1)
10966                         field->offset = fb->offset;
10967                 field->parent = klass;
10968                 fb->handle = field;
10969                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10970
10971                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10972                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10973                 }
10974                 if (fb->def_value) {
10975                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10976                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10977                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10978                         /* Copy the data from the blob since it might get realloc-ed */
10979                         p = assembly->blob.data + idx;
10980                         len = mono_metadata_decode_blob_size (p, &p2);
10981                         len += p2 - p;
10982                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10983                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10984                 }
10985         }
10986
10987         klass->instance_size = MAX (klass->instance_size, real_size);
10988         mono_class_layout_fields (klass);
10989 }
10990
10991 static void
10992 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10993 {
10994         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10995         MonoReflectionPropertyBuilder *pb;
10996         MonoImage *image = klass->image;
10997         MonoProperty *properties;
10998         int i;
10999
11000         mono_error_init (error);
11001
11002         if (!klass->ext)
11003                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11004
11005         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11006         klass->ext->property.first = 0;
11007
11008         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11009         klass->ext->properties = properties;
11010         for (i = 0; i < klass->ext->property.count; ++i) {
11011                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11012                 properties [i].parent = klass;
11013                 properties [i].attrs = pb->attrs;
11014                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11015                 if (!mono_error_ok (error))
11016                         return;
11017                 if (pb->get_method)
11018                         properties [i].get = pb->get_method->mhandle;
11019                 if (pb->set_method)
11020                         properties [i].set = pb->set_method->mhandle;
11021
11022                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11023                 if (pb->def_value) {
11024                         guint32 len, idx;
11025                         const char *p, *p2;
11026                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11027                         if (!klass->ext->prop_def_values)
11028                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11029                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11030                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11031                         /* Copy the data from the blob since it might get realloc-ed */
11032                         p = assembly->blob.data + idx;
11033                         len = mono_metadata_decode_blob_size (p, &p2);
11034                         len += p2 - p;
11035                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11036                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11037                 }
11038         }
11039 }
11040
11041 MonoReflectionEvent *
11042 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11043 {
11044         MonoEvent *event = g_new0 (MonoEvent, 1);
11045         MonoClass *klass;
11046
11047         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11048
11049         event->parent = klass;
11050         event->attrs = eb->attrs;
11051         event->name = mono_string_to_utf8 (eb->name);
11052         if (eb->add_method)
11053                 event->add = eb->add_method->mhandle;
11054         if (eb->remove_method)
11055                 event->remove = eb->remove_method->mhandle;
11056         if (eb->raise_method)
11057                 event->raise = eb->raise_method->mhandle;
11058
11059 #ifndef MONO_SMALL_CONFIG
11060         if (eb->other_methods) {
11061                 int j;
11062                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11063                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11064                         MonoReflectionMethodBuilder *mb = 
11065                                 mono_array_get (eb->other_methods,
11066                                                 MonoReflectionMethodBuilder*, j);
11067                         event->other [j] = mb->mhandle;
11068                 }
11069         }
11070 #endif
11071
11072         return mono_event_get_object (mono_object_domain (tb), klass, event);
11073 }
11074
11075 static void
11076 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11077 {
11078         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11079         MonoReflectionEventBuilder *eb;
11080         MonoImage *image = klass->image;
11081         MonoEvent *events;
11082         int i;
11083
11084         mono_error_init (error);
11085
11086         if (!klass->ext)
11087                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11088
11089         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11090         klass->ext->event.first = 0;
11091
11092         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11093         klass->ext->events = events;
11094         for (i = 0; i < klass->ext->event.count; ++i) {
11095                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11096                 events [i].parent = klass;
11097                 events [i].attrs = eb->attrs;
11098                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11099                 if (!mono_error_ok (error))
11100                         return;
11101                 if (eb->add_method)
11102                         events [i].add = eb->add_method->mhandle;
11103                 if (eb->remove_method)
11104                         events [i].remove = eb->remove_method->mhandle;
11105                 if (eb->raise_method)
11106                         events [i].raise = eb->raise_method->mhandle;
11107
11108 #ifndef MONO_SMALL_CONFIG
11109                 if (eb->other_methods) {
11110                         int j;
11111                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11112                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11113                                 MonoReflectionMethodBuilder *mb = 
11114                                         mono_array_get (eb->other_methods,
11115                                                                         MonoReflectionMethodBuilder*, j);
11116                                 events [i].other [j] = mb->mhandle;
11117                         }
11118                 }
11119 #endif
11120                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11121         }
11122 }
11123
11124 static gboolean
11125 remove_instantiations_of_and_ensure_contents (gpointer key,
11126                                                   gpointer value,
11127                                                   gpointer user_data)
11128 {
11129         MonoType *type = (MonoType*)key;
11130         MonoClass *klass = (MonoClass*)user_data;
11131
11132         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11133                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11134                 return TRUE;
11135         } else
11136                 return FALSE;
11137 }
11138
11139 static void
11140 check_array_for_usertypes (MonoArray *arr)
11141 {
11142         int i;
11143
11144         if (!arr)
11145                 return;
11146
11147         for (i = 0; i < mono_array_length (arr); ++i)
11148                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11149 }
11150
11151 MonoReflectionType*
11152 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11153 {
11154         MonoError error;
11155         MonoClass *klass;
11156         MonoDomain* domain;
11157         MonoReflectionType* res;
11158         int i, j;
11159
11160         MONO_ARCH_SAVE_REGS;
11161
11162         domain = mono_object_domain (tb);
11163         klass = mono_class_from_mono_type (tb->type.type);
11164
11165         /*
11166          * Check for user defined Type subclasses.
11167          */
11168         RESOLVE_TYPE (tb->parent);
11169         check_array_for_usertypes (tb->interfaces);
11170         if (tb->fields) {
11171                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11172                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11173                         if (fb) {
11174                                 RESOLVE_TYPE (fb->type);
11175                                 check_array_for_usertypes (fb->modreq);
11176                                 check_array_for_usertypes (fb->modopt);
11177                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11178                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11179                         }
11180                 }
11181         }
11182         if (tb->methods) {
11183                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11184                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11185                         if (mb) {
11186                                 RESOLVE_TYPE (mb->rtype);
11187                                 check_array_for_usertypes (mb->return_modreq);
11188                                 check_array_for_usertypes (mb->return_modopt);
11189                                 check_array_for_usertypes (mb->parameters);
11190                                 if (mb->param_modreq)
11191                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11192                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11193                                 if (mb->param_modopt)
11194                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11195                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11196                         }
11197                 }
11198         }
11199         if (tb->ctors) {
11200                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11201                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11202                         if (mb) {
11203                                 check_array_for_usertypes (mb->parameters);
11204                                 if (mb->param_modreq)
11205                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11206                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11207                                 if (mb->param_modopt)
11208                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11209                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11210                         }
11211                 }
11212         }
11213
11214         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11215
11216         /* 
11217          * we need to lock the domain because the lock will be taken inside
11218          * So, we need to keep the locking order correct.
11219          */
11220         mono_loader_lock ();
11221         mono_domain_lock (domain);
11222         if (klass->wastypebuilder) {
11223                 mono_domain_unlock (domain);
11224                 mono_loader_unlock ();
11225                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11226         }
11227         /*
11228          * Fields to set in klass:
11229          * the various flags: delegate/unicode/contextbound etc.
11230          */
11231         klass->flags = tb->attrs;
11232         klass->has_cctor = 1;
11233         klass->has_finalize = 1;
11234         klass->has_finalize_inited = 1;
11235
11236         /* fool mono_class_setup_parent */
11237         klass->supertypes = NULL;
11238         mono_class_setup_parent (klass, klass->parent);
11239         mono_class_setup_mono_type (klass);
11240
11241 #if 0
11242         if (!((MonoDynamicImage*)klass->image)->run) {
11243                 if (klass->generic_container) {
11244                         /* FIXME: The code below can't handle generic classes */
11245                         klass->wastypebuilder = TRUE;
11246                         mono_loader_unlock ();
11247                         mono_domain_unlock (domain);
11248                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11249                 }
11250         }
11251 #endif
11252
11253         /* enums are done right away */
11254         if (!klass->enumtype)
11255                 ensure_runtime_vtable (klass);
11256
11257         if (tb->subtypes) {
11258                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11259                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11260                         mono_class_alloc_ext (klass);
11261                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11262                 }
11263         }
11264
11265         klass->nested_classes_inited = TRUE;
11266
11267         /* fields and object layout */
11268         if (klass->parent) {
11269                 if (!klass->parent->size_inited)
11270                         mono_class_init (klass->parent);
11271                 klass->instance_size = klass->parent->instance_size;
11272                 klass->sizes.class_size = 0;
11273                 klass->min_align = klass->parent->min_align;
11274                 /* if the type has no fields we won't call the field_setup
11275                  * routine which sets up klass->has_references.
11276                  */
11277                 klass->has_references |= klass->parent->has_references;
11278         } else {
11279                 klass->instance_size = sizeof (MonoObject);
11280                 klass->min_align = 1;
11281         }
11282
11283         /* FIXME: handle packing_size and instance_size */
11284         typebuilder_setup_fields (klass, &error);
11285         if (!mono_error_ok (&error))
11286                 goto failure;
11287         typebuilder_setup_properties (klass, &error);
11288         if (!mono_error_ok (&error))
11289                 goto failure;
11290
11291         typebuilder_setup_events (klass, &error);
11292         if (!mono_error_ok (&error))
11293                 goto failure;
11294
11295         klass->wastypebuilder = TRUE;
11296
11297         /* 
11298          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11299          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11300          * we want to return normal System.MonoType objects, so clear these out from the cache.
11301          *
11302          * Together with this we must ensure the contents of all instances to match the created type.
11303          */
11304         if (domain->type_hash && klass->generic_container)
11305                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11306
11307         mono_domain_unlock (domain);
11308         mono_loader_unlock ();
11309
11310         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11311                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11312                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11313         }
11314
11315         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11316         g_assert (res != (MonoReflectionType*)tb);
11317
11318         return res;
11319
11320 failure:
11321         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11322         klass->wastypebuilder = TRUE;
11323         mono_domain_unlock (domain);
11324         mono_loader_unlock ();
11325         mono_error_raise_exception (&error);
11326         return NULL;
11327 }
11328
11329 void
11330 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11331 {
11332         MonoGenericParamFull *param;
11333         MonoImage *image;
11334         MonoClass *pklass;
11335         MonoError error;
11336
11337         MONO_ARCH_SAVE_REGS;
11338
11339         image = &gparam->tbuilder->module->dynamic_image->image;
11340
11341         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11342
11343         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11344         g_assert (mono_error_ok (&error));
11345         param->param.num = gparam->index;
11346
11347         if (gparam->mbuilder) {
11348                 if (!gparam->mbuilder->generic_container) {
11349                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11350                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11351                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11352                         gparam->mbuilder->generic_container->is_method = TRUE;
11353                         /* 
11354                          * Cannot set owner.method, since the MonoMethod is not created yet.
11355                          * Set the image field instead, so type_in_image () works.
11356                          */
11357                         gparam->mbuilder->generic_container->image = klass->image;
11358                 }
11359                 param->param.owner = gparam->mbuilder->generic_container;
11360         } else if (gparam->tbuilder) {
11361                 if (!gparam->tbuilder->generic_container) {
11362                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11363                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11364                         gparam->tbuilder->generic_container->owner.klass = klass;
11365                 }
11366                 param->param.owner = gparam->tbuilder->generic_container;
11367         }
11368
11369         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11370
11371         gparam->type.type = &pklass->byval_arg;
11372
11373         mono_class_set_ref_info (pklass, gparam);
11374         mono_image_lock (image);
11375         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11376         mono_image_unlock (image);
11377 }
11378
11379 MonoArray *
11380 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11381 {
11382         MonoReflectionModuleBuilder *module = sig->module;
11383         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11384         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11385         guint32 buflen, i;
11386         MonoArray *result;
11387         SigBuffer buf;
11388
11389         check_array_for_usertypes (sig->arguments);
11390
11391         sigbuffer_init (&buf, 32);
11392
11393         sigbuffer_add_value (&buf, 0x07);
11394         sigbuffer_add_value (&buf, na);
11395         if (assembly != NULL){
11396                 for (i = 0; i < na; ++i) {
11397                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11398                         encode_reflection_type (assembly, type, &buf);
11399                 }
11400         }
11401
11402         buflen = buf.p - buf.buf;
11403         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11404         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11405         sigbuffer_free (&buf);
11406
11407         return result;
11408 }
11409
11410 MonoArray *
11411 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11412 {
11413         MonoDynamicImage *assembly = sig->module->dynamic_image;
11414         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11415         guint32 buflen, i;
11416         MonoArray *result;
11417         SigBuffer buf;
11418
11419         check_array_for_usertypes (sig->arguments);
11420
11421         sigbuffer_init (&buf, 32);
11422
11423         sigbuffer_add_value (&buf, 0x06);
11424         for (i = 0; i < na; ++i) {
11425                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11426                 encode_reflection_type (assembly, type, &buf);
11427         }
11428
11429         buflen = buf.p - buf.buf;
11430         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11431         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11432         sigbuffer_free (&buf);
11433
11434         return result;
11435 }
11436
11437 typedef struct {
11438         MonoMethod *handle;
11439         MonoDomain *domain;
11440 } DynamicMethodReleaseData;
11441
11442 /*
11443  * The runtime automatically clean up those after finalization.
11444 */      
11445 static MonoReferenceQueue *dynamic_method_queue;
11446
11447 static void
11448 free_dynamic_method (void *dynamic_method)
11449 {
11450         DynamicMethodReleaseData *data = dynamic_method;
11451
11452         mono_runtime_free_method (data->domain, data->handle);
11453         g_free (data);
11454 }
11455
11456 void 
11457 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11458 {
11459         MonoReferenceQueue *queue;
11460         MonoMethod *handle;
11461         DynamicMethodReleaseData *release_data;
11462         ReflectionMethodBuilder rmb;
11463         MonoMethodSignature *sig;
11464         MonoClass *klass;
11465         GSList *l;
11466         int i;
11467
11468         if (mono_runtime_is_shutting_down ())
11469                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11470
11471         if (!(queue = dynamic_method_queue)) {
11472                 mono_loader_lock ();
11473                 if (!(queue = dynamic_method_queue))
11474                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11475                 mono_loader_unlock ();
11476         }
11477
11478         sig = dynamic_method_to_signature (mb);
11479
11480         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11481
11482         /*
11483          * Resolve references.
11484          */
11485         /* 
11486          * Every second entry in the refs array is reserved for storing handle_class,
11487          * which is needed by the ldtoken implementation in the JIT.
11488          */
11489         rmb.nrefs = mb->nrefs;
11490         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11491         for (i = 0; i < mb->nrefs; i += 2) {
11492                 MonoClass *handle_class;
11493                 gpointer ref;
11494                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11495
11496                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11497                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11498                         /*
11499                          * The referenced DynamicMethod should already be created by the managed
11500                          * code, except in the case of circular references. In that case, we store
11501                          * method in the refs array, and fix it up later when the referenced 
11502                          * DynamicMethod is created.
11503                          */
11504                         if (method->mhandle) {
11505                                 ref = method->mhandle;
11506                         } else {
11507                                 /* FIXME: GC object stored in unmanaged memory */
11508                                 ref = method;
11509
11510                                 /* FIXME: GC object stored in unmanaged memory */
11511                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11512                         }
11513                         handle_class = mono_defaults.methodhandle_class;
11514                 } else {
11515                         MonoException *ex = NULL;
11516                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11517                         if (!ref)
11518                                 ex = mono_get_exception_type_load (NULL, NULL);
11519                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11520                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11521
11522                         if (ex) {
11523                                 g_free (rmb.refs);
11524                                 mono_raise_exception (ex);
11525                                 return;
11526                         }
11527                 }
11528
11529                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11530                 rmb.refs [i + 1] = handle_class;
11531         }               
11532
11533         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11534
11535         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11536         release_data = g_new (DynamicMethodReleaseData, 1);
11537         release_data->handle = handle;
11538         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11539         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11540                 g_free (release_data);
11541
11542         /* Fix up refs entries pointing at us */
11543         for (l = mb->referenced_by; l; l = l->next) {
11544                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11545                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11546                 gpointer *data;
11547                 
11548                 g_assert (method->mhandle);
11549
11550                 data = (gpointer*)wrapper->method_data;
11551                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11552                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11553                                 data [i + 1] = mb->mhandle;
11554                 }
11555         }
11556         g_slist_free (mb->referenced_by);
11557
11558         g_free (rmb.refs);
11559
11560         /* ilgen is no longer needed */
11561         mb->ilgen = NULL;
11562 }
11563
11564 #endif /* DISABLE_REFLECTION_EMIT */
11565
11566 /**
11567  * 
11568  * mono_reflection_is_valid_dynamic_token:
11569  * 
11570  * Returns TRUE if token is valid.
11571  * 
11572  */
11573 gboolean
11574 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11575 {
11576         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11577 }
11578
11579 MonoMethodSignature *
11580 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11581 {
11582         MonoMethodSignature *sig;
11583         g_assert (image->dynamic);
11584
11585         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11586         if (sig)
11587                 return sig;
11588
11589         return mono_method_signature (method);
11590 }
11591
11592 #ifndef DISABLE_REFLECTION_EMIT
11593
11594 /**
11595  * mono_reflection_lookup_dynamic_token:
11596  *
11597  * Finish the Builder object pointed to by TOKEN and return the corresponding
11598  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11599  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11600  * mapping table.
11601  *
11602  * LOCKING: Take the loader lock
11603  */
11604 gpointer
11605 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11606 {
11607         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11608         MonoObject *obj;
11609         MonoClass *klass;
11610
11611         mono_loader_lock ();
11612         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11613         mono_loader_unlock ();
11614         if (!obj) {
11615                 if (valid_token)
11616                         g_error ("Could not find required dynamic token 0x%08x", token);
11617                 else
11618                         return NULL;
11619         }
11620
11621         if (!handle_class)
11622                 handle_class = &klass;
11623         return resolve_object (image, obj, handle_class, context);
11624 }
11625
11626 /*
11627  * ensure_complete_type:
11628  *
11629  *   Ensure that KLASS is completed if it is a dynamic type, or references
11630  * dynamic types.
11631  */
11632 static void
11633 ensure_complete_type (MonoClass *klass)
11634 {
11635         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11636                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11637
11638                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11639
11640                 // Asserting here could break a lot of code
11641                 //g_assert (klass->wastypebuilder);
11642         }
11643
11644         if (klass->generic_class) {
11645                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11646                 int i;
11647
11648                 for (i = 0; i < inst->type_argc; ++i) {
11649                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11650                 }
11651         }
11652 }
11653
11654 static gpointer
11655 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11656 {
11657         gpointer result = NULL;
11658
11659         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11660                 result = mono_string_intern ((MonoString*)obj);
11661                 *handle_class = mono_defaults.string_class;
11662                 g_assert (result);
11663         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11664                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11665                 MonoClass *mc = mono_class_from_mono_type (type);
11666                 if (!mono_class_init (mc))
11667                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11668
11669                 if (context) {
11670                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11671                         result = mono_class_from_mono_type (inflated);
11672                         mono_metadata_free_type (inflated);
11673                 } else {
11674                         result = mono_class_from_mono_type (type);
11675                 }
11676                 *handle_class = mono_defaults.typehandle_class;
11677                 g_assert (result);
11678         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11679                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11680                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11681                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11682                 result = ((MonoReflectionMethod*)obj)->method;
11683                 if (context)
11684                         result = mono_class_inflate_generic_method (result, context);
11685                 *handle_class = mono_defaults.methodhandle_class;
11686                 g_assert (result);
11687         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11688                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11689                 result = mb->mhandle;
11690                 if (!result) {
11691                         /* Type is not yet created */
11692                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11693
11694                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11695
11696                         /*
11697                          * Hopefully this has been filled in by calling CreateType() on the
11698                          * TypeBuilder.
11699                          */
11700                         /*
11701                          * TODO: This won't work if the application finishes another 
11702                          * TypeBuilder instance instead of this one.
11703                          */
11704                         result = mb->mhandle;
11705                 }
11706                 if (context)
11707                         result = mono_class_inflate_generic_method (result, context);
11708                 *handle_class = mono_defaults.methodhandle_class;
11709         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11710                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11711
11712                 result = cb->mhandle;
11713                 if (!result) {
11714                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11715
11716                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11717                         result = cb->mhandle;
11718                 }
11719                 if (context)
11720                         result = mono_class_inflate_generic_method (result, context);
11721                 *handle_class = mono_defaults.methodhandle_class;
11722         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11723                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11724
11725                 ensure_complete_type (field->parent);
11726                 if (context) {
11727                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11728                         MonoClass *class = mono_class_from_mono_type (inflated);
11729                         MonoClassField *inflated_field;
11730                         gpointer iter = NULL;
11731                         mono_metadata_free_type (inflated);
11732                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11733                                 if (!strcmp (field->name, inflated_field->name))
11734                                         break;
11735                         }
11736                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11737                         result = inflated_field;
11738                 } else {
11739                         result = field;
11740                 }
11741                 *handle_class = mono_defaults.fieldhandle_class;
11742                 g_assert (result);
11743         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11744                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11745                 result = fb->handle;
11746
11747                 if (!result) {
11748                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11749
11750                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11751                         result = fb->handle;
11752                 }
11753
11754                 if (fb->handle && fb->handle->parent->generic_container) {
11755                         MonoClass *klass = fb->handle->parent;
11756                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11757                         MonoClass *inflated = mono_class_from_mono_type (type);
11758
11759                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11760                         g_assert (result);
11761                         mono_metadata_free_type (type);
11762                 }
11763                 *handle_class = mono_defaults.fieldhandle_class;
11764         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11765                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11766                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11767                 MonoClass *klass;
11768
11769                 klass = type->data.klass;
11770                 if (klass->wastypebuilder) {
11771                         /* Already created */
11772                         result = klass;
11773                 }
11774                 else {
11775                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11776                         result = type->data.klass;
11777                         g_assert (result);
11778                 }
11779                 *handle_class = mono_defaults.typehandle_class;
11780         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11781                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11782                 MonoMethodSignature *sig;
11783                 int nargs, i;
11784
11785                 if (helper->arguments)
11786                         nargs = mono_array_length (helper->arguments);
11787                 else
11788                         nargs = 0;
11789
11790                 sig = mono_metadata_signature_alloc (image, nargs);
11791                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11792                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11793
11794                 if (helper->unmanaged_call_conv) { /* unmanaged */
11795                         sig->call_convention = helper->unmanaged_call_conv - 1;
11796                         sig->pinvoke = TRUE;
11797                 } else if (helper->call_conv & 0x02) {
11798                         sig->call_convention = MONO_CALL_VARARG;
11799                 } else {
11800                         sig->call_convention = MONO_CALL_DEFAULT;
11801                 }
11802
11803                 sig->param_count = nargs;
11804                 /* TODO: Copy type ? */
11805                 sig->ret = helper->return_type->type;
11806                 for (i = 0; i < nargs; ++i)
11807                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11808
11809                 result = sig;
11810                 *handle_class = NULL;
11811         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11812                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11813                 /* Already created by the managed code */
11814                 g_assert (method->mhandle);
11815                 result = method->mhandle;
11816                 *handle_class = mono_defaults.methodhandle_class;
11817         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11818                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11819                 type = mono_class_inflate_generic_type (type, context);
11820                 result = mono_class_from_mono_type (type);
11821                 *handle_class = mono_defaults.typehandle_class;
11822                 g_assert (result);
11823                 mono_metadata_free_type (type);
11824         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11825                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11826                 type = mono_class_inflate_generic_type (type, context);
11827                 result = mono_class_from_mono_type (type);
11828                 *handle_class = mono_defaults.typehandle_class;
11829                 g_assert (result);
11830                 mono_metadata_free_type (type);
11831         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11832                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11833                 MonoClass *inflated;
11834                 MonoType *type;
11835                 MonoClassField *field;
11836
11837                 if (is_sre_field_builder (mono_object_class (f->fb)))
11838                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11839                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11840                         field = ((MonoReflectionField*)f->fb)->field;
11841                 else
11842                         g_error ("resolve_object:: can't handle a FTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (f->fb)));
11843
11844                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11845                 inflated = mono_class_from_mono_type (type);
11846
11847                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11848                 ensure_complete_type (field->parent);
11849                 g_assert (result);
11850                 mono_metadata_free_type (type);
11851                 *handle_class = mono_defaults.fieldhandle_class;
11852         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11853                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11854                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11855                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11856                 MonoMethod *method;
11857
11858                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11859                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11860                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11861                         method = ((MonoReflectionMethod *)c->cb)->method;
11862                 else
11863                         g_error ("resolve_object:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (c->cb)));
11864
11865                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11866                 *handle_class = mono_defaults.methodhandle_class;
11867                 mono_metadata_free_type (type);
11868         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11869                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11870                 if (m->method_args) {
11871                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11872                         if (context)
11873                                 result = mono_class_inflate_generic_method (result, context);
11874                 } else {
11875                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11876                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11877                         MonoMethod *method;
11878
11879                         if (is_sre_method_builder (mono_object_class (m->mb)))
11880                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11881                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11882                                 method = ((MonoReflectionMethod *)m->mb)->method;
11883                         else
11884                                 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
11885
11886                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11887                         mono_metadata_free_type (type);
11888                 }
11889                 *handle_class = mono_defaults.methodhandle_class;
11890         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11891                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11892                 MonoType *mtype;
11893                 MonoClass *klass;
11894                 MonoMethod *method;
11895                 gpointer iter;
11896                 char *name;
11897
11898                 mtype = mono_reflection_type_get_handle (m->parent);
11899                 klass = mono_class_from_mono_type (mtype);
11900
11901                 /* Find the method */
11902
11903                 name = mono_string_to_utf8 (m->name);
11904                 iter = NULL;
11905                 while ((method = mono_class_get_methods (klass, &iter))) {
11906                         if (!strcmp (method->name, name))
11907                                 break;
11908                 }
11909                 g_free (name);
11910
11911                 // FIXME:
11912                 g_assert (method);
11913                 // FIXME: Check parameters/return value etc. match
11914
11915                 result = method;
11916                 *handle_class = mono_defaults.methodhandle_class;
11917         } else if (is_sre_array (mono_object_get_class(obj)) ||
11918                                 is_sre_byref (mono_object_get_class(obj)) ||
11919                                 is_sre_pointer (mono_object_get_class(obj))) {
11920                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11921                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11922                 result = mono_class_from_mono_type (type);
11923                 *handle_class = mono_defaults.typehandle_class;
11924         } else {
11925                 g_print ("%s\n", obj->vtable->klass->name);
11926                 g_assert_not_reached ();
11927         }
11928         return result;
11929 }
11930
11931 #else /* DISABLE_REFLECTION_EMIT */
11932
11933 MonoArray*
11934 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11935 {
11936         g_assert_not_reached ();
11937         return NULL;
11938 }
11939
11940 void
11941 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11942 {
11943         g_assert_not_reached ();
11944 }
11945
11946 void
11947 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11948 {
11949         g_assert_not_reached ();
11950 }
11951
11952 void
11953 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11954 {
11955         g_assert_not_reached ();
11956 }
11957
11958 void
11959 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11960 {
11961         g_assert_not_reached ();
11962 }
11963
11964 void
11965 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11966 {
11967         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11968 }
11969
11970 void
11971 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11972 {
11973         g_assert_not_reached ();
11974 }
11975
11976 void
11977 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11978 {
11979         g_assert_not_reached ();
11980 }
11981
11982 MonoReflectionModule *
11983 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11984 {
11985         g_assert_not_reached ();
11986         return NULL;
11987 }
11988
11989 guint32
11990 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11991 {
11992         g_assert_not_reached ();
11993         return 0;
11994 }
11995
11996 guint32
11997 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11998 {
11999         g_assert_not_reached ();
12000         return 0;
12001 }
12002
12003 guint32
12004 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12005                                                  gboolean create_open_instance, gboolean register_token)
12006 {
12007         g_assert_not_reached ();
12008         return 0;
12009 }
12010
12011 void
12012 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12013 {
12014 }
12015
12016 void
12017 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
12018                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12019                                           MonoArray *events)
12020 {
12021         g_assert_not_reached ();
12022 }
12023
12024 void
12025 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12026 {
12027         *overrides = NULL;
12028         *num_overrides = 0;
12029 }
12030
12031 MonoReflectionEvent *
12032 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12033 {
12034         g_assert_not_reached ();
12035         return NULL;
12036 }
12037
12038 MonoReflectionType*
12039 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12040 {
12041         g_assert_not_reached ();
12042         return NULL;
12043 }
12044
12045 void
12046 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12047 {
12048         g_assert_not_reached ();
12049 }
12050
12051 MonoArray *
12052 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12053 {
12054         g_assert_not_reached ();
12055         return NULL;
12056 }
12057
12058 MonoArray *
12059 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12060 {
12061         g_assert_not_reached ();
12062         return NULL;
12063 }
12064
12065 void 
12066 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12067 {
12068 }
12069
12070 gpointer
12071 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12072 {
12073         return NULL;
12074 }
12075
12076 MonoType*
12077 mono_reflection_type_get_handle (MonoReflectionType* ref)
12078 {
12079         if (!ref)
12080                 return NULL;
12081         return ref->type;
12082 }
12083
12084 void
12085 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12086 {
12087         g_assert_not_reached ();
12088 }
12089
12090 #endif /* DISABLE_REFLECTION_EMIT */
12091
12092 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12093 const static guint32 declsec_flags_map[] = {
12094         0x00000000,                                     /* empty */
12095         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12096         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12097         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12098         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12099         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12100         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12101         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12102         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12103         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12104         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12105         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12106         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12107         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12108         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12109         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12110         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12111         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12112         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12113 };
12114
12115 /*
12116  * Returns flags that includes all available security action associated to the handle.
12117  * @token: metadata token (either for a class or a method)
12118  * @image: image where resides the metadata.
12119  */
12120 static guint32
12121 mono_declsec_get_flags (MonoImage *image, guint32 token)
12122 {
12123         int index = mono_metadata_declsec_from_index (image, token);
12124         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12125         guint32 result = 0;
12126         guint32 action;
12127         int i;
12128
12129         /* HasSecurity can be present for other, not specially encoded, attributes,
12130            e.g. SuppressUnmanagedCodeSecurityAttribute */
12131         if (index < 0)
12132                 return 0;
12133
12134         for (i = index; i < t->rows; i++) {
12135                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12136
12137                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12138                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12139                         break;
12140
12141                 action = cols [MONO_DECL_SECURITY_ACTION];
12142                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12143                         result |= declsec_flags_map [action];
12144                 } else {
12145                         g_assert_not_reached ();
12146                 }
12147         }
12148         return result;
12149 }
12150
12151 /*
12152  * Get the security actions (in the form of flags) associated with the specified method.
12153  *
12154  * @method: The method for which we want the declarative security flags.
12155  * Return the declarative security flags for the method (only).
12156  *
12157  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12158  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12159  */
12160 guint32
12161 mono_declsec_flags_from_method (MonoMethod *method)
12162 {
12163         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12164                 /* FIXME: No cache (for the moment) */
12165                 guint32 idx = mono_method_get_index (method);
12166                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12167                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12168                 return mono_declsec_get_flags (method->klass->image, idx);
12169         }
12170         return 0;
12171 }
12172
12173 /*
12174  * Get the security actions (in the form of flags) associated with the specified class.
12175  *
12176  * @klass: The class for which we want the declarative security flags.
12177  * Return the declarative security flags for the class.
12178  *
12179  * Note: We cache the flags inside the MonoClass structure as this will get 
12180  *       called very often (at least for each method).
12181  */
12182 guint32
12183 mono_declsec_flags_from_class (MonoClass *klass)
12184 {
12185         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12186                 if (!klass->ext || !klass->ext->declsec_flags) {
12187                         guint32 idx;
12188
12189                         idx = mono_metadata_token_index (klass->type_token);
12190                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12191                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12192                         mono_loader_lock ();
12193                         mono_class_alloc_ext (klass);
12194                         mono_loader_unlock ();
12195                         /* we cache the flags on classes */
12196                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12197                 }
12198                 return klass->ext->declsec_flags;
12199         }
12200         return 0;
12201 }
12202
12203 /*
12204  * Get the security actions (in the form of flags) associated with the specified assembly.
12205  *
12206  * @assembly: The assembly for which we want the declarative security flags.
12207  * Return the declarative security flags for the assembly.
12208  */
12209 guint32
12210 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12211 {
12212         guint32 idx = 1; /* there is only one assembly */
12213         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12214         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12215         return mono_declsec_get_flags (assembly->image, idx);
12216 }
12217
12218
12219 /*
12220  * Fill actions for the specific index (which may either be an encoded class token or
12221  * an encoded method token) from the metadata image.
12222  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12223  */
12224 static MonoBoolean
12225 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12226         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12227 {
12228         MonoBoolean result = FALSE;
12229         MonoTableInfo *t;
12230         guint32 cols [MONO_DECL_SECURITY_SIZE];
12231         int index = mono_metadata_declsec_from_index (image, token);
12232         int i;
12233
12234         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12235         for (i = index; i < t->rows; i++) {
12236                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12237
12238                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12239                         return result;
12240
12241                 /* if present only replace (class) permissions with method permissions */
12242                 /* if empty accept either class or method permissions */
12243                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12244                         if (!actions->demand.blob) {
12245                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12246                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12247                                 actions->demand.blob = (char*) (blob + 2);
12248                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12249                                 result = TRUE;
12250                         }
12251                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12252                         if (!actions->noncasdemand.blob) {
12253                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12254                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12255                                 actions->noncasdemand.blob = (char*) (blob + 2);
12256                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12257                                 result = TRUE;
12258                         }
12259                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12260                         if (!actions->demandchoice.blob) {
12261                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12262                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12263                                 actions->demandchoice.blob = (char*) (blob + 2);
12264                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12265                                 result = TRUE;
12266                         }
12267                 }
12268         }
12269
12270         return result;
12271 }
12272
12273 static MonoBoolean
12274 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12275         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12276 {
12277         guint32 idx = mono_metadata_token_index (klass->type_token);
12278         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12279         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12280         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12281 }
12282
12283 static MonoBoolean
12284 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12285         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12286 {
12287         guint32 idx = mono_method_get_index (method);
12288         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12289         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12290         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12291 }
12292
12293 /*
12294  * Collect all actions (that requires to generate code in mini) assigned for
12295  * the specified method.
12296  * Note: Don't use the content of actions if the function return FALSE.
12297  */
12298 MonoBoolean
12299 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12300 {
12301         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12302                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12303         MonoBoolean result = FALSE;
12304         guint32 flags;
12305
12306         /* quick exit if no declarative security is present in the metadata */
12307         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12308                 return FALSE;
12309
12310         /* we want the original as the wrapper is "free" of the security informations */
12311         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12312                 method = mono_marshal_method_from_wrapper (method);
12313                 if (!method)
12314                         return FALSE;
12315         }
12316
12317         /* First we look for method-level attributes */
12318         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12319                 mono_class_init (method->klass);
12320                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12321
12322                 result = mono_declsec_get_method_demands_params (method, demands, 
12323                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12324         }
12325
12326         /* Here we use (or create) the class declarative cache to look for demands */
12327         flags = mono_declsec_flags_from_class (method->klass);
12328         if (flags & mask) {
12329                 if (!result) {
12330                         mono_class_init (method->klass);
12331                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12332                 }
12333                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12334                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12335         }
12336
12337         /* The boolean return value is used as a shortcut in case nothing needs to
12338            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12339         return result;
12340 }
12341
12342
12343 /*
12344  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12345  *
12346  * Note: Don't use the content of actions if the function return FALSE.
12347  */
12348 MonoBoolean
12349 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12350 {
12351         MonoBoolean result = FALSE;
12352         guint32 flags;
12353
12354         /* quick exit if no declarative security is present in the metadata */
12355         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12356                 return FALSE;
12357
12358         /* we want the original as the wrapper is "free" of the security informations */
12359         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12360                 method = mono_marshal_method_from_wrapper (method);
12361                 if (!method)
12362                         return FALSE;
12363         }
12364
12365         /* results are independant - zeroize both */
12366         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12367         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12368
12369         /* First we look for method-level attributes */
12370         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12371                 mono_class_init (method->klass);
12372
12373                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12374                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12375         }
12376
12377         /* Here we use (or create) the class declarative cache to look for demands */
12378         flags = mono_declsec_flags_from_class (method->klass);
12379         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12380                 mono_class_init (method->klass);
12381
12382                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12383                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12384         }
12385
12386         return result;
12387 }
12388
12389 /*
12390  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12391  *
12392  * @klass       The inherited class - this is the class that provides the security check (attributes)
12393  * @demans      
12394  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12395  * 
12396  * Note: Don't use the content of actions if the function return FALSE.
12397  */
12398 MonoBoolean
12399 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12400 {
12401         MonoBoolean result = FALSE;
12402         guint32 flags;
12403
12404         /* quick exit if no declarative security is present in the metadata */
12405         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12406                 return FALSE;
12407
12408         /* Here we use (or create) the class declarative cache to look for demands */
12409         flags = mono_declsec_flags_from_class (klass);
12410         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12411                 mono_class_init (klass);
12412                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12413
12414                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12415                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12416         }
12417
12418         return result;
12419 }
12420
12421 /*
12422  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12423  *
12424  * Note: Don't use the content of actions if the function return FALSE.
12425  */
12426 MonoBoolean
12427 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12428 {
12429         /* quick exit if no declarative security is present in the metadata */
12430         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12431                 return FALSE;
12432
12433         /* we want the original as the wrapper is "free" of the security informations */
12434         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12435                 method = mono_marshal_method_from_wrapper (method);
12436                 if (!method)
12437                         return FALSE;
12438         }
12439
12440         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12441                 mono_class_init (method->klass);
12442                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12443
12444                 return mono_declsec_get_method_demands_params (method, demands, 
12445                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12446         }
12447         return FALSE;
12448 }
12449
12450
12451 static MonoBoolean
12452 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12453 {
12454         guint32 cols [MONO_DECL_SECURITY_SIZE];
12455         MonoTableInfo *t;
12456         int i;
12457
12458         int index = mono_metadata_declsec_from_index (image, token);
12459         if (index == -1)
12460                 return FALSE;
12461
12462         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12463         for (i = index; i < t->rows; i++) {
12464                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12465
12466                 /* shortcut - index are ordered */
12467                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12468                         return FALSE;
12469
12470                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12471                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12472                         entry->blob = (char*) (metadata + 2);
12473                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12474                         return TRUE;
12475                 }
12476         }
12477
12478         return FALSE;
12479 }
12480
12481 MonoBoolean
12482 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12483 {
12484         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12485                 guint32 idx = mono_method_get_index (method);
12486                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12487                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12488                 return get_declsec_action (method->klass->image, idx, action, entry);
12489         }
12490         return FALSE;
12491 }
12492
12493 MonoBoolean
12494 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12495 {
12496         /* use cache */
12497         guint32 flags = mono_declsec_flags_from_class (klass);
12498         if (declsec_flags_map [action] & flags) {
12499                 guint32 idx = mono_metadata_token_index (klass->type_token);
12500                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12501                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12502                 return get_declsec_action (klass->image, idx, action, entry);
12503         }
12504         return FALSE;
12505 }
12506
12507 MonoBoolean
12508 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12509 {
12510         guint32 idx = 1; /* there is only one assembly */
12511         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12512         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12513
12514         return get_declsec_action (assembly->image, idx, action, entry);
12515 }
12516
12517 gboolean
12518 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12519 {
12520         MonoObject *res, *exc;
12521         void *params [1];
12522         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12523         static MonoMethod *method = NULL;
12524
12525         if (!System_Reflection_Emit_TypeBuilder) {
12526                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12527                 g_assert (System_Reflection_Emit_TypeBuilder);
12528         }
12529         if (method == NULL) {
12530                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12531                 g_assert (method);
12532         }
12533
12534         /* 
12535          * The result of mono_type_get_object () might be a System.MonoType but we
12536          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12537          */
12538         g_assert (mono_class_get_ref_info (klass));
12539         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12540
12541         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12542
12543         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12544         if (exc)
12545                 return FALSE;
12546         else
12547                 return *(MonoBoolean*)mono_object_unbox (res);
12548 }