2009-04-22 Rodrigo Kumpera <rkumpera@novell.com>
[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
41 #if HAVE_SGEN_GC
42 static void* reflection_info_desc = NULL;
43 #define MOVING_GC_REGISTER(addr) do {   \
44                 if (!reflection_info_desc) {    \
45                         gsize bmap = 1;         \
46                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
47                 }       \
48                 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
49         } while (0)
50 #else
51 #define MOVING_GC_REGISTER(addr)
52 #endif
53
54 static void
55 check_array_for_usertypes (MonoArray *arr)
56 {
57         int i;
58
59         if (!arr)
60                 return;
61
62         for (i = 0; i < mono_array_length (arr); ++i)
63                 CHECK_MONOTYPE (mono_array_get (arr, gpointer, i));
64 }
65
66 typedef struct {
67         char *p;
68         char *buf;
69         char *end;
70 } SigBuffer;
71
72 #define TEXT_OFFSET 512
73 #define CLI_H_SIZE 136
74 #define FILE_ALIGN 512
75 #define VIRT_ALIGN 8192
76 #define START_TEXT_RVA  0x00002000
77
78 typedef struct {
79         MonoReflectionILGen *ilgen;
80         MonoReflectionType *rtype;
81         MonoArray *parameters;
82         MonoArray *generic_params;
83         MonoGenericContainer *generic_container;
84         MonoArray *pinfo;
85         MonoArray *opt_types;
86         guint32 attrs;
87         guint32 iattrs;
88         guint32 call_conv;
89         guint32 *table_idx; /* note: it's a pointer */
90         MonoArray *code;
91         MonoObject *type;
92         MonoString *name;
93         MonoBoolean init_locals;
94         MonoBoolean skip_visibility;
95         MonoArray *return_modreq;
96         MonoArray *return_modopt;
97         MonoArray *param_modreq;
98         MonoArray *param_modopt;
99         MonoArray *permissions;
100         MonoMethod *mhandle;
101         guint32 nrefs;
102         gpointer *refs;
103         /* for PInvoke */
104         int charset, extra_flags, native_cc;
105         MonoString *dll, *dllentry;
106 } ReflectionMethodBuilder;
107
108 typedef struct {
109         guint32 owner;
110         MonoReflectionGenericParam *gparam;
111 } GenericParamTableEntry;
112
113 const unsigned char table_sizes [MONO_TABLE_NUM] = {
114         MONO_MODULE_SIZE,
115         MONO_TYPEREF_SIZE,
116         MONO_TYPEDEF_SIZE,
117         0,
118         MONO_FIELD_SIZE,
119         0,
120         MONO_METHOD_SIZE,
121         0,
122         MONO_PARAM_SIZE,
123         MONO_INTERFACEIMPL_SIZE,
124         MONO_MEMBERREF_SIZE,    /* 0x0A */
125         MONO_CONSTANT_SIZE,
126         MONO_CUSTOM_ATTR_SIZE,
127         MONO_FIELD_MARSHAL_SIZE,
128         MONO_DECL_SECURITY_SIZE,
129         MONO_CLASS_LAYOUT_SIZE,
130         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
131         MONO_STAND_ALONE_SIGNATURE_SIZE,
132         MONO_EVENT_MAP_SIZE,
133         0,
134         MONO_EVENT_SIZE,
135         MONO_PROPERTY_MAP_SIZE,
136         0,
137         MONO_PROPERTY_SIZE,
138         MONO_METHOD_SEMA_SIZE,
139         MONO_METHODIMPL_SIZE,
140         MONO_MODULEREF_SIZE,    /* 0x1A */
141         MONO_TYPESPEC_SIZE,
142         MONO_IMPLMAP_SIZE,      
143         MONO_FIELD_RVA_SIZE,
144         0,
145         0,
146         MONO_ASSEMBLY_SIZE,     /* 0x20 */
147         MONO_ASSEMBLY_PROCESSOR_SIZE,
148         MONO_ASSEMBLYOS_SIZE,
149         MONO_ASSEMBLYREF_SIZE,
150         MONO_ASSEMBLYREFPROC_SIZE,
151         MONO_ASSEMBLYREFOS_SIZE,
152         MONO_FILE_SIZE,
153         MONO_EXP_TYPE_SIZE,
154         MONO_MANIFEST_SIZE,
155         MONO_NESTED_CLASS_SIZE,
156
157         MONO_GENERICPARAM_SIZE, /* 0x2A */
158         MONO_METHODSPEC_SIZE,
159         MONO_GENPARCONSTRAINT_SIZE
160
161 };
162
163 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
164 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
165 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
166 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
167 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
168 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
169 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
170 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
171 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
172 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
173 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
174 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
175 static void    ensure_runtime_vtable (MonoClass *klass);
176 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
177 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
178 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
179 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
180 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
181 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
182 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
183 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
184
185 void
186 mono_reflection_init (void)
187 {
188 }
189
190 static void
191 sigbuffer_init (SigBuffer *buf, int size)
192 {
193         buf->buf = g_malloc (size);
194         buf->p = buf->buf;
195         buf->end = buf->buf + size;
196 }
197
198 static void
199 sigbuffer_make_room (SigBuffer *buf, int size)
200 {
201         if (buf->end - buf->p < size) {
202                 int new_size = buf->end - buf->buf + size + 32;
203                 char *p = g_realloc (buf->buf, new_size);
204                 size = buf->p - buf->buf;
205                 buf->buf = p;
206                 buf->p = p + size;
207                 buf->end = buf->buf + new_size;
208         }
209 }
210
211 static void
212 sigbuffer_add_value (SigBuffer *buf, guint32 val)
213 {
214         sigbuffer_make_room (buf, 6);
215         mono_metadata_encode_value (val, buf->p, &buf->p);
216 }
217
218 static void
219 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
220 {
221         sigbuffer_make_room (buf, 1);
222         buf->p [0] = val;
223         buf->p++;
224 }
225
226 static void
227 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
228 {
229         sigbuffer_make_room (buf, size);
230         memcpy (buf->p, p, size);
231         buf->p += size;
232 }
233
234 static void
235 sigbuffer_free (SigBuffer *buf)
236 {
237         g_free (buf->buf);
238 }
239
240 /**
241  * mp_g_alloc:
242  *
243  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
244  * from the C heap.
245  */
246 static gpointer
247 image_g_malloc (MonoImage *image, guint size)
248 {
249         if (image)
250                 return mono_image_alloc (image, size);
251         else
252                 return g_malloc (size);
253 }
254
255 /**
256  * image_g_alloc0:
257  *
258  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
259  * from the C heap.
260  */
261 static gpointer
262 image_g_malloc0 (MonoImage *image, guint size)
263 {
264         if (image)
265                 return mono_image_alloc0 (image, size);
266         else
267                 return g_malloc0 (size);
268 }
269
270 static char*
271 image_strdup (MonoImage *image, const char *s)
272 {
273         if (image)
274                 return mono_image_strdup (image, s);
275         else
276                 return g_strdup (s);
277 }
278
279 #define image_g_new(image,struct_type, n_structs)               \
280     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
281
282 #define image_g_new0(image,struct_type, n_structs)              \
283     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
284
285
286 static void
287 alloc_table (MonoDynamicTable *table, guint nrows)
288 {
289         table->rows = nrows;
290         g_assert (table->columns);
291         if (nrows + 1 >= table->alloc_rows) {
292                 while (nrows + 1 >= table->alloc_rows) {
293                         if (table->alloc_rows == 0)
294                                 table->alloc_rows = 16;
295                         else
296                                 table->alloc_rows *= 2;
297                 }
298
299                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
300         }
301 }
302
303 static void
304 make_room_in_stream (MonoDynamicStream *stream, int size)
305 {
306         if (size <= stream->alloc_size)
307                 return;
308         
309         while (stream->alloc_size <= size) {
310                 if (stream->alloc_size < 4096)
311                         stream->alloc_size = 4096;
312                 else
313                         stream->alloc_size *= 2;
314         }
315         
316         stream->data = g_realloc (stream->data, stream->alloc_size);
317 }
318
319 static guint32
320 string_heap_insert (MonoDynamicStream *sh, const char *str)
321 {
322         guint32 idx;
323         guint32 len;
324         gpointer oldkey, oldval;
325
326         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
327                 return GPOINTER_TO_UINT (oldval);
328
329         len = strlen (str) + 1;
330         idx = sh->index;
331         
332         make_room_in_stream (sh, idx + len);
333
334         /*
335          * We strdup the string even if we already copy them in sh->data
336          * so that the string pointers in the hash remain valid even if
337          * we need to realloc sh->data. We may want to avoid that later.
338          */
339         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
340         memcpy (sh->data + idx, str, len);
341         sh->index += len;
342         return idx;
343 }
344
345 static guint32
346 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
347 {
348         char *name = mono_string_to_utf8 (str);
349         guint32 idx;
350         idx = string_heap_insert (sh, name);
351         g_free (name);
352         return idx;
353 }
354
355 static void
356 string_heap_init (MonoDynamicStream *sh)
357 {
358         sh->index = 0;
359         sh->alloc_size = 4096;
360         sh->data = g_malloc (4096);
361         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
362         string_heap_insert (sh, "");
363 }
364
365 static guint32
366 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
367 {
368         guint32 idx;
369         
370         make_room_in_stream (stream, stream->index + len);
371         memcpy (stream->data + stream->index, data, len);
372         idx = stream->index;
373         stream->index += len;
374         /* 
375          * align index? Not without adding an additional param that controls it since
376          * we may store a blob value in pieces.
377          */
378         return idx;
379 }
380
381 static guint32
382 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
383 {
384         guint32 idx;
385         
386         make_room_in_stream (stream, stream->index + len);
387         memset (stream->data + stream->index, 0, len);
388         idx = stream->index;
389         stream->index += len;
390         return idx;
391 }
392
393 static void
394 stream_data_align (MonoDynamicStream *stream)
395 {
396         char buf [4] = {0};
397         guint32 count = stream->index % 4;
398
399         /* we assume the stream data will be aligned */
400         if (count)
401                 mono_image_add_stream_data (stream, buf, 4 - count);
402 }
403
404 static int
405 mono_blob_entry_hash (const char* str)
406 {
407         guint len, h;
408         const char *end;
409         len = mono_metadata_decode_blob_size (str, &str);
410         if (len > 0) {
411                 end = str + len;
412                 h = *str;
413                 for (str += 1; str < end; str++)
414                         h = (h << 5) - h + *str;
415                 return h;
416         } else {
417                 return 0;
418         }
419 }
420
421 static gboolean
422 mono_blob_entry_equal (const char *str1, const char *str2) {
423         int len, len2;
424         const char *end1;
425         const char *end2;
426         len = mono_metadata_decode_blob_size (str1, &end1);
427         len2 = mono_metadata_decode_blob_size (str2, &end2);
428         if (len != len2)
429                 return 0;
430         return memcmp (end1, end2, len) == 0;
431 }
432
433 static guint32
434 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
435 {
436         guint32 idx;
437         char *copy;
438         gpointer oldkey, oldval;
439
440         copy = g_malloc (s1+s2);
441         memcpy (copy, b1, s1);
442         memcpy (copy + s1, b2, s2);
443         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
444                 g_free (copy);
445                 idx = GPOINTER_TO_UINT (oldval);
446         } else {
447                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
448                 mono_image_add_stream_data (&assembly->blob, b2, s2);
449                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
450         }
451         return idx;
452 }
453
454 static guint32
455 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
456 {
457         char blob_size [8];
458         char *b = blob_size;
459         guint32 size = buf->p - buf->buf;
460         /* store length */
461         g_assert (size <= (buf->end - buf->buf));
462         mono_metadata_encode_value (size, b, &b);
463         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
464 }
465
466 /*
467  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
468  * dest may be misaligned.
469  */
470 static void
471 swap_with_size (char *dest, const char* val, int len, int nelem) {
472 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
473         int elem;
474
475         for (elem = 0; elem < nelem; ++elem) {
476                 switch (len) {
477                 case 1:
478                         *dest = *val;
479                         break;
480                 case 2:
481                         dest [0] = val [1];
482                         dest [1] = val [0];
483                         break;
484                 case 4:
485                         dest [0] = val [3];
486                         dest [1] = val [2];
487                         dest [2] = val [1];
488                         dest [3] = val [0];
489                         break;
490                 case 8:
491                         dest [0] = val [7];
492                         dest [1] = val [6];
493                         dest [2] = val [5];
494                         dest [3] = val [4];
495                         dest [4] = val [3];
496                         dest [5] = val [2];
497                         dest [6] = val [1];
498                         dest [7] = val [0];
499                         break;
500                 default:
501                         g_assert_not_reached ();
502                 }
503                 dest += len;
504                 val += len;
505         }
506 #else
507         memcpy (dest, val, len * nelem);
508 #endif
509 }
510
511 static guint32
512 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
513 {
514         char blob_size [64];
515         char *b = blob_size;
516         guint32 idx = 0, len;
517
518         len = str->length * 2;
519         mono_metadata_encode_value (len, b, &b);
520 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
521         {
522                 char *swapped = g_malloc (2 * mono_string_length (str));
523                 const char *p = (const char*)mono_string_chars (str);
524
525                 swap_with_size (swapped, p, 2, mono_string_length (str));
526                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
527                 g_free (swapped);
528         }
529 #else
530         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
531 #endif
532         return idx;
533 }
534
535 static MonoClass *
536 default_class_from_mono_type (MonoType *type)
537 {
538         switch (type->type) {
539         case MONO_TYPE_OBJECT:
540                 return mono_defaults.object_class;
541         case MONO_TYPE_VOID:
542                 return mono_defaults.void_class;
543         case MONO_TYPE_BOOLEAN:
544                 return mono_defaults.boolean_class;
545         case MONO_TYPE_CHAR:
546                 return mono_defaults.char_class;
547         case MONO_TYPE_I1:
548                 return mono_defaults.sbyte_class;
549         case MONO_TYPE_U1:
550                 return mono_defaults.byte_class;
551         case MONO_TYPE_I2:
552                 return mono_defaults.int16_class;
553         case MONO_TYPE_U2:
554                 return mono_defaults.uint16_class;
555         case MONO_TYPE_I4:
556                 return mono_defaults.int32_class;
557         case MONO_TYPE_U4:
558                 return mono_defaults.uint32_class;
559         case MONO_TYPE_I:
560                 return mono_defaults.int_class;
561         case MONO_TYPE_U:
562                 return mono_defaults.uint_class;
563         case MONO_TYPE_I8:
564                 return mono_defaults.int64_class;
565         case MONO_TYPE_U8:
566                 return mono_defaults.uint64_class;
567         case MONO_TYPE_R4:
568                 return mono_defaults.single_class;
569         case MONO_TYPE_R8:
570                 return mono_defaults.double_class;
571         case MONO_TYPE_STRING:
572                 return mono_defaults.string_class;
573         default:
574                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
575                 g_assert_not_reached ();
576         }
577         
578         return NULL;
579 }
580
581 static void
582 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
583 {
584         int i;
585         MonoGenericInst *class_inst;
586         MonoClass *klass;
587
588         g_assert (gclass);
589
590         class_inst = gclass->context.class_inst;
591
592         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
593         klass = gclass->container_class;
594         sigbuffer_add_value (buf, klass->byval_arg.type);
595         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
596
597         sigbuffer_add_value (buf, class_inst->type_argc);
598         for (i = 0; i < class_inst->type_argc; ++i)
599                 encode_type (assembly, class_inst->type_argv [i], buf);
600
601 }
602
603 static void
604 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
605 {
606         if (!type) {
607                 g_assert_not_reached ();
608                 return;
609         }
610                 
611         if (type->byref)
612                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
613
614         switch (type->type){
615         case MONO_TYPE_VOID:
616         case MONO_TYPE_BOOLEAN:
617         case MONO_TYPE_CHAR:
618         case MONO_TYPE_I1:
619         case MONO_TYPE_U1:
620         case MONO_TYPE_I2:
621         case MONO_TYPE_U2:
622         case MONO_TYPE_I4:
623         case MONO_TYPE_U4:
624         case MONO_TYPE_I8:
625         case MONO_TYPE_U8:
626         case MONO_TYPE_R4:
627         case MONO_TYPE_R8:
628         case MONO_TYPE_I:
629         case MONO_TYPE_U:
630         case MONO_TYPE_STRING:
631         case MONO_TYPE_OBJECT:
632         case MONO_TYPE_TYPEDBYREF:
633                 sigbuffer_add_value (buf, type->type);
634                 break;
635         case MONO_TYPE_PTR:
636                 sigbuffer_add_value (buf, type->type);
637                 encode_type (assembly, type->data.type, buf);
638                 break;
639         case MONO_TYPE_SZARRAY:
640                 sigbuffer_add_value (buf, type->type);
641                 encode_type (assembly, &type->data.klass->byval_arg, buf);
642                 break;
643         case MONO_TYPE_VALUETYPE:
644         case MONO_TYPE_CLASS: {
645                 MonoClass *k = mono_class_from_mono_type (type);
646
647                 if (k->generic_container) {
648                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
649                         encode_generic_class (assembly, gclass, buf);
650                 } else {
651                         /*
652                          * Make sure we use the correct type.
653                          */
654                         sigbuffer_add_value (buf, k->byval_arg.type);
655                         /*
656                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
657                          * otherwise two typerefs could point to the same type, leading to
658                          * verification errors.
659                          */
660                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
661                 }
662                 break;
663         }
664         case MONO_TYPE_ARRAY:
665                 sigbuffer_add_value (buf, type->type);
666                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
667                 sigbuffer_add_value (buf, type->data.array->rank);
668                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
669                 sigbuffer_add_value (buf, 0);
670                 break;
671         case MONO_TYPE_GENERICINST:
672                 encode_generic_class (assembly, type->data.generic_class, buf);
673                 break;
674         case MONO_TYPE_VAR:
675         case MONO_TYPE_MVAR:
676                 sigbuffer_add_value (buf, type->type);
677                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
678                 break;
679         default:
680                 g_error ("need to encode type %x", type->type);
681         }
682 }
683
684 static void
685 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
686 {
687         if (!type) {
688                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
689                 return;
690         }
691
692         if (type->type ||
693             ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
694                 encode_type (assembly, type->type, buf);
695                 return;
696         }
697
698         g_assert_not_reached ();
699
700 }
701
702 static void
703 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
704 {
705         int i;
706
707         if (modreq) {
708                 for (i = 0; i < mono_array_length (modreq); ++i) {
709                         MonoReflectionType *mod = mono_type_array_get (modreq, i);
710                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
711                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
712                 }
713         }
714         if (modopt) {
715                 for (i = 0; i < mono_array_length (modopt); ++i) {
716                         MonoReflectionType *mod = mono_type_array_get (modopt, i);
717                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
718                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
719                 }
720         }
721 }
722
723 static guint32
724 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
725 {
726         SigBuffer buf;
727         int i;
728         guint32 nparams =  sig->param_count;
729         guint32 idx;
730
731         if (!assembly->save)
732                 return 0;
733
734         sigbuffer_init (&buf, 32);
735         /*
736          * FIXME: vararg, explicit_this, differenc call_conv values...
737          */
738         idx = sig->call_convention;
739         if (sig->hasthis)
740                 idx |= 0x20; /* hasthis */
741         if (sig->generic_param_count)
742                 idx |= 0x10; /* generic */
743         sigbuffer_add_byte (&buf, idx);
744         if (sig->generic_param_count)
745                 sigbuffer_add_value (&buf, sig->generic_param_count);
746         sigbuffer_add_value (&buf, nparams);
747         encode_type (assembly, sig->ret, &buf);
748         for (i = 0; i < nparams; ++i) {
749                 if (i == sig->sentinelpos)
750                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
751                 encode_type (assembly, sig->params [i], &buf);
752         }
753         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
754         sigbuffer_free (&buf);
755         return idx;
756 }
757
758 static guint32
759 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
760 {
761         /*
762          * FIXME: reuse code from method_encode_signature().
763          */
764         SigBuffer buf;
765         int i;
766         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
767         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
768         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
769         guint32 idx;
770
771         sigbuffer_init (&buf, 32);
772         /* LAMESPEC: all the call conv spec is foobared */
773         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
774         if (mb->call_conv & 2)
775                 idx |= 0x5; /* vararg */
776         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
777                 idx |= 0x20; /* hasthis */
778         if (ngparams)
779                 idx |= 0x10; /* generic */
780         sigbuffer_add_byte (&buf, idx);
781         if (ngparams)
782                 sigbuffer_add_value (&buf, ngparams);
783         sigbuffer_add_value (&buf, nparams + notypes);
784         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
785         encode_reflection_type (assembly, mb->rtype, &buf);
786         for (i = 0; i < nparams; ++i) {
787                 MonoArray *modreq = NULL;
788                 MonoArray *modopt = NULL;
789                 MonoReflectionType *pt;
790
791                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
792                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
793                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
794                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
795                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
796                 pt = mono_type_array_get (mb->parameters, i);
797                 encode_reflection_type (assembly, pt, &buf);
798         }
799         if (notypes)
800                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
801         for (i = 0; i < notypes; ++i) {
802                 MonoReflectionType *pt;
803
804                 pt = mono_type_array_get (mb->opt_types, i);
805                 encode_reflection_type (assembly, pt, &buf);
806         }
807
808         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
809         sigbuffer_free (&buf);
810         return idx;
811 }
812
813 static guint32
814 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
815 {
816         MonoDynamicTable *table;
817         guint32 *values;
818         guint32 idx, sig_idx;
819         guint nl = mono_array_length (ilgen->locals);
820         SigBuffer buf;
821         int i;
822
823         sigbuffer_init (&buf, 32);
824         sigbuffer_add_value (&buf, 0x07);
825         sigbuffer_add_value (&buf, nl);
826         for (i = 0; i < nl; ++i) {
827                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
828                 
829                 if (lb->is_pinned)
830                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
831                 
832                 encode_reflection_type (assembly, monotype_cast (lb->type), &buf);
833         }
834         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
835         sigbuffer_free (&buf);
836
837         if (assembly->standalonesig_cache == NULL)
838                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
839         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
840         if (idx)
841                 return idx;
842
843         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
844         idx = table->next_idx ++;
845         table->rows ++;
846         alloc_table (table, table->rows);
847         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
848
849         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
850
851         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
852
853         return idx;
854 }
855
856 static guint32
857 method_count_clauses (MonoReflectionILGen *ilgen)
858 {
859         guint32 num_clauses = 0;
860         int i;
861
862         MonoILExceptionInfo *ex_info;
863         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
864                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
865                 if (ex_info->handlers)
866                         num_clauses += mono_array_length (ex_info->handlers);
867                 else
868                         num_clauses++;
869         }
870
871         return num_clauses;
872 }
873
874 static MonoExceptionClause*
875 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
876 {
877         MonoExceptionClause *clauses;
878         MonoExceptionClause *clause;
879         MonoILExceptionInfo *ex_info;
880         MonoILExceptionBlock *ex_block;
881         guint32 finally_start;
882         int i, j, clause_index;;
883
884         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
885
886         clause_index = 0;
887         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
888                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
889                 finally_start = ex_info->start + ex_info->len;
890                 if (!ex_info->handlers)
891                         continue;
892                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
893                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
894                         clause = &(clauses [clause_index]);
895
896                         clause->flags = ex_block->type;
897                         clause->try_offset = ex_info->start;
898
899                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
900                                 clause->try_len = finally_start - ex_info->start;
901                         else
902                                 clause->try_len = ex_info->len;
903                         clause->handler_offset = ex_block->start;
904                         clause->handler_len = ex_block->len;
905                         if (ex_block->extype) {
906                                 clause->data.catch_class = mono_class_from_mono_type (monotype_cast (ex_block->extype)->type);
907                         } else {
908                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
909                                         clause->data.filter_offset = ex_block->filter_offset;
910                                 else
911                                         clause->data.filter_offset = 0;
912                         }
913                         finally_start = ex_block->start + ex_block->len;
914
915                         clause_index ++;
916                 }
917         }
918
919         return clauses;
920 }
921
922 static guint32
923 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
924 {
925         char flags = 0;
926         guint32 idx;
927         guint32 code_size;
928         gint32 max_stack, i;
929         gint32 num_locals = 0;
930         gint32 num_exception = 0;
931         gint maybe_small;
932         guint32 fat_flags;
933         char fat_header [12];
934         guint32 int_value;
935         guint16 short_value;
936         guint32 local_sig = 0;
937         guint32 header_size = 12;
938         MonoArray *code;
939
940         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
941                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
942                 return 0;
943
944         /*if (mb->name)
945                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
946         if (mb->ilgen) {
947                 code = mb->ilgen->code;
948                 code_size = mb->ilgen->code_len;
949                 max_stack = mb->ilgen->max_stack;
950                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
951                 if (mb->ilgen->ex_handlers)
952                         num_exception = method_count_clauses (mb->ilgen);
953         } else {
954                 code = mb->code;
955                 if (code == NULL){
956                         char *name = mono_string_to_utf8 (mb->name);
957                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
958                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
959                         g_free (str);
960                         g_free (name);
961                         mono_raise_exception (exception);
962                 }
963
964                 code_size = mono_array_length (code);
965                 max_stack = 8; /* we probably need to run a verifier on the code... */
966         }
967
968         stream_data_align (&assembly->code);
969
970         /* check for exceptions, maxstack, locals */
971         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
972         if (maybe_small) {
973                 if (code_size < 64 && !(code_size & 1)) {
974                         flags = (code_size << 2) | 0x2;
975                 } else if (code_size < 32 && (code_size & 1)) {
976                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
977                 } else {
978                         goto fat_header;
979                 }
980                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
981                 /* add to the fixup todo list */
982                 if (mb->ilgen && mb->ilgen->num_token_fixups)
983                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
984                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
985                 return assembly->text_rva + idx;
986         } 
987 fat_header:
988         if (num_locals)
989                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
990         /* 
991          * FIXME: need to set also the header size in fat_flags.
992          * (and more sects and init locals flags)
993          */
994         fat_flags =  0x03;
995         if (num_exception)
996                 fat_flags |= METHOD_HEADER_MORE_SECTS;
997         if (mb->init_locals)
998                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
999         fat_header [0] = fat_flags;
1000         fat_header [1] = (header_size / 4 ) << 4;
1001         short_value = GUINT16_TO_LE (max_stack);
1002         memcpy (fat_header + 2, &short_value, 2);
1003         int_value = GUINT32_TO_LE (code_size);
1004         memcpy (fat_header + 4, &int_value, 4);
1005         int_value = GUINT32_TO_LE (local_sig);
1006         memcpy (fat_header + 8, &int_value, 4);
1007         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1008         /* add to the fixup todo list */
1009         if (mb->ilgen && mb->ilgen->num_token_fixups)
1010                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1011         
1012         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1013         if (num_exception) {
1014                 unsigned char sheader [4];
1015                 MonoILExceptionInfo * ex_info;
1016                 MonoILExceptionBlock * ex_block;
1017                 int j;
1018
1019                 stream_data_align (&assembly->code);
1020                 /* always use fat format for now */
1021                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1022                 num_exception *= 6 * sizeof (guint32);
1023                 num_exception += 4; /* include the size of the header */
1024                 sheader [1] = num_exception & 0xff;
1025                 sheader [2] = (num_exception >> 8) & 0xff;
1026                 sheader [3] = (num_exception >> 16) & 0xff;
1027                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1028                 /* fat header, so we are already aligned */
1029                 /* reverse order */
1030                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1031                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1032                         if (ex_info->handlers) {
1033                                 int finally_start = ex_info->start + ex_info->len;
1034                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1035                                         guint32 val;
1036                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1037                                         /* the flags */
1038                                         val = GUINT32_TO_LE (ex_block->type);
1039                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1040                                         /* try offset */
1041                                         val = GUINT32_TO_LE (ex_info->start);
1042                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1043                                         /* need fault, too, probably */
1044                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1045                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1046                                         else
1047                                                 val = GUINT32_TO_LE (ex_info->len);
1048                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1049                                         /* handler offset */
1050                                         val = GUINT32_TO_LE (ex_block->start);
1051                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1052                                         /* handler len */
1053                                         val = GUINT32_TO_LE (ex_block->len);
1054                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1055                                         finally_start = ex_block->start + ex_block->len;
1056                                         if (ex_block->extype) {
1057                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, monotype_cast (ex_block->extype)->type));
1058                                         } else {
1059                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1060                                                         val = ex_block->filter_offset;
1061                                                 else
1062                                                         val = 0;
1063                                         }
1064                                         val = GUINT32_TO_LE (val);
1065                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1066                                         /*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", 
1067                                                         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);*/
1068                                 }
1069                         } else {
1070                                 g_error ("No clauses for ex info block %d", i);
1071                         }
1072                 }
1073         }
1074         return assembly->text_rva + idx;
1075 }
1076
1077 static guint32
1078 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1079 {
1080         int i;
1081         MonoDynamicTable *table;
1082         guint32 *values;
1083         
1084         table = &assembly->tables [table_idx];
1085
1086         g_assert (col < table->columns);
1087
1088         values = table->values + table->columns;
1089         for (i = 1; i <= table->rows; ++i) {
1090                 if (values [col] == token)
1091                         return i;
1092                 values += table->columns;
1093         }
1094         return 0;
1095 }
1096
1097 /*
1098  * LOCKING: Acquires the loader lock. 
1099  */
1100 static MonoCustomAttrInfo*
1101 lookup_custom_attr (MonoImage *image, gpointer member)
1102 {
1103         MonoCustomAttrInfo* res;
1104
1105         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1106
1107         if (!res)
1108                 return NULL;
1109
1110         return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1111 }
1112
1113 static gboolean
1114 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1115 {
1116         /* FIXME: Need to do more checks */
1117         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1118                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1119
1120                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1121                         return FALSE;
1122         }
1123
1124         return TRUE;
1125 }
1126
1127 static MonoCustomAttrInfo*
1128 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1129 {
1130         int i, index, count, not_visible;
1131         MonoCustomAttrInfo *ainfo;
1132         MonoReflectionCustomAttr *cattr;
1133
1134         if (!cattrs)
1135                 return NULL;
1136         /* FIXME: check in assembly the Run flag is set */
1137
1138         count = mono_array_length (cattrs);
1139
1140         /* Skip nonpublic attributes since MS.NET seems to do the same */
1141         /* FIXME: This needs to be done more globally */
1142         not_visible = 0;
1143         for (i = 0; i < count; ++i) {
1144                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1145                 if (!custom_attr_visible (image, cattr))
1146                         not_visible ++;
1147         }
1148         count -= not_visible;
1149
1150         ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1151
1152         ainfo->image = image;
1153         ainfo->num_attrs = count;
1154         ainfo->cached = alloc_img != NULL;
1155         index = 0;
1156         for (i = 0; i < count; ++i) {
1157                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1158                 if (custom_attr_visible (image, cattr)) {
1159                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1160                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1161                         ainfo->attrs [index].ctor = cattr->ctor->method;
1162                         ainfo->attrs [index].data = saved;
1163                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1164                         index ++;
1165                 }
1166         }
1167
1168         return ainfo;
1169 }
1170
1171 /*
1172  * LOCKING: Acquires the loader lock. 
1173  */
1174 static void
1175 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1176 {
1177         MonoCustomAttrInfo *ainfo, *tmp;
1178
1179         if (!cattrs || !mono_array_length (cattrs))
1180                 return;
1181
1182         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1183
1184         mono_loader_lock ();
1185         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1186         if (tmp)
1187                 mono_custom_attrs_free (tmp);
1188         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1189         mono_loader_unlock ();
1190
1191 }
1192
1193 void
1194 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1195 {
1196         if (!ainfo->cached)
1197                 g_free (ainfo);
1198 }
1199
1200 /*
1201  * idx is the table index of the object
1202  * type is one of MONO_CUSTOM_ATTR_*
1203  */
1204 static void
1205 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1206 {
1207         MonoDynamicTable *table;
1208         MonoReflectionCustomAttr *cattr;
1209         guint32 *values;
1210         guint32 count, i, token;
1211         char blob_size [6];
1212         char *p = blob_size;
1213         
1214         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1215         if (!cattrs)
1216                 return;
1217         count = mono_array_length (cattrs);
1218         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1219         table->rows += count;
1220         alloc_table (table, table->rows);
1221         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1222         idx <<= MONO_CUSTOM_ATTR_BITS;
1223         idx |= type;
1224         for (i = 0; i < count; ++i) {
1225                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1226                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1227                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1228                 type = mono_metadata_token_index (token);
1229                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1230                 switch (mono_metadata_token_table (token)) {
1231                 case MONO_TABLE_METHOD:
1232                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1233                         break;
1234                 case MONO_TABLE_MEMBERREF:
1235                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1236                         break;
1237                 default:
1238                         g_warning ("got wrong token in custom attr");
1239                         continue;
1240                 }
1241                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1242                 p = blob_size;
1243                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1244                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1245                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1246                 values += MONO_CUSTOM_ATTR_SIZE;
1247                 ++table->next_idx;
1248         }
1249 }
1250
1251 static void
1252 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1253 {
1254         MonoDynamicTable *table;
1255         guint32 *values;
1256         guint32 count, i, idx;
1257         MonoReflectionPermissionSet *perm;
1258
1259         if (!permissions)
1260                 return;
1261
1262         count = mono_array_length (permissions);
1263         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1264         table->rows += count;
1265         alloc_table (table, table->rows);
1266
1267         for (i = 0; i < mono_array_length (permissions); ++i) {
1268                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1269
1270                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1271
1272                 idx = mono_metadata_token_index (parent_token);
1273                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1274                 switch (mono_metadata_token_table (parent_token)) {
1275                 case MONO_TABLE_TYPEDEF:
1276                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1277                         break;
1278                 case MONO_TABLE_METHOD:
1279                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1280                         break;
1281                 case MONO_TABLE_ASSEMBLY:
1282                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1283                         break;
1284                 default:
1285                         g_assert_not_reached ();
1286                 }
1287
1288                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1289                 values [MONO_DECL_SECURITY_PARENT] = idx;
1290                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1291
1292                 ++table->next_idx;
1293         }
1294 }
1295
1296 /*
1297  * Fill in the MethodDef and ParamDef tables for a method.
1298  * This is used for both normal methods and constructors.
1299  */
1300 static void
1301 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1302 {
1303         MonoDynamicTable *table;
1304         guint32 *values;
1305         guint i, count;
1306
1307         /* room in this table is already allocated */
1308         table = &assembly->tables [MONO_TABLE_METHOD];
1309         *mb->table_idx = table->next_idx ++;
1310         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1311         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1312         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1313         values [MONO_METHOD_FLAGS] = mb->attrs;
1314         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1315         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1316         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1317         
1318         table = &assembly->tables [MONO_TABLE_PARAM];
1319         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1320
1321         mono_image_add_decl_security (assembly, 
1322                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1323
1324         if (mb->pinfo) {
1325                 MonoDynamicTable *mtable;
1326                 guint32 *mvalues;
1327                 
1328                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1329                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1330                 
1331                 count = 0;
1332                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1333                         if (mono_array_get (mb->pinfo, gpointer, i))
1334                                 count++;
1335                 }
1336                 table->rows += count;
1337                 alloc_table (table, table->rows);
1338                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1339                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1340                         MonoReflectionParamBuilder *pb;
1341                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1342                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1343                                 values [MONO_PARAM_SEQUENCE] = i;
1344                                 if (pb->name != NULL) {
1345                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1346                                 } else {
1347                                         values [MONO_PARAM_NAME] = 0;
1348                                 }
1349                                 values += MONO_PARAM_SIZE;
1350                                 if (pb->marshal_info) {
1351                                         mtable->rows++;
1352                                         alloc_table (mtable, mtable->rows);
1353                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1354                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1355                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1356                                 }
1357                                 pb->table_idx = table->next_idx++;
1358                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1359                                         guint32 field_type = 0;
1360                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1361                                         mtable->rows ++;
1362                                         alloc_table (mtable, mtable->rows);
1363                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1364                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1365                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1366                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1367                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1368                                 }
1369                         }
1370                 }
1371         }
1372 }
1373
1374 static void
1375 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1376 {
1377         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1378
1379         rmb->ilgen = mb->ilgen;
1380         rmb->rtype = monotype_cast (mb->rtype);
1381         rmb->parameters = mb->parameters;
1382         rmb->generic_params = mb->generic_params;
1383         rmb->generic_container = mb->generic_container;
1384         rmb->opt_types = NULL;
1385         rmb->pinfo = mb->pinfo;
1386         rmb->attrs = mb->attrs;
1387         rmb->iattrs = mb->iattrs;
1388         rmb->call_conv = mb->call_conv;
1389         rmb->code = mb->code;
1390         rmb->type = mb->type;
1391         rmb->name = mb->name;
1392         rmb->table_idx = &mb->table_idx;
1393         rmb->init_locals = mb->init_locals;
1394         rmb->skip_visibility = FALSE;
1395         rmb->return_modreq = mb->return_modreq;
1396         rmb->return_modopt = mb->return_modopt;
1397         rmb->param_modreq = mb->param_modreq;
1398         rmb->param_modopt = mb->param_modopt;
1399         rmb->permissions = mb->permissions;
1400         rmb->mhandle = mb->mhandle;
1401         rmb->nrefs = 0;
1402         rmb->refs = NULL;
1403
1404         if (mb->dll) {
1405                 rmb->charset = mb->charset;
1406                 rmb->extra_flags = mb->extra_flags;
1407                 rmb->native_cc = mb->native_cc;
1408                 rmb->dllentry = mb->dllentry;
1409                 rmb->dll = mb->dll;
1410         }
1411 }
1412
1413 static void
1414 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1415 {
1416         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1417
1418         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1419
1420         rmb->ilgen = mb->ilgen;
1421         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1422         rmb->parameters = mb->parameters;
1423         rmb->generic_params = NULL;
1424         rmb->generic_container = NULL;
1425         rmb->opt_types = NULL;
1426         rmb->pinfo = mb->pinfo;
1427         rmb->attrs = mb->attrs;
1428         rmb->iattrs = mb->iattrs;
1429         rmb->call_conv = mb->call_conv;
1430         rmb->code = NULL;
1431         rmb->type = mb->type;
1432         rmb->name = mono_string_new (mono_domain_get (), name);
1433         rmb->table_idx = &mb->table_idx;
1434         rmb->init_locals = mb->init_locals;
1435         rmb->skip_visibility = FALSE;
1436         rmb->return_modreq = NULL;
1437         rmb->return_modopt = NULL;
1438         rmb->param_modreq = mb->param_modreq;
1439         rmb->param_modopt = mb->param_modopt;
1440         rmb->permissions = mb->permissions;
1441         rmb->mhandle = mb->mhandle;
1442         rmb->nrefs = 0;
1443         rmb->refs = NULL;
1444 }
1445
1446 static void
1447 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1448 {
1449         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1450
1451         rmb->ilgen = mb->ilgen;
1452         rmb->rtype = mb->rtype;
1453         rmb->parameters = mb->parameters;
1454         rmb->generic_params = NULL;
1455         rmb->generic_container = NULL;
1456         rmb->opt_types = NULL;
1457         rmb->pinfo = NULL;
1458         rmb->attrs = mb->attrs;
1459         rmb->iattrs = 0;
1460         rmb->call_conv = mb->call_conv;
1461         rmb->code = NULL;
1462         rmb->type = (MonoObject *) mb->owner;
1463         rmb->name = mb->name;
1464         rmb->table_idx = NULL;
1465         rmb->init_locals = mb->init_locals;
1466         rmb->skip_visibility = mb->skip_visibility;
1467         rmb->return_modreq = NULL;
1468         rmb->return_modopt = NULL;
1469         rmb->param_modreq = NULL;
1470         rmb->param_modopt = NULL;
1471         rmb->permissions = NULL;
1472         rmb->mhandle = mb->mhandle;
1473         rmb->nrefs = 0;
1474         rmb->refs = NULL;
1475 }       
1476
1477 static void
1478 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1479 {
1480         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1481         MonoDynamicTable *table;
1482         guint32 *values;
1483         guint32 tok;
1484
1485         if (!mb->override_method)
1486                 return;
1487
1488         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1489         table->rows ++;
1490         alloc_table (table, table->rows);
1491         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1492         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1493         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1494
1495         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1496         switch (mono_metadata_token_table (tok)) {
1497         case MONO_TABLE_MEMBERREF:
1498                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1499                 break;
1500         case MONO_TABLE_METHOD:
1501                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1502                 break;
1503         default:
1504                 g_assert_not_reached ();
1505         }
1506         values [MONO_METHODIMPL_DECLARATION] = tok;
1507 }
1508
1509 static void
1510 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1511 {
1512         MonoDynamicTable *table;
1513         guint32 *values;
1514         ReflectionMethodBuilder rmb;
1515         int i;
1516
1517         reflection_methodbuilder_from_method_builder (&rmb, mb);
1518
1519         mono_image_basic_method (&rmb, assembly);
1520         mb->table_idx = *rmb.table_idx;
1521
1522         if (mb->dll) { /* It's a P/Invoke method */
1523                 guint32 moduleref;
1524                 /* map CharSet values to on-disk values */
1525                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1526                 int extra_flags = mb->extra_flags;
1527                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1528                 table->rows ++;
1529                 alloc_table (table, table->rows);
1530                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1531                 
1532                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1533                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1534                 if (mb->dllentry)
1535                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1536                 else
1537                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1538                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1539                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1540                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1541                         table->rows ++;
1542                         alloc_table (table, table->rows);
1543                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1544                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1545                 }
1546         }
1547
1548         if (mb->generic_params) {
1549                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1550                 table->rows += mono_array_length (mb->generic_params);
1551                 alloc_table (table, table->rows);
1552                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1553                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1554
1555                         mono_image_get_generic_param_info (
1556                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1557                 }
1558         }
1559
1560 }
1561
1562 static void
1563 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1564 {
1565         ReflectionMethodBuilder rmb;
1566
1567         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1568
1569         mono_image_basic_method (&rmb, assembly);
1570         mb->table_idx = *rmb.table_idx;
1571 }
1572
1573 static char*
1574 type_get_fully_qualified_name (MonoType *type)
1575 {
1576         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1577 }
1578
1579 static char*
1580 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1581         MonoClass *klass;
1582         MonoAssembly *ta;
1583
1584         klass = mono_class_from_mono_type (type);
1585         if (!klass) 
1586                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1587         ta = klass->image->assembly;
1588         if (ta->dynamic || (ta == ass)) {
1589                 if (klass->generic_class || klass->generic_container)
1590                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1591                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1592                 else
1593                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1594         }
1595
1596         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1597 }
1598
1599 static guint32
1600 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1601 {
1602         SigBuffer buf;
1603         guint32 idx, i;
1604
1605         if (!assembly->save)
1606                 return 0;
1607
1608         sigbuffer_init (&buf, 32);
1609         
1610         sigbuffer_add_value (&buf, 0x06);
1611         /* encode custom attributes before the type */
1612         /* FIXME: This should probably go in encode_type () */
1613         if (type->num_mods) {
1614                 for (i = 0; i < type->num_mods; ++i) {
1615                         if (type->modifiers [i].required)
1616                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1617                         else
1618                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1619                         sigbuffer_add_value (&buf, type->modifiers [i].token);
1620                 }
1621         }
1622         encode_type (assembly, type, &buf);
1623         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1624         sigbuffer_free (&buf);
1625         return idx;
1626 }
1627
1628 static guint32
1629 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1630 {
1631         SigBuffer buf;
1632         guint32 idx;
1633
1634         sigbuffer_init (&buf, 32);
1635         
1636         sigbuffer_add_value (&buf, 0x06);
1637         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1638         /* encode custom attributes before the type */
1639         encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1640         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1641         sigbuffer_free (&buf);
1642         return idx;
1643 }
1644
1645 static guint32
1646 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1647         char blob_size [64];
1648         char *b = blob_size;
1649         char *p, *box_val;
1650         char* buf;
1651         guint32 idx = 0, len = 0, dummy = 0;
1652 #ifdef ARM_FPU_FPA
1653 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1654         guint32 fpa_double [2];
1655         guint32 *fpa_p;
1656 #endif
1657 #endif
1658         
1659         p = buf = g_malloc (64);
1660         if (!val) {
1661                 *ret_type = MONO_TYPE_CLASS;
1662                 len = 4;
1663                 box_val = (char*)&dummy;
1664         } else {
1665                 box_val = ((char*)val) + sizeof (MonoObject);
1666                 *ret_type = val->vtable->klass->byval_arg.type;
1667         }
1668 handle_enum:
1669         switch (*ret_type) {
1670         case MONO_TYPE_BOOLEAN:
1671         case MONO_TYPE_U1:
1672         case MONO_TYPE_I1:
1673                 len = 1;
1674                 break;
1675         case MONO_TYPE_CHAR:
1676         case MONO_TYPE_U2:
1677         case MONO_TYPE_I2:
1678                 len = 2;
1679                 break;
1680         case MONO_TYPE_U4:
1681         case MONO_TYPE_I4:
1682         case MONO_TYPE_R4:
1683                 len = 4;
1684                 break;
1685         case MONO_TYPE_U8:
1686         case MONO_TYPE_I8:
1687                 len = 8;
1688                 break;
1689         case MONO_TYPE_R8:
1690                 len = 8;
1691 #ifdef ARM_FPU_FPA
1692 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1693                 fpa_p = (guint32*)box_val;
1694                 fpa_double [0] = fpa_p [1];
1695                 fpa_double [1] = fpa_p [0];
1696                 box_val = (char*)fpa_double;
1697 #endif
1698 #endif
1699                 break;
1700         case MONO_TYPE_VALUETYPE:
1701                 if (val->vtable->klass->enumtype) {
1702                         *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1703                         goto handle_enum;
1704                 } else
1705                         g_error ("we can't encode valuetypes");
1706         case MONO_TYPE_CLASS:
1707                 break;
1708         case MONO_TYPE_STRING: {
1709                 MonoString *str = (MonoString*)val;
1710                 /* there is no signature */
1711                 len = str->length * 2;
1712                 mono_metadata_encode_value (len, b, &b);
1713 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1714                 {
1715                         char *swapped = g_malloc (2 * mono_string_length (str));
1716                         const char *p = (const char*)mono_string_chars (str);
1717
1718                         swap_with_size (swapped, p, 2, mono_string_length (str));
1719                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1720                         g_free (swapped);
1721                 }
1722 #else
1723                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1724 #endif
1725
1726                 g_free (buf);
1727                 return idx;
1728         }
1729         case MONO_TYPE_GENERICINST:
1730                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1731                 goto handle_enum;
1732         default:
1733                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1734         }
1735
1736         /* there is no signature */
1737         mono_metadata_encode_value (len, b, &b);
1738 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1739         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1740         swap_with_size (blob_size, box_val, len, 1);
1741         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1742 #else
1743         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1744 #endif
1745
1746         g_free (buf);
1747         return idx;
1748 }
1749
1750 static guint32
1751 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1752         char *str;
1753         SigBuffer buf;
1754         guint32 idx, len;
1755
1756         sigbuffer_init (&buf, 32);
1757
1758         sigbuffer_add_value (&buf, minfo->type);
1759
1760         switch (minfo->type) {
1761         case MONO_NATIVE_BYVALTSTR:
1762         case MONO_NATIVE_BYVALARRAY:
1763                 sigbuffer_add_value (&buf, minfo->count);
1764                 break;
1765         case MONO_NATIVE_LPARRAY:
1766                 if (minfo->eltype || minfo->has_size) {
1767                         sigbuffer_add_value (&buf, minfo->eltype);
1768                         if (minfo->has_size) {
1769                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1770                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1771
1772                                 /* LAMESPEC: ElemMult is undocumented */
1773                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1774                         }
1775                 }
1776                 break;
1777         case MONO_NATIVE_CUSTOM:
1778                 if (minfo->guid) {
1779                         str = mono_string_to_utf8 (minfo->guid);
1780                         len = strlen (str);
1781                         sigbuffer_add_value (&buf, len);
1782                         sigbuffer_add_mem (&buf, str, len);
1783                         g_free (str);
1784                 } else {
1785                         sigbuffer_add_value (&buf, 0);
1786                 }
1787                 /* native type name */
1788                 sigbuffer_add_value (&buf, 0);
1789                 /* custom marshaler type name */
1790                 if (minfo->marshaltype || minfo->marshaltyperef) {
1791                         if (minfo->marshaltyperef)
1792                                 str = type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
1793                         else
1794                                 str = mono_string_to_utf8 (minfo->marshaltype);
1795                         len = strlen (str);
1796                         sigbuffer_add_value (&buf, len);
1797                         sigbuffer_add_mem (&buf, str, len);
1798                         g_free (str);
1799                 } else {
1800                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1801                         sigbuffer_add_value (&buf, 0);
1802                 }
1803                 if (minfo->mcookie) {
1804                         str = mono_string_to_utf8 (minfo->mcookie);
1805                         len = strlen (str);
1806                         sigbuffer_add_value (&buf, len);
1807                         sigbuffer_add_mem (&buf, str, len);
1808                         g_free (str);
1809                 } else {
1810                         sigbuffer_add_value (&buf, 0);
1811                 }
1812                 break;
1813         default:
1814                 break;
1815         }
1816         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1817         sigbuffer_free (&buf);
1818         return idx;
1819 }
1820
1821 static void
1822 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1823 {
1824         MonoDynamicTable *table;
1825         guint32 *values;
1826
1827         /* maybe this fixup should be done in the C# code */
1828         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1829                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1830         table = &assembly->tables [MONO_TABLE_FIELD];
1831         fb->table_idx = table->next_idx ++;
1832         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1833         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1834         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1835         values [MONO_FIELD_FLAGS] = fb->attrs;
1836         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1837
1838         if (fb->offset != -1) {
1839                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1840                 table->rows ++;
1841                 alloc_table (table, table->rows);
1842                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1843                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1844                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1845         }
1846         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1847                 guint32 field_type = 0;
1848                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1849                 table->rows ++;
1850                 alloc_table (table, table->rows);
1851                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1852                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1853                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1854                 values [MONO_CONSTANT_TYPE] = field_type;
1855                 values [MONO_CONSTANT_PADDING] = 0;
1856         }
1857         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1858                 guint32 rva_idx;
1859                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1860                 table->rows ++;
1861                 alloc_table (table, table->rows);
1862                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1863                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1864                 /*
1865                  * We store it in the code section because it's simpler for now.
1866                  */
1867                 if (fb->rva_data) {
1868                         if (mono_array_length (fb->rva_data) >= 10)
1869                                 stream_data_align (&assembly->code);
1870                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1871                 } else
1872                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1873                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1874         }
1875         if (fb->marshal_info) {
1876                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1877                 table->rows ++;
1878                 alloc_table (table, table->rows);
1879                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1880                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1881                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1882         }
1883 }
1884
1885 static guint32
1886 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1887 {
1888         SigBuffer buf;
1889         guint32 nparams = 0;
1890         MonoReflectionMethodBuilder *mb = fb->get_method;
1891         MonoReflectionMethodBuilder *smb = fb->set_method;
1892         guint32 idx, i;
1893
1894         if (mb && mb->parameters)
1895                 nparams = mono_array_length (mb->parameters);
1896         if (!mb && smb && smb->parameters)
1897                 nparams = mono_array_length (smb->parameters) - 1;
1898         sigbuffer_init (&buf, 32);
1899         sigbuffer_add_byte (&buf, 0x08);
1900         sigbuffer_add_value (&buf, nparams);
1901         if (mb) {
1902                 encode_reflection_type (assembly, monotype_cast (mb->rtype), &buf);
1903                 for (i = 0; i < nparams; ++i) {
1904                         MonoReflectionType *pt = mono_type_array_get (mb->parameters, i);
1905                         encode_reflection_type (assembly, pt, &buf);
1906                 }
1907         } else if (smb && smb->parameters) {
1908                 /* the property type is the last param */
1909                 encode_reflection_type (assembly, mono_type_array_get (smb->parameters, nparams), &buf);
1910                 for (i = 0; i < nparams; ++i) {
1911                         MonoReflectionType *pt = mono_type_array_get (smb->parameters, i);
1912                         encode_reflection_type (assembly, pt, &buf);
1913                 }
1914         } else {
1915                 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1916         }
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_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1925 {
1926         MonoDynamicTable *table;
1927         guint32 *values;
1928         guint num_methods = 0;
1929         guint32 semaidx;
1930
1931         /* 
1932          * we need to set things in the following tables:
1933          * PROPERTYMAP (info already filled in _get_type_info ())
1934          * PROPERTY    (rows already preallocated in _get_type_info ())
1935          * METHOD      (method info already done with the generic method code)
1936          * METHODSEMANTICS
1937          */
1938         table = &assembly->tables [MONO_TABLE_PROPERTY];
1939         pb->table_idx = table->next_idx ++;
1940         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1941         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1942         values [MONO_PROPERTY_FLAGS] = pb->attrs;
1943         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1944
1945         /* FIXME: we still don't handle 'other' methods */
1946         if (pb->get_method) num_methods ++;
1947         if (pb->set_method) num_methods ++;
1948
1949         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1950         table->rows += num_methods;
1951         alloc_table (table, table->rows);
1952
1953         if (pb->get_method) {
1954                 semaidx = table->next_idx ++;
1955                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1956                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1957                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1958                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1959         }
1960         if (pb->set_method) {
1961                 semaidx = table->next_idx ++;
1962                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1963                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1964                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1965                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1966         }
1967 }
1968
1969 static void
1970 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1971 {
1972         MonoDynamicTable *table;
1973         guint32 *values;
1974         guint num_methods = 0;
1975         guint32 semaidx;
1976
1977         /* 
1978          * we need to set things in the following tables:
1979          * EVENTMAP (info already filled in _get_type_info ())
1980          * EVENT    (rows already preallocated in _get_type_info ())
1981          * METHOD      (method info already done with the generic method code)
1982          * METHODSEMANTICS
1983          */
1984         table = &assembly->tables [MONO_TABLE_EVENT];
1985         eb->table_idx = table->next_idx ++;
1986         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1987         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1988         values [MONO_EVENT_FLAGS] = eb->attrs;
1989         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1990
1991         /*
1992          * FIXME: we still don't handle 'other' methods 
1993          */
1994         if (eb->add_method) num_methods ++;
1995         if (eb->remove_method) num_methods ++;
1996         if (eb->raise_method) num_methods ++;
1997
1998         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1999         table->rows += num_methods;
2000         alloc_table (table, table->rows);
2001
2002         if (eb->add_method) {
2003                 semaidx = table->next_idx ++;
2004                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2005                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2006                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2007                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2008         }
2009         if (eb->remove_method) {
2010                 semaidx = table->next_idx ++;
2011                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2012                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2013                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2014                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2015         }
2016         if (eb->raise_method) {
2017                 semaidx = table->next_idx ++;
2018                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2019                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2020                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2021                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2022         }
2023 }
2024
2025 static void
2026 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2027 {
2028         MonoDynamicTable *table;
2029         guint32 num_constraints, i;
2030         guint32 *values;
2031         guint32 table_idx;
2032
2033         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2034         num_constraints = gparam->iface_constraints ?
2035                 mono_array_length (gparam->iface_constraints) : 0;
2036         table->rows += num_constraints;
2037         if (gparam->base_type)
2038                 table->rows++;
2039         alloc_table (table, table->rows);
2040
2041         if (gparam->base_type) {
2042                 table_idx = table->next_idx ++;
2043                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2044
2045                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2046                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2047                         assembly, gparam->base_type->type);
2048         }
2049
2050         for (i = 0; i < num_constraints; i++) {
2051                 MonoReflectionType *constraint = mono_array_get (
2052                         gparam->iface_constraints, gpointer, i);
2053
2054                 table_idx = table->next_idx ++;
2055                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2056
2057                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2058                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2059                         assembly, constraint->type);
2060         }
2061 }
2062
2063 static void
2064 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2065 {
2066         GenericParamTableEntry *entry;
2067
2068         /*
2069          * The GenericParam table must be sorted according to the `owner' field.
2070          * We need to do this sorting prior to writing the GenericParamConstraint
2071          * table, since we have to use the final GenericParam table indices there
2072          * and they must also be sorted.
2073          */
2074
2075         entry = g_new0 (GenericParamTableEntry, 1);
2076         entry->owner = owner;
2077         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2078         MOVING_GC_REGISTER (&entry->gparam);
2079         entry->gparam = gparam;
2080
2081         g_ptr_array_add (assembly->gen_params, entry);
2082 }
2083
2084 static void
2085 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2086 {
2087         MonoDynamicTable *table;
2088         MonoGenericParam *param;
2089         guint32 *values;
2090         guint32 table_idx;
2091
2092         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2093         table_idx = table->next_idx ++;
2094         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2095
2096         param = entry->gparam->type.type->data.generic_param;
2097
2098         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2099         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2100         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2101         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2102
2103         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2104
2105         encode_constraints (entry->gparam, table_idx, assembly);
2106 }
2107
2108 static guint32
2109 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2110 {
2111         MonoDynamicTable *table;
2112         guint32 token;
2113         guint32 *values;
2114         guint32 cols [MONO_ASSEMBLY_SIZE];
2115         const char *pubkey;
2116         guint32 publen;
2117
2118         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2119                 return token;
2120
2121         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2122                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2123                 token = table->next_idx ++;
2124                 table->rows ++;
2125                 alloc_table (table, table->rows);
2126                 values = table->values + token * MONO_MODULEREF_SIZE;
2127                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2128
2129                 token <<= MONO_RESOLTION_SCOPE_BITS;
2130                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2131                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2132
2133                 return token;
2134         }
2135         
2136         if (image->assembly->dynamic)
2137                 /* FIXME: */
2138                 memset (cols, 0, sizeof (cols));
2139         else {
2140                 /* image->assembly->image is the manifest module */
2141                 image = image->assembly->image;
2142                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2143         }
2144
2145         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2146         token = table->next_idx ++;
2147         table->rows ++;
2148         alloc_table (table, table->rows);
2149         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2150         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2151         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2152         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2153         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2154         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2155         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2156         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2157         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2158
2159         if (strcmp ("", image->assembly->aname.culture)) {
2160                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2161                                 image->assembly->aname.culture);
2162         }
2163
2164         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2165                 guchar pubtoken [9];
2166                 pubtoken [0] = 8;
2167                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2168                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2169         } else {
2170                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2171         }
2172         token <<= MONO_RESOLTION_SCOPE_BITS;
2173         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2174         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2175         return token;
2176 }
2177
2178 static guint32
2179 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2180 {
2181         MonoDynamicTable *table;
2182         guint32 *values;
2183         guint32 token;
2184         SigBuffer buf;
2185
2186         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2187                 return token;
2188
2189         sigbuffer_init (&buf, 32);
2190         switch (type->type) {
2191         case MONO_TYPE_FNPTR:
2192         case MONO_TYPE_PTR:
2193         case MONO_TYPE_SZARRAY:
2194         case MONO_TYPE_ARRAY:
2195         case MONO_TYPE_VAR:
2196         case MONO_TYPE_MVAR:
2197         case MONO_TYPE_GENERICINST:
2198                 encode_type (assembly, type, &buf);
2199                 break;
2200         case MONO_TYPE_CLASS:
2201         case MONO_TYPE_VALUETYPE: {
2202                 MonoClass *k = mono_class_from_mono_type (type);
2203                 if (!k || !k->generic_container) {
2204                         sigbuffer_free (&buf);
2205                         return 0;
2206                 }
2207                 encode_type (assembly, type, &buf);
2208                 break;
2209         }
2210         default:
2211                 sigbuffer_free (&buf);
2212                 return 0;
2213         }
2214
2215         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2216         if (assembly->save) {
2217                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2218                 alloc_table (table, table->rows + 1);
2219                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2220                 values [MONO_TYPESPEC_SIGNATURE] = token;
2221         }
2222         sigbuffer_free (&buf);
2223
2224         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2225         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2226         table->next_idx ++;
2227         return token;
2228 }
2229
2230 static guint32
2231 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2232 {
2233         MonoDynamicTable *table;
2234         guint32 *values;
2235         guint32 token, scope, enclosing;
2236         MonoClass *klass;
2237
2238         /* if the type requires a typespec, we must try that first*/
2239         if (try_typespec && (token = create_typespec (assembly, type)))
2240                 return token;
2241         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2242         if (token)
2243                 return token;
2244         klass = mono_class_from_mono_type (type);
2245         if (!klass)
2246                 klass = mono_class_from_mono_type (type);
2247
2248         /*
2249          * If it's in the same module and not a generic type parameter:
2250          */
2251         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2252                         (type->type != MONO_TYPE_MVAR)) {
2253                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2254                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2255                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2256                 return token;
2257         }
2258
2259         if (klass->nested_in) {
2260                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2261                 /* get the typeref idx of the enclosing type */
2262                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2263                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2264         } else {
2265                 scope = resolution_scope_from_image (assembly, klass->image);
2266         }
2267         table = &assembly->tables [MONO_TABLE_TYPEREF];
2268         if (assembly->save) {
2269                 alloc_table (table, table->rows + 1);
2270                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2271                 values [MONO_TYPEREF_SCOPE] = scope;
2272                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2273                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2274         }
2275         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2276         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2277         table->next_idx ++;
2278         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2279         return token;
2280 }
2281
2282 /*
2283  * Despite the name, we handle also TypeSpec (with the above helper).
2284  */
2285 static guint32
2286 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2287 {
2288         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2289 }
2290
2291 /*
2292  * Insert a memberef row into the metadata: the token that point to the memberref
2293  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2294  * mono_image_get_fieldref_token()).
2295  * The sig param is an index to an already built signature.
2296  */
2297 static guint32
2298 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2299 {
2300         MonoDynamicTable *table;
2301         guint32 *values;
2302         guint32 token, pclass;
2303         guint32 parent;
2304
2305         parent = mono_image_typedef_or_ref (assembly, type);
2306         switch (parent & MONO_TYPEDEFORREF_MASK) {
2307         case MONO_TYPEDEFORREF_TYPEREF:
2308                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2309                 break;
2310         case MONO_TYPEDEFORREF_TYPESPEC:
2311                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2312                 break;
2313         case MONO_TYPEDEFORREF_TYPEDEF:
2314                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2315                 break;
2316         default:
2317                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2318                 return 0;
2319         }
2320         /* extract the index */
2321         parent >>= MONO_TYPEDEFORREF_BITS;
2322
2323         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2324
2325         if (assembly->save) {
2326                 alloc_table (table, table->rows + 1);
2327                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2328                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2329                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2330                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2331         }
2332
2333         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2334         table->next_idx ++;
2335
2336         return token;
2337 }
2338
2339 static guint32
2340 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2341 {
2342         guint32 token;
2343         MonoMethodSignature *sig;
2344         
2345         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2346
2347         if (create_typespec) {
2348                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2349                 if (token)
2350                         return token;
2351         } 
2352
2353         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2354         if (token && !create_typespec)
2355                 return token;
2356
2357         g_assert (!method->is_inflated);
2358         if (!token) {
2359                 /*
2360                  * A methodref signature can't contain an unmanaged calling convention.
2361                  */
2362                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2363                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2364                         sig->call_convention = MONO_CALL_DEFAULT;
2365                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2366                         method->name,  method_encode_signature (assembly, sig));
2367                 g_free (sig);
2368                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2369         }
2370
2371         if (create_typespec) {
2372                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2373                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2374                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2375
2376                 if (assembly->save) {
2377                         guint32 *values;
2378
2379                         alloc_table (table, table->rows + 1);
2380                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2381                         values [MONO_METHODSPEC_METHOD] = token;
2382                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2383                 }
2384
2385                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2386                 table->next_idx ++;
2387                 /*methodspec and memberef tokens are diferent, */
2388                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2389                 return token;
2390         }
2391         return token;
2392 }
2393
2394 static guint32
2395 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2396 {
2397         guint32 token;
2398         ReflectionMethodBuilder rmb;
2399         char *name;
2400         
2401         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2402         if (token)
2403                 return token;
2404
2405         name = mono_string_to_utf8 (method->name);
2406         reflection_methodbuilder_from_method_builder (&rmb, method);
2407
2408         /*
2409          * A methodref signature can't contain an unmanaged calling convention.
2410          * Since some flags are encoded as part of call_conv, we need to check against it.
2411         */
2412         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2413                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2414         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2415                                         name, method_builder_encode_signature (assembly, &rmb));
2416
2417         g_free (name);
2418         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2419         return token;
2420 }
2421
2422 static guint32
2423 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2424                                      const gchar *name, guint32 sig)
2425 {
2426         MonoDynamicTable *table;
2427         guint32 token;
2428         guint32 *values;
2429         
2430         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2431
2432         if (assembly->save) {
2433                 alloc_table (table, table->rows + 1);
2434                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2435                 values [MONO_MEMBERREF_CLASS] = original;
2436                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2437                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2438         }
2439
2440         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2441         table->next_idx ++;
2442
2443         return token;
2444 }
2445
2446 static guint32
2447 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2448 {
2449         SigBuffer buf;
2450         int i;
2451         guint32 nparams = mono_array_length (mb->generic_params);
2452         guint32 idx;
2453
2454         if (!assembly->save)
2455                 return 0;
2456
2457         sigbuffer_init (&buf, 32);
2458
2459         sigbuffer_add_value (&buf, 0xa);
2460         sigbuffer_add_value (&buf, nparams);
2461
2462         for (i = 0; i < nparams; i++) {
2463                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2464                 sigbuffer_add_value (&buf, i);
2465         }
2466
2467         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2468         sigbuffer_free (&buf);
2469         return idx;
2470 }
2471
2472 static guint32
2473 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2474 {
2475         MonoDynamicTable *table;
2476         guint32 *values;
2477         guint32 token, mtoken = 0;
2478
2479         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2480         if (token)
2481                 return token;
2482
2483         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2484
2485         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2486         switch (mono_metadata_token_table (mtoken)) {
2487         case MONO_TABLE_MEMBERREF:
2488                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2489                 break;
2490         case MONO_TABLE_METHOD:
2491                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2492                 break;
2493         default:
2494                 g_assert_not_reached ();
2495         }
2496
2497         if (assembly->save) {
2498                 alloc_table (table, table->rows + 1);
2499                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2500                 values [MONO_METHODSPEC_METHOD] = mtoken;
2501                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2502         }
2503
2504         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2505         table->next_idx ++;
2506
2507         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2508         return token;
2509 }
2510
2511 static guint32
2512 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2513 {
2514         guint32 token;
2515         
2516         if (mb->generic_params && create_methodspec) 
2517                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2518
2519         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2520         if (token)
2521                 return token;
2522
2523         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2524         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2525         return token;
2526 }
2527
2528 static guint32
2529 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2530 {
2531         guint32 token;
2532         ReflectionMethodBuilder rmb;
2533         char *name;
2534         
2535         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2536         if (token)
2537                 return token;
2538
2539         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2540
2541         name = mono_string_to_utf8 (rmb.name);
2542         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2543                 name, method_builder_encode_signature (assembly, &rmb));
2544
2545         g_free (name);
2546         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2547         return token;
2548 }
2549
2550 static gboolean
2551 is_field_on_inst (MonoClassField *field)
2552 {
2553         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2554 }
2555
2556 /*
2557  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2558  */
2559 static MonoType*
2560 get_field_on_inst_generic_type (MonoClassField *field)
2561 {
2562         MonoDynamicGenericClass *dgclass;
2563         int field_index;
2564
2565         g_assert (is_field_on_inst (field));
2566
2567         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2568         field_index = field - dgclass->fields;
2569
2570         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2571         return dgclass->field_generic_types [field_index];
2572 }
2573
2574 static guint32
2575 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2576 {
2577         MonoType *type;
2578         guint32 token;
2579         MonoClassField *field;
2580
2581         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2582         if (token)
2583                 return token;
2584         g_assert (f->field->parent);
2585
2586         field = f->field;
2587         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2588                 int index = field - field->parent->fields;
2589                 type = field->parent->generic_class->container_class->fields [index].type;
2590         } else {
2591                 if (is_field_on_inst (f->field))
2592                         type = get_field_on_inst_generic_type (f->field);
2593                 else
2594                         type = f->field->type;
2595         }
2596         token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg, 
2597                                                                                         mono_field_get_name (f->field),  
2598                                                                                         fieldref_encode_signature (assembly, type));
2599         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2600         return token;
2601 }
2602
2603 static guint32
2604 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2605 {
2606         guint32 token;
2607         MonoClass *klass;
2608         MonoGenericClass *gclass;
2609         MonoDynamicGenericClass *dgclass;
2610         MonoReflectionFieldBuilder *fb = f->fb;
2611         char *name;
2612
2613         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2614         if (token)
2615                 return token;
2616         klass = mono_class_from_mono_type (f->inst->type.type);
2617         gclass = f->inst->type.type->data.generic_class;
2618         g_assert (gclass->is_dynamic);
2619         dgclass = (MonoDynamicGenericClass *) gclass;
2620
2621         name = mono_string_to_utf8 (fb->name);
2622         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2623                                                                                         field_encode_signature (assembly, fb));
2624         g_free (name);
2625         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2626         return token;
2627 }
2628
2629 static guint32
2630 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2631 {
2632         guint32 sig, token;
2633         MonoClass *klass;
2634         MonoGenericClass *gclass;
2635         MonoDynamicGenericClass *dgclass;
2636         MonoReflectionCtorBuilder *cb = c->cb;
2637         ReflectionMethodBuilder rmb;
2638         char *name;
2639
2640         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2641
2642         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2643         if (token)
2644                 return token;
2645         klass = mono_class_from_mono_type (c->inst->type.type);
2646         gclass = c->inst->type.type->data.generic_class;
2647         g_assert (gclass->is_dynamic);
2648         dgclass = (MonoDynamicGenericClass *) gclass;
2649
2650         reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2651
2652         name = mono_string_to_utf8 (rmb.name);
2653
2654         sig = method_builder_encode_signature (assembly, &rmb);
2655
2656         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2657         g_free (name);
2658
2659         g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2660         return token;
2661 }
2662
2663 static guint32
2664 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2665 {
2666         guint32 sig, token;
2667         MonoClass *klass;
2668         MonoGenericClass *gclass;
2669         MonoReflectionMethodBuilder *mb = m->mb;
2670         ReflectionMethodBuilder rmb;
2671         char *name;
2672
2673         if (create_methodspec && mb->generic_params)
2674                 // FIXME:
2675                 g_assert_not_reached ();
2676
2677         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2678         if (token)
2679                 return token;
2680         klass = mono_class_from_mono_type (m->inst->type.type);
2681         gclass = m->inst->type.type->data.generic_class;
2682         g_assert (gclass->is_dynamic);
2683
2684         reflection_methodbuilder_from_method_builder (&rmb, mb);
2685
2686         name = mono_string_to_utf8 (rmb.name);
2687
2688         sig = method_builder_encode_signature (assembly, &rmb);
2689
2690         token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2691         g_free (name);
2692
2693         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2694         return token;
2695 }
2696
2697 static guint32
2698 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2699 {
2700         SigBuffer buf;
2701         int i;
2702         guint32 nparams = context->method_inst->type_argc;
2703         guint32 idx;
2704
2705         if (!assembly->save)
2706                 return 0;
2707
2708         sigbuffer_init (&buf, 32);
2709         /*
2710          * FIXME: vararg, explicit_this, differenc call_conv values...
2711          */
2712         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2713         sigbuffer_add_value (&buf, nparams);
2714
2715         for (i = 0; i < nparams; i++)
2716                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2717
2718         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2719         sigbuffer_free (&buf);
2720         return idx;
2721 }
2722
2723 static guint32
2724 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2725 {
2726         MonoDynamicTable *table;
2727         guint32 *values;
2728         guint32 token, mtoken = 0, sig;
2729         MonoMethodInflated *imethod;
2730         MonoMethod *declaring;
2731
2732         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2733
2734         g_assert (method->is_inflated);
2735         imethod = (MonoMethodInflated *) method;
2736         declaring = imethod->declaring;
2737
2738         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2739         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2740
2741         if (!mono_method_signature (declaring)->generic_param_count)
2742                 return mtoken;
2743
2744         switch (mono_metadata_token_table (mtoken)) {
2745         case MONO_TABLE_MEMBERREF:
2746                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2747                 break;
2748         case MONO_TABLE_METHOD:
2749                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2750                 break;
2751         default:
2752                 g_assert_not_reached ();
2753         }
2754
2755         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2756
2757         if (assembly->save) {
2758                 alloc_table (table, table->rows + 1);
2759                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2760                 values [MONO_METHODSPEC_METHOD] = mtoken;
2761                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2762         }
2763
2764         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2765         table->next_idx ++;
2766
2767         return token;
2768 }
2769
2770 static guint32
2771 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2772 {
2773         MonoMethodInflated *imethod;
2774         guint32 token;
2775         
2776         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2777         if (token)
2778                 return token;
2779
2780         g_assert (method->is_inflated);
2781         imethod = (MonoMethodInflated *) method;
2782
2783         if (mono_method_signature (imethod->declaring)->generic_param_count) {
2784                 token = method_encode_methodspec (assembly, method);
2785         } else {
2786                 guint32 sig = method_encode_signature (
2787                         assembly, mono_method_signature (imethod->declaring));
2788                 token = mono_image_get_memberref_token (
2789                         assembly, &method->klass->byval_arg, method->name, sig);
2790         }
2791
2792         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2793         return token;
2794 }
2795
2796 static guint32
2797 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2798 {
2799         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2800         guint32 sig, token;
2801
2802         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2803         token = mono_image_get_memberref_token (
2804                 assembly, &m->klass->byval_arg, m->name, sig);
2805
2806         return token;
2807 }
2808
2809 static guint32
2810 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2811 {
2812         MonoDynamicTable *table;
2813         MonoClass *klass;
2814         guint32 *values;
2815         guint32 token;
2816         SigBuffer buf;
2817         int count, i;
2818
2819         /*
2820          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2821          * ie. what we'd normally use as the generic type in a TypeSpec signature.
2822          * Because of this, we must not insert it into the `typeref' hash table.
2823          */
2824
2825         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2826         if (token)
2827                 return token;
2828
2829         sigbuffer_init (&buf, 32);
2830
2831         g_assert (tb->generic_params);
2832         klass = mono_class_from_mono_type (tb->type.type);
2833
2834         if (tb->generic_container)
2835                 mono_reflection_create_generic_class (tb);
2836
2837         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2838         g_assert (klass->generic_container);
2839         sigbuffer_add_value (&buf, klass->byval_arg.type);
2840         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2841
2842         count = mono_array_length (tb->generic_params);
2843         sigbuffer_add_value (&buf, count);
2844         for (i = 0; i < count; i++) {
2845                 MonoReflectionGenericParam *gparam;
2846
2847                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2848
2849                 encode_type (assembly, gparam->type.type, &buf);
2850         }
2851
2852         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2853
2854         if (assembly->save) {
2855                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2856                 alloc_table (table, table->rows + 1);
2857                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2858                 values [MONO_TYPESPEC_SIGNATURE] = token;
2859         }
2860         sigbuffer_free (&buf);
2861
2862         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2863         g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2864         table->next_idx ++;
2865         return token;
2866 }
2867
2868 /*
2869  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2870  */
2871 static MonoType*
2872 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2873 {
2874         int i, count, len, pos;
2875         MonoType *t;
2876
2877         count = 0;
2878         if (modreq)
2879                 count += mono_array_length (modreq);
2880         if (modopt)
2881                 count += mono_array_length (modopt);
2882
2883         if (count == 0)
2884                 return mono_metadata_type_dup (NULL, type);
2885
2886         len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2887         t = g_malloc (len);
2888         memcpy (t, type, len);
2889
2890         t->num_mods = count;
2891         pos = 0;
2892         if (modreq) {
2893                 for (i = 0; i < mono_array_length (modreq); ++i) {
2894                         MonoReflectionType *mod = mono_type_array_get (modreq, i);
2895                         t->modifiers [pos].required = 1;
2896                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2897                         pos ++;
2898                 }
2899         }
2900         if (modopt) {
2901                 for (i = 0; i < mono_array_length (modopt); ++i) {
2902                         MonoReflectionType *mod = mono_type_array_get (modopt, i);
2903                         t->modifiers [pos].required = 0;
2904                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2905                         pos ++;
2906                 }
2907         }
2908
2909         return t;
2910 }
2911
2912 static guint32
2913 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2914 {
2915         MonoDynamicTable *table;
2916         MonoClass *klass;
2917         MonoType *custom = NULL;
2918         guint32 *values;
2919         guint32 token, pclass, parent, sig;
2920         gchar *name;
2921
2922         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2923         if (token)
2924                 return token;
2925
2926         klass = mono_class_from_mono_type (fb->typeb->type);
2927         name = mono_string_to_utf8 (fb->name);
2928
2929         /* fb->type does not include the custom modifiers */
2930         /* FIXME: We should do this in one place when a fieldbuilder is created */
2931         if (fb->modreq || fb->modopt) {
2932                 custom = add_custom_modifiers (assembly, monotype_cast (fb->type)->type, fb->modreq, fb->modopt);
2933                 sig = fieldref_encode_signature (assembly, custom);
2934                 g_free (custom);
2935         } else {
2936                 sig = fieldref_encode_signature (assembly, monotype_cast (fb->type)->type);
2937         }
2938
2939         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2940         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2941         
2942         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2943         parent >>= MONO_TYPEDEFORREF_BITS;
2944
2945         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2946
2947         if (assembly->save) {
2948                 alloc_table (table, table->rows + 1);
2949                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2950                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2951                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2952                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2953         }
2954
2955         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2956         table->next_idx ++;
2957         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2958         g_free (name);
2959         return token;
2960 }
2961
2962 static guint32
2963 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2964 {
2965         SigBuffer buf;
2966         guint32 nargs;
2967         guint32 size;
2968         guint32 i, idx;
2969
2970         if (!assembly->save)
2971                 return 0;
2972
2973         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2974         g_assert (helper->type == 2);
2975
2976         if (helper->arguments)
2977                 nargs = mono_array_length (helper->arguments);
2978         else
2979                 nargs = 0;
2980
2981         size = 10 + (nargs * 10);
2982         
2983         sigbuffer_init (&buf, 32);
2984
2985         /* Encode calling convention */
2986         /* Change Any to Standard */
2987         if ((helper->call_conv & 0x03) == 0x03)
2988                 helper->call_conv = 0x01;
2989         /* explicit_this implies has_this */
2990         if (helper->call_conv & 0x40)
2991                 helper->call_conv &= 0x20;
2992
2993         if (helper->call_conv == 0) { /* Unmanaged */
2994                 idx = helper->unmanaged_call_conv - 1;
2995         } else {
2996                 /* Managed */
2997                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2998                 if (helper->call_conv & 0x02) /* varargs */
2999                         idx += 0x05;
3000         }
3001
3002         sigbuffer_add_byte (&buf, idx);
3003         sigbuffer_add_value (&buf, nargs);
3004         encode_reflection_type (assembly, helper->return_type, &buf);
3005         for (i = 0; i < nargs; ++i) {
3006                 MonoArray *modreqs = NULL;
3007                 MonoArray *modopts = NULL;
3008                 MonoReflectionType *pt;
3009
3010                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3011                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3012                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3013                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3014
3015                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3016                 pt = mono_type_array_get (helper->arguments, i);
3017                 encode_reflection_type (assembly, pt, &buf);
3018         }
3019         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3020         sigbuffer_free (&buf);
3021
3022         return idx;
3023 }
3024         
3025 static guint32 
3026 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3027 {
3028         guint32 idx;
3029         MonoDynamicTable *table;
3030         guint32 *values;
3031
3032         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3033         idx = table->next_idx ++;
3034         table->rows ++;
3035         alloc_table (table, table->rows);
3036         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3037
3038         values [MONO_STAND_ALONE_SIGNATURE] =
3039                 mono_reflection_encode_sighelper (assembly, helper);
3040
3041         return idx;
3042 }
3043
3044 static int
3045 reflection_cc_to_file (int call_conv) {
3046         switch (call_conv & 0x3) {
3047         case 0:
3048         case 1: return MONO_CALL_DEFAULT;
3049         case 2: return MONO_CALL_VARARG;
3050         default:
3051                 g_assert_not_reached ();
3052         }
3053         return 0;
3054 }
3055
3056 typedef struct {
3057         MonoType *parent;
3058         MonoMethodSignature *sig;
3059         char *name;
3060         guint32 token;
3061 } ArrayMethod;
3062
3063 static guint32
3064 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3065 {
3066         guint32 nparams, i;
3067         GList *tmp;
3068         char *name;
3069         MonoMethodSignature *sig;
3070         ArrayMethod *am;
3071         
3072         name = mono_string_to_utf8 (m->name);
3073         nparams = mono_array_length (m->parameters);
3074         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3075         sig->hasthis = 1;
3076         sig->sentinelpos = -1;
3077         sig->call_convention = reflection_cc_to_file (m->call_conv);
3078         sig->param_count = nparams;
3079         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3080         for (i = 0; i < nparams; ++i) {
3081                 MonoReflectionType *t = mono_type_array_get (m->parameters, i);
3082                 sig->params [i] = t->type;
3083         }
3084
3085         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3086                 am = tmp->data;
3087                 if (strcmp (name, am->name) == 0 && 
3088                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
3089                                 mono_metadata_signature_equal (am->sig, sig)) {
3090                         g_free (name);
3091                         g_free (sig);
3092                         m->table_idx = am->token & 0xffffff;
3093                         return am->token;
3094                 }
3095         }
3096         am = g_new0 (ArrayMethod, 1);
3097         am->name = name;
3098         am->sig = sig;
3099         am->parent = m->parent->type;
3100         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3101                 method_encode_signature (assembly, sig));
3102         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3103         m->table_idx = am->token & 0xffffff;
3104         return am->token;
3105 }
3106
3107 /*
3108  * Insert into the metadata tables all the info about the TypeBuilder tb.
3109  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3110  */
3111 static void
3112 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3113 {
3114         MonoDynamicTable *table;
3115         guint *values;
3116         int i, is_object = 0, is_system = 0;
3117         char *n;
3118
3119         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3120         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3121         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3122         n = mono_string_to_utf8 (tb->name);
3123         if (strcmp (n, "Object") == 0)
3124                 is_object++;
3125         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3126         g_free (n);
3127         n = mono_string_to_utf8 (tb->nspace);
3128         if (strcmp (n, "System") == 0)
3129                 is_system++;
3130         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3131         g_free (n);
3132         if (tb->parent && !(is_system && is_object) && 
3133                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3134                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, monotype_cast (tb->parent)->type);
3135         } else {
3136                 values [MONO_TYPEDEF_EXTENDS] = 0;
3137         }
3138         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3139         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3140
3141         /*
3142          * if we have explicitlayout or sequentiallayouts, output data in the
3143          * ClassLayout table.
3144          */
3145         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3146                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3147                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3148                 table->rows++;
3149                 alloc_table (table, table->rows);
3150                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3151                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3152                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3153                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3154         }
3155
3156         /* handle interfaces */
3157         if (tb->interfaces) {
3158                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3159                 i = table->rows;
3160                 table->rows += mono_array_length (tb->interfaces);
3161                 alloc_table (table, table->rows);
3162                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3163                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3164                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3165                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3166                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3167                         values += MONO_INTERFACEIMPL_SIZE;
3168                 }
3169         }
3170
3171         /* handle fields */
3172         if (tb->fields) {
3173                 table = &assembly->tables [MONO_TABLE_FIELD];
3174                 table->rows += tb->num_fields;
3175                 alloc_table (table, table->rows);
3176                 for (i = 0; i < tb->num_fields; ++i)
3177                         mono_image_get_field_info (
3178                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3179         }
3180
3181         /* handle constructors */
3182         if (tb->ctors) {
3183                 table = &assembly->tables [MONO_TABLE_METHOD];
3184                 table->rows += mono_array_length (tb->ctors);
3185                 alloc_table (table, table->rows);
3186                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3187                         mono_image_get_ctor_info (domain,
3188                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3189         }
3190
3191         /* handle methods */
3192         if (tb->methods) {
3193                 table = &assembly->tables [MONO_TABLE_METHOD];
3194                 table->rows += tb->num_methods;
3195                 alloc_table (table, table->rows);
3196                 for (i = 0; i < tb->num_methods; ++i)
3197                         mono_image_get_method_info (
3198                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3199         }
3200
3201         /* Do the same with properties etc.. */
3202         if (tb->events && mono_array_length (tb->events)) {
3203                 table = &assembly->tables [MONO_TABLE_EVENT];
3204                 table->rows += mono_array_length (tb->events);
3205                 alloc_table (table, table->rows);
3206                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3207                 table->rows ++;
3208                 alloc_table (table, table->rows);
3209                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3210                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3211                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3212                 for (i = 0; i < mono_array_length (tb->events); ++i)
3213                         mono_image_get_event_info (
3214                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3215         }
3216         if (tb->properties && mono_array_length (tb->properties)) {
3217                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3218                 table->rows += mono_array_length (tb->properties);
3219                 alloc_table (table, table->rows);
3220                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3221                 table->rows ++;
3222                 alloc_table (table, table->rows);
3223                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3224                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3225                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3226                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3227                         mono_image_get_property_info (
3228                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3229         }
3230
3231         /* handle generic parameters */
3232         if (tb->generic_params) {
3233                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3234                 table->rows += mono_array_length (tb->generic_params);
3235                 alloc_table (table, table->rows);
3236                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3237                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3238
3239                         mono_image_get_generic_param_info (
3240                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3241                 }
3242         }
3243
3244         mono_image_add_decl_security (assembly, 
3245                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3246
3247         if (tb->subtypes) {
3248                 MonoDynamicTable *ntable;
3249                 
3250                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3251                 ntable->rows += mono_array_length (tb->subtypes);
3252                 alloc_table (ntable, ntable->rows);
3253                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3254
3255                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3256                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3257
3258                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3259                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3260                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3261                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3262                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3263                                 ntable->next_idx, ntable->rows);*/
3264                         values += MONO_NESTED_CLASS_SIZE;
3265                         ntable->next_idx++;
3266                 }
3267         }
3268 }
3269
3270 static void
3271 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3272 {
3273         int i;
3274
3275         g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3276
3277         if (!type->subtypes)
3278                 return;
3279
3280         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3281                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3282                 collect_types (types, subtype);
3283         }
3284 }
3285
3286 static gint
3287 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3288 {
3289         if ((*type1)->table_idx < (*type2)->table_idx)
3290                 return -1;
3291         else
3292                 if ((*type1)->table_idx > (*type2)->table_idx)
3293                         return 1;
3294         else
3295                 return 0;
3296 }
3297
3298 static void
3299 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3300         int i;
3301
3302         if (!pinfo)
3303                 return;
3304         for (i = 0; i < mono_array_length (pinfo); ++i) {
3305                 MonoReflectionParamBuilder *pb;
3306                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3307                 if (!pb)
3308                         continue;
3309                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3310         }
3311 }
3312
3313 static void
3314 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3315         int i;
3316         
3317         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3318         if (tb->fields) {
3319                 for (i = 0; i < tb->num_fields; ++i) {
3320                         MonoReflectionFieldBuilder* fb;
3321                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3322                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3323                 }
3324         }
3325         if (tb->events) {
3326                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3327                         MonoReflectionEventBuilder* eb;
3328                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3329                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3330                 }
3331         }
3332         if (tb->properties) {
3333                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3334                         MonoReflectionPropertyBuilder* pb;
3335                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3336                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3337                 }
3338         }
3339         if (tb->ctors) {
3340                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3341                         MonoReflectionCtorBuilder* cb;
3342                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3343                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3344                         params_add_cattrs (assembly, cb->pinfo);
3345                 }
3346         }
3347
3348         if (tb->methods) {
3349                 for (i = 0; i < tb->num_methods; ++i) {
3350                         MonoReflectionMethodBuilder* mb;
3351                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3352                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3353                         params_add_cattrs (assembly, mb->pinfo);
3354                 }
3355         }
3356
3357         if (tb->subtypes) {
3358                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3359                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3360         }
3361 }
3362
3363 static void
3364 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3365 {
3366         int i;
3367         
3368         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3369
3370         if (moduleb->global_methods) {
3371                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3372                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3373                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3374                         params_add_cattrs (assembly, mb->pinfo);
3375                 }
3376         }
3377
3378         if (moduleb->global_fields) {
3379                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3380                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3381                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3382                 }
3383         }
3384         
3385         if (moduleb->types) {
3386                 for (i = 0; i < moduleb->num_types; ++i)
3387                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3388         }
3389 }
3390
3391 static void
3392 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3393 {
3394         MonoDynamicTable *table;
3395         guint32 *values;
3396         char blob_size [6];
3397         guchar hash [20];
3398         char *b = blob_size;
3399         char *dir, *path;
3400
3401         table = &assembly->tables [MONO_TABLE_FILE];
3402         table->rows++;
3403         alloc_table (table, table->rows);
3404         values = table->values + table->next_idx * MONO_FILE_SIZE;
3405         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3406         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3407         if (module->image->dynamic) {
3408                 /* This depends on the fact that the main module is emitted last */
3409                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3410                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3411         } else {
3412                 dir = NULL;
3413                 path = g_strdup (module->image->name);
3414         }
3415         mono_sha1_get_digest_from_file (path, hash);
3416         g_free (dir);
3417         g_free (path);
3418         mono_metadata_encode_value (20, b, &b);
3419         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3420         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3421         table->next_idx ++;
3422 }
3423
3424 static void
3425 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3426 {
3427         MonoDynamicTable *table;
3428         int i;
3429
3430         table = &assembly->tables [MONO_TABLE_MODULE];
3431         mb->table_idx = table->next_idx ++;
3432         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3433         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3434         i /= 16;
3435         ++i;
3436         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3437         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3438         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3439         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3440 }
3441
3442 static guint32
3443 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3444         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3445 {
3446         MonoDynamicTable *table;
3447         guint32 *values;
3448         guint32 visib, res;
3449
3450         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3451         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3452                 return 0;
3453
3454         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3455         table->rows++;
3456         alloc_table (table, table->rows);
3457         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3458
3459         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3460         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3461         if (klass->nested_in)
3462                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3463         else
3464                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3465         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3466         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3467
3468         res = table->next_idx;
3469
3470         table->next_idx ++;
3471
3472         /* Emit nested types */
3473         if (klass->ext && klass->ext->nested_classes) {
3474                 GList *tmp;
3475
3476                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3477                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3478         }
3479
3480         return res;
3481 }
3482
3483 static void
3484 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3485         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3486 {
3487         MonoClass *klass;
3488         guint32 idx, i;
3489
3490         klass = mono_class_from_mono_type (tb->type.type);
3491
3492         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3493
3494         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3495                                                                                                    parent_index, assembly);
3496
3497         /* 
3498          * Emit nested types
3499          * We need to do this ourselves since klass->nested_classes is not set up.
3500          */
3501         if (tb->subtypes) {
3502                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3503                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3504         }
3505 }
3506
3507 static void
3508 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3509         guint32 module_index, MonoDynamicImage *assembly)
3510 {
3511         MonoImage *image = module->image;
3512         MonoTableInfo  *t;
3513         guint32 i;
3514
3515         t = &image->tables [MONO_TABLE_TYPEDEF];
3516
3517         for (i = 0; i < t->rows; ++i) {
3518                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3519
3520                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3521                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3522         }
3523 }
3524
3525 static void
3526 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3527 {
3528         MonoDynamicTable *table;
3529         MonoClass *klass;
3530         guint32 *values;
3531         guint32 scope, idx;
3532         int i;
3533
3534         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3535
3536         if (assemblyb->type_forwarders) {
3537                 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3538                         MonoReflectionType *t = mono_type_array_get (assemblyb->type_forwarders, i);
3539                         if (!t)
3540                                 continue;
3541
3542                         g_assert (t->type);
3543
3544                         klass = mono_class_from_mono_type (t->type);
3545
3546                         scope = resolution_scope_from_image (assembly, klass->image);
3547                         g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3548                         idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3549
3550                         table->rows++;
3551                         alloc_table (table, table->rows);
3552                         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3553
3554                         values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3555                         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3556                         values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3557                         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3558                         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3559
3560                         table->next_idx++;
3561                 }
3562         }
3563 }
3564
3565 #define align_pointer(base,p)\
3566         do {\
3567                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3568                 if (__diff & 3)\
3569                         (p) += 4 - (__diff & 3);\
3570         } while (0)
3571
3572 static int
3573 compare_constants (const void *a, const void *b)
3574 {
3575         const guint32 *a_values = a;
3576         const guint32 *b_values = b;
3577         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3578 }
3579
3580 static int
3581 compare_semantics (const void *a, const void *b)
3582 {
3583         const guint32 *a_values = a;
3584         const guint32 *b_values = b;
3585         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3586         if (assoc)
3587                 return assoc;
3588         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3589 }
3590
3591 static int
3592 compare_custom_attrs (const void *a, const void *b)
3593 {
3594         const guint32 *a_values = a;
3595         const guint32 *b_values = b;
3596
3597         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3598 }
3599
3600 static int
3601 compare_field_marshal (const void *a, const void *b)
3602 {
3603         const guint32 *a_values = a;
3604         const guint32 *b_values = b;
3605
3606         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3607 }
3608
3609 static int
3610 compare_nested (const void *a, const void *b)
3611 {
3612         const guint32 *a_values = a;
3613         const guint32 *b_values = b;
3614
3615         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3616 }
3617
3618 static int
3619 compare_genericparam (const void *a, const void *b)
3620 {
3621         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3622         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3623
3624         if ((*b_entry)->owner == (*a_entry)->owner)
3625                 return 
3626                         mono_type_get_generic_param_num ((*a_entry)->gparam->type.type) -
3627                         mono_type_get_generic_param_num ((*b_entry)->gparam->type.type);
3628         else
3629                 return (*a_entry)->owner - (*b_entry)->owner;
3630 }
3631
3632 static int
3633 compare_declsecurity_attrs (const void *a, const void *b)
3634 {
3635         const guint32 *a_values = a;
3636         const guint32 *b_values = b;
3637
3638         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3639 }
3640
3641 static int
3642 compare_interface_impl (const void *a, const void *b)
3643 {
3644         const guint32 *a_values = a;
3645         const guint32 *b_values = b;
3646
3647         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3648         if (klass)
3649                 return klass;
3650
3651         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3652 }
3653
3654 static void
3655 pad_heap (MonoDynamicStream *sh)
3656 {
3657         if (sh->index & 3) {
3658                 int sz = 4 - (sh->index & 3);
3659                 memset (sh->data + sh->index, 0, sz);
3660                 sh->index += sz;
3661         }
3662 }
3663
3664 struct StreamDesc {
3665         const char *name;
3666         MonoDynamicStream *stream;
3667 };
3668
3669 /*
3670  * build_compressed_metadata() fills in the blob of data that represents the 
3671  * raw metadata as it will be saved in the PE file. The five streams are output 
3672  * and the metadata tables are comnpressed from the guint32 array representation, 
3673  * to the compressed on-disk format.
3674  */
3675 static void
3676 build_compressed_metadata (MonoDynamicImage *assembly)
3677 {
3678         MonoDynamicTable *table;
3679         int i;
3680         guint64 valid_mask = 0;
3681         guint64 sorted_mask;
3682         guint32 heapt_size = 0;
3683         guint32 meta_size = 256; /* allow for header and other stuff */
3684         guint32 table_offset;
3685         guint32 ntables = 0;
3686         guint64 *int64val;
3687         guint32 *int32val;
3688         guint16 *int16val;
3689         MonoImage *meta;
3690         unsigned char *p;
3691         struct StreamDesc stream_desc [5];
3692
3693         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3694         for (i = 0; i < assembly->gen_params->len; i++){
3695                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3696                 write_generic_param_entry (assembly, entry);
3697         }
3698
3699         stream_desc [0].name  = "#~";
3700         stream_desc [0].stream = &assembly->tstream;
3701         stream_desc [1].name  = "#Strings";
3702         stream_desc [1].stream = &assembly->sheap;
3703         stream_desc [2].name  = "#US";
3704         stream_desc [2].stream = &assembly->us;
3705         stream_desc [3].name  = "#Blob";
3706         stream_desc [3].stream = &assembly->blob;
3707         stream_desc [4].name  = "#GUID";
3708         stream_desc [4].stream = &assembly->guid;
3709         
3710         /* tables that are sorted */
3711         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3712                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3713                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3714                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3715                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3716                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3717                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3718         
3719         /* Compute table sizes */
3720         /* the MonoImage has already been created in mono_image_basic_init() */
3721         meta = &assembly->image;
3722
3723         /* sizes should be multiple of 4 */
3724         pad_heap (&assembly->blob);
3725         pad_heap (&assembly->guid);
3726         pad_heap (&assembly->sheap);
3727         pad_heap (&assembly->us);
3728
3729         /* Setup the info used by compute_sizes () */
3730         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3731         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3732         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3733
3734         meta_size += assembly->blob.index;
3735         meta_size += assembly->guid.index;
3736         meta_size += assembly->sheap.index;
3737         meta_size += assembly->us.index;
3738
3739         for (i=0; i < MONO_TABLE_NUM; ++i)
3740                 meta->tables [i].rows = assembly->tables [i].rows;
3741         
3742         for (i = 0; i < MONO_TABLE_NUM; i++){
3743                 if (meta->tables [i].rows == 0)
3744                         continue;
3745                 valid_mask |= (guint64)1 << i;
3746                 ntables ++;
3747                 meta->tables [i].row_size = mono_metadata_compute_size (
3748                         meta, i, &meta->tables [i].size_bitfield);
3749                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3750         }
3751         heapt_size += 24; /* #~ header size */
3752         heapt_size += ntables * 4;
3753         /* make multiple of 4 */
3754         heapt_size += 3;
3755         heapt_size &= ~3;
3756         meta_size += heapt_size;
3757         meta->raw_metadata = g_malloc0 (meta_size);
3758         p = (unsigned char*)meta->raw_metadata;
3759         /* the metadata signature */
3760         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3761         /* version numbers and 4 bytes reserved */
3762         int16val = (guint16*)p;
3763         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3764         *int16val = GUINT16_TO_LE (meta->md_version_minor);
3765         p += 8;
3766         /* version string */
3767         int32val = (guint32*)p;
3768         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3769         p += 4;
3770         memcpy (p, meta->version, strlen (meta->version));
3771         p += GUINT32_FROM_LE (*int32val);
3772         align_pointer (meta->raw_metadata, p);
3773         int16val = (guint16*)p;
3774         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3775         *int16val = GUINT16_TO_LE (5); /* number of streams */
3776         p += 4;
3777
3778         /*
3779          * write the stream info.
3780          */
3781         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3782         table_offset += 3; table_offset &= ~3;
3783
3784         assembly->tstream.index = heapt_size;
3785         for (i = 0; i < 5; ++i) {
3786                 int32val = (guint32*)p;
3787                 stream_desc [i].stream->offset = table_offset;
3788                 *int32val++ = GUINT32_TO_LE (table_offset);
3789                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3790                 table_offset += GUINT32_FROM_LE (*int32val);
3791                 table_offset += 3; table_offset &= ~3;
3792                 p += 8;
3793                 strcpy ((char*)p, stream_desc [i].name);
3794                 p += strlen (stream_desc [i].name) + 1;
3795                 align_pointer (meta->raw_metadata, p);
3796         }
3797         /* 
3798          * now copy the data, the table stream header and contents goes first.
3799          */
3800         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3801         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3802         int32val = (guint32*)p;
3803         *int32val = GUINT32_TO_LE (0); /* reserved */
3804         p += 4;
3805
3806         if (mono_framework_version () > 1) {
3807                 *p++ = 2; /* version */
3808                 *p++ = 0;
3809         } else {
3810                 *p++ = 1; /* version */
3811                 *p++ = 0;
3812         }
3813
3814         if (meta->idx_string_wide)
3815                 *p |= 0x01;
3816         if (meta->idx_guid_wide)
3817                 *p |= 0x02;
3818         if (meta->idx_blob_wide)
3819                 *p |= 0x04;
3820         ++p;
3821         *p++ = 1; /* reserved */
3822         int64val = (guint64*)p;
3823         *int64val++ = GUINT64_TO_LE (valid_mask);
3824         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3825         p += 16;
3826         int32val = (guint32*)p;
3827         for (i = 0; i < MONO_TABLE_NUM; i++){
3828                 if (meta->tables [i].rows == 0)
3829                         continue;
3830                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3831         }
3832         p = (unsigned char*)int32val;
3833
3834         /* sort the tables that still need sorting */
3835         table = &assembly->tables [MONO_TABLE_CONSTANT];
3836         if (table->rows)
3837                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3838         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3839         if (table->rows)
3840                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3841         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3842         if (table->rows)
3843                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3844         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3845         if (table->rows)
3846                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3847         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3848         if (table->rows)
3849                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3850         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3851         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3852         if (table->rows)
3853                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3854         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3855         if (table->rows)
3856                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3857
3858         /* compress the tables */
3859         for (i = 0; i < MONO_TABLE_NUM; i++){
3860                 int row, col;
3861                 guint32 *values;
3862                 guint32 bitfield = meta->tables [i].size_bitfield;
3863                 if (!meta->tables [i].rows)
3864                         continue;
3865                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3866                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3867                 meta->tables [i].base = (char*)p;
3868                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3869                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3870                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3871                                 switch (mono_metadata_table_size (bitfield, col)) {
3872                                 case 1:
3873                                         *p++ = values [col];
3874                                         break;
3875                                 case 2:
3876                                         *p++ = values [col] & 0xff;
3877                                         *p++ = (values [col] >> 8) & 0xff;
3878                                         break;
3879                                 case 4:
3880                                         *p++ = values [col] & 0xff;
3881                                         *p++ = (values [col] >> 8) & 0xff;
3882                                         *p++ = (values [col] >> 16) & 0xff;
3883                                         *p++ = (values [col] >> 24) & 0xff;
3884                                         break;
3885                                 default:
3886                                         g_assert_not_reached ();
3887                                 }
3888                         }
3889                 }
3890                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3891         }
3892         
3893         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3894         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3895         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3896         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3897         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3898
3899         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3900 }
3901
3902 /*
3903  * Some tables in metadata need to be sorted according to some criteria, but
3904  * when methods and fields are first created with reflection, they may be assigned a token
3905  * that doesn't correspond to the final token they will get assigned after the sorting.
3906  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3907  * with the reflection objects that represent them. Once all the tables are set up, the 
3908  * reflection objects will contains the correct table index. fixup_method() will fixup the
3909  * tokens for the method with ILGenerator @ilgen.
3910  */
3911 static void
3912 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3913 {
3914         guint32 code_idx = GPOINTER_TO_UINT (value);
3915         MonoReflectionILTokenInfo *iltoken;
3916         MonoReflectionFieldBuilder *field;
3917         MonoReflectionCtorBuilder *ctor;
3918         MonoReflectionMethodBuilder *method;
3919         MonoReflectionTypeBuilder *tb;
3920         MonoReflectionArrayMethod *am;
3921         guint32 i, idx = 0;
3922         unsigned char *target;
3923
3924         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3925                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3926                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3927                 switch (target [3]) {
3928                 case MONO_TABLE_FIELD:
3929                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3930                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3931                                 idx = field->table_idx;
3932                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3933                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3934                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3935                         } else {
3936                                 g_assert_not_reached ();
3937                         }
3938                         break;
3939                 case MONO_TABLE_METHOD:
3940                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3941                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3942                                 idx = method->table_idx;
3943                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3944                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3945                                 idx = ctor->table_idx;
3946                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3947                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3948                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3949                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3950                         } else {
3951                                 g_assert_not_reached ();
3952                         }
3953                         break;
3954                 case MONO_TABLE_TYPEDEF:
3955                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3956                                 g_assert_not_reached ();
3957                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3958                         idx = tb->table_idx;
3959                         break;
3960                 case MONO_TABLE_MEMBERREF:
3961                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3962                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3963                                 idx = am->table_idx;
3964                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3965                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3966                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3967                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3968                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3969                                 g_assert (m->klass->generic_class || m->klass->generic_container);
3970                                 continue;
3971                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3972                                 continue;
3973                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3974                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3975                                 g_assert (is_field_on_inst (f));
3976                                 continue;
3977                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3978                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3979                                 continue;
3980                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3981                                 continue;
3982                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3983                                 continue;
3984                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3985                                 continue;
3986                         } else {
3987                                 g_assert_not_reached ();
3988                         }
3989                         break;
3990                 case MONO_TABLE_METHODSPEC:
3991                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3992                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3993                                 g_assert (mono_method_signature (m)->generic_param_count);
3994                                 continue;
3995                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3996                                 continue;
3997                         } else {
3998                                 g_assert_not_reached ();
3999                         }
4000                         break;
4001                 default:
4002                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4003                 }
4004                 target [0] = idx & 0xff;
4005                 target [1] = (idx >> 8) & 0xff;
4006                 target [2] = (idx >> 16) & 0xff;
4007         }
4008 }
4009
4010 /*
4011  * fixup_cattrs:
4012  *
4013  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4014  * value is not known when the table is emitted.
4015  */
4016 static void
4017 fixup_cattrs (MonoDynamicImage *assembly)
4018 {
4019         MonoDynamicTable *table;
4020         guint32 *values;
4021         guint32 type, i, idx, token;
4022         MonoObject *ctor;
4023
4024         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4025
4026         for (i = 0; i < table->rows; ++i) {
4027                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4028
4029                 type = values [MONO_CUSTOM_ATTR_TYPE];
4030                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4031                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4032                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4033                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4034                         g_assert (ctor);
4035
4036                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4037                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4038                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4039                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4040                         }
4041                 }
4042         }
4043 }
4044
4045 static void
4046 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4047 {
4048         MonoDynamicTable *table;
4049         guint32 *values;
4050
4051         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4052         table->rows++;
4053         alloc_table (table, table->rows);
4054         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4055         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4056         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4057         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4058         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4059         table->next_idx++;
4060 }
4061
4062 static void
4063 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4064 {
4065         MonoDynamicTable *table;
4066         guint32 *values;
4067         char blob_size [6];
4068         guchar hash [20];
4069         char *b = blob_size;
4070         char *name, *sname;
4071         guint32 idx, offset;
4072
4073         if (rsrc->filename) {
4074                 name = mono_string_to_utf8 (rsrc->filename);
4075                 sname = g_path_get_basename (name);
4076         
4077                 table = &assembly->tables [MONO_TABLE_FILE];
4078                 table->rows++;
4079                 alloc_table (table, table->rows);
4080                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4081                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4082                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4083                 g_free (sname);
4084
4085                 mono_sha1_get_digest_from_file (name, hash);
4086                 mono_metadata_encode_value (20, b, &b);
4087                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4088                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4089                 g_free (name);
4090                 idx = table->next_idx++;
4091                 rsrc->offset = 0;
4092                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4093         } else {
4094                 char sizebuf [4];
4095                 char *data;
4096                 guint len;
4097                 if (rsrc->data) {
4098                         data = mono_array_addr (rsrc->data, char, 0);
4099                         len = mono_array_length (rsrc->data);
4100                 } else {
4101                         data = NULL;
4102                         len = 0;
4103                 }
4104                 offset = len;
4105                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4106                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4107                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4108                 mono_image_add_stream_data (&assembly->resources, data, len);
4109
4110                 if (!mb->is_main)
4111                         /* 
4112                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4113                          * the main module, but that needs to reference the FILE table
4114                          * which isn't emitted yet.
4115                          */
4116                         return;
4117                 else
4118                         idx = 0;
4119         }
4120
4121         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4122 }
4123
4124 static void
4125 set_version_from_string (MonoString *version, guint32 *values)
4126 {
4127         gchar *ver, *p, *str;
4128         guint32 i;
4129         
4130         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4131         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4132         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4133         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4134         if (!version)
4135                 return;
4136         ver = str = mono_string_to_utf8 (version);
4137         for (i = 0; i < 4; ++i) {
4138                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4139                 switch (*p) {
4140                 case '.':
4141                         p++;
4142                         break;
4143                 case '*':
4144                         /* handle Revision and Build */
4145                         p++;
4146                         break;
4147                 }
4148                 ver = p;
4149         }
4150         g_free (str);
4151 }
4152
4153 static guint32
4154 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4155         gsize len;
4156         guint32 token = 0;
4157         char blob_size [6];
4158         char *b = blob_size;
4159
4160         if (!pkey)
4161                 return token;
4162
4163         len = mono_array_length (pkey);
4164         mono_metadata_encode_value (len, b, &b);
4165         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4166         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4167
4168         assembly->public_key = g_malloc (len);
4169         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4170         assembly->public_key_len = len;
4171
4172         /* Special case: check for ECMA key (16 bytes) */
4173         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4174                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4175                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4176         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4177                 /* minimum key size (in 2.0) is 384 bits */
4178                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4179         } else {
4180                 /* FIXME - verifier */
4181                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4182                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4183         }
4184         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4185
4186         return token;
4187 }
4188
4189 static void
4190 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4191 {
4192         MonoDynamicTable *table;
4193         MonoDynamicImage *assembly;
4194         MonoReflectionAssemblyBuilder *assemblyb;
4195         MonoDomain *domain;
4196         guint32 *values;
4197         int i;
4198         guint32 module_index;
4199
4200         assemblyb = moduleb->assemblyb;
4201         assembly = moduleb->dynamic_image;
4202         domain = mono_object_domain (assemblyb);
4203
4204         /* Emit ASSEMBLY table */
4205         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4206         alloc_table (table, 1);
4207         values = table->values + MONO_ASSEMBLY_SIZE;
4208         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4209         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4210         if (assemblyb->culture) {
4211                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4212         } else {
4213                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4214         }
4215         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4216         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4217         set_version_from_string (assemblyb->version, values);
4218
4219         /* Emit FILE + EXPORTED_TYPE table */
4220         module_index = 0;
4221         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4222                 int j;
4223                 MonoReflectionModuleBuilder *file_module = 
4224                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4225                 if (file_module != moduleb) {
4226                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4227                         module_index ++;
4228                         if (file_module->types) {
4229                                 for (j = 0; j < file_module->num_types; ++j) {
4230                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4231                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4232                                 }
4233                         }
4234                 }
4235         }
4236         if (assemblyb->loaded_modules) {
4237                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4238                         MonoReflectionModule *file_module = 
4239                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4240                         mono_image_fill_file_table (domain, file_module, assembly);
4241                         module_index ++;
4242                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4243                 }
4244         }
4245         if (assemblyb->type_forwarders)
4246                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4247
4248         /* Emit MANIFESTRESOURCE table */
4249         module_index = 0;
4250         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4251                 int j;
4252                 MonoReflectionModuleBuilder *file_module = 
4253                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4254                 /* The table for the main module is emitted later */
4255                 if (file_module != moduleb) {
4256                         module_index ++;
4257                         if (file_module->resources) {
4258                                 int len = mono_array_length (file_module->resources);
4259                                 for (j = 0; j < len; ++j) {
4260                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4261                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4262                                 }
4263                         }
4264                 }
4265         }               
4266 }
4267
4268 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4269
4270 /*
4271  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4272  * for the modulebuilder @moduleb.
4273  * At the end of the process, method and field tokens are fixed up and the 
4274  * on-disk compressed metadata representation is created.
4275  */
4276 void
4277 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4278 {
4279         MonoDynamicTable *table;
4280         MonoDynamicImage *assembly;
4281         MonoReflectionAssemblyBuilder *assemblyb;
4282         MonoDomain *domain;
4283         GPtrArray *types;
4284         guint32 *values;
4285         int i, j;
4286
4287         assemblyb = moduleb->assemblyb;
4288         assembly = moduleb->dynamic_image;
4289         domain = mono_object_domain (assemblyb);
4290
4291         if (assembly->text_rva)
4292                 return;
4293
4294         assembly->text_rva = START_TEXT_RVA;
4295
4296         if (moduleb->is_main) {
4297                 mono_image_emit_manifest (moduleb);
4298         }
4299
4300         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4301         table->rows = 1; /* .<Module> */
4302         table->next_idx++;
4303         alloc_table (table, table->rows);
4304         /*
4305          * Set the first entry.
4306          */
4307         values = table->values + table->columns;
4308         values [MONO_TYPEDEF_FLAGS] = 0;
4309         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4310         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4311         values [MONO_TYPEDEF_EXTENDS] = 0;
4312         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4313         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4314
4315         /* 
4316          * handle global methods 
4317          * FIXME: test what to do when global methods are defined in multiple modules.
4318          */
4319         if (moduleb->global_methods) {
4320                 table = &assembly->tables [MONO_TABLE_METHOD];
4321                 table->rows += mono_array_length (moduleb->global_methods);
4322                 alloc_table (table, table->rows);
4323                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4324                         mono_image_get_method_info (
4325                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4326         }
4327         if (moduleb->global_fields) {
4328                 table = &assembly->tables [MONO_TABLE_FIELD];
4329                 table->rows += mono_array_length (moduleb->global_fields);
4330                 alloc_table (table, table->rows);
4331                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4332                         mono_image_get_field_info (
4333                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4334         }
4335
4336         table = &assembly->tables [MONO_TABLE_MODULE];
4337         alloc_table (table, 1);
4338         mono_image_fill_module_table (domain, moduleb, assembly);
4339
4340         /* Collect all types into a list sorted by their table_idx */
4341         types = g_ptr_array_new ();
4342
4343         if (moduleb->types)
4344                 for (i = 0; i < moduleb->num_types; ++i) {
4345                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4346                         collect_types (types, type);
4347                 }
4348
4349         g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4350         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4351         table->rows += types->len;
4352         alloc_table (table, table->rows);
4353
4354         /*
4355          * Emit type names + namespaces at one place inside the string heap,
4356          * so load_class_names () needs to touch fewer pages.
4357          */
4358         for (i = 0; i < types->len; ++i) {
4359                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4360                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4361         }
4362         for (i = 0; i < types->len; ++i) {
4363                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4364                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4365         }
4366
4367         for (i = 0; i < types->len; ++i) {
4368                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4369                 mono_image_get_type_info (domain, type, assembly);
4370         }
4371
4372         /* 
4373          * table->rows is already set above and in mono_image_fill_module_table.
4374          */
4375         /* add all the custom attributes at the end, once all the indexes are stable */
4376         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4377
4378         /* CAS assembly permissions */
4379         if (assemblyb->permissions_minimum)
4380                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4381         if (assemblyb->permissions_optional)
4382                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4383         if (assemblyb->permissions_refused)
4384                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4385
4386         module_add_cattrs (assembly, moduleb);
4387
4388         /* fixup tokens */
4389         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4390
4391         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4392          * the final tokens and don't need another fixup pass. */
4393
4394         if (moduleb->global_methods) {
4395                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4396                         MonoReflectionMethodBuilder *mb = mono_array_get (
4397                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4398                         mono_image_add_methodimpl (assembly, mb);
4399                 }
4400         }
4401
4402         for (i = 0; i < types->len; ++i) {
4403                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4404                 if (type->methods) {
4405                         for (j = 0; j < type->num_methods; ++j) {
4406                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4407                                         type->methods, MonoReflectionMethodBuilder*, j);
4408
4409                                 mono_image_add_methodimpl (assembly, mb);
4410                         }
4411                 }
4412         }
4413
4414         g_ptr_array_free (types, TRUE);
4415
4416         fixup_cattrs (assembly);
4417 }
4418
4419 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4420
4421 void
4422 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4423 {
4424         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4425 }
4426
4427 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4428
4429 #ifndef DISABLE_REFLECTION_EMIT
4430
4431 /*
4432  * mono_image_insert_string:
4433  * @module: module builder object
4434  * @str: a string
4435  *
4436  * Insert @str into the user string stream of @module.
4437  */
4438 guint32
4439 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4440 {
4441         MonoDynamicImage *assembly;
4442         guint32 idx;
4443         char buf [16];
4444         char *b = buf;
4445         
4446         MONO_ARCH_SAVE_REGS;
4447
4448         if (!module->dynamic_image)
4449                 mono_image_module_basic_init (module);
4450
4451         assembly = module->dynamic_image;
4452         
4453         if (assembly->save) {
4454                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4455                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4456 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4457         {
4458                 char *swapped = g_malloc (2 * mono_string_length (str));
4459                 const char *p = (const char*)mono_string_chars (str);
4460
4461                 swap_with_size (swapped, p, 2, mono_string_length (str));
4462                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4463                 g_free (swapped);
4464         }
4465 #else
4466                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4467 #endif
4468                 mono_image_add_stream_data (&assembly->us, "", 1);
4469         } else {
4470                 idx = assembly->us.index ++;
4471         }
4472
4473         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4474
4475         return MONO_TOKEN_STRING | idx;
4476 }
4477
4478 guint32
4479 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4480 {
4481         MonoClass *klass;
4482         guint32 token = 0;
4483
4484         klass = obj->vtable->klass;
4485         if (strcmp (klass->name, "MonoMethod") == 0) {
4486                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4487                 MonoMethodSignature *sig, *old;
4488                 guint32 sig_token, parent;
4489                 int nargs, i;
4490
4491                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4492
4493                 nargs = mono_array_length (opt_param_types);
4494                 old = mono_method_signature (method);
4495                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4496
4497                 sig->hasthis = old->hasthis;
4498                 sig->explicit_this = old->explicit_this;
4499                 sig->call_convention = old->call_convention;
4500                 sig->generic_param_count = old->generic_param_count;
4501                 sig->param_count = old->param_count + nargs;
4502                 sig->sentinelpos = old->param_count;
4503                 sig->ret = old->ret;
4504
4505                 for (i = 0; i < old->param_count; i++)
4506                         sig->params [i] = old->params [i];
4507
4508                 for (i = 0; i < nargs; i++) {
4509                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4510                         sig->params [old->param_count + i] = rt->type;
4511                 }
4512
4513                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4514                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4515                 parent >>= MONO_TYPEDEFORREF_BITS;
4516
4517                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4518                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4519
4520                 sig_token = method_encode_signature (assembly, sig);
4521                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4522         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4523                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4524                 ReflectionMethodBuilder rmb;
4525                 guint32 parent, sig;
4526                 char *name;
4527
4528                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4529                 rmb.opt_types = opt_param_types;
4530
4531                 sig = method_builder_encode_signature (assembly, &rmb);
4532
4533                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4534                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4535
4536                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4537                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4538
4539                 name = mono_string_to_utf8 (rmb.name);
4540                 token = mono_image_get_varargs_method_token (
4541                         assembly, parent, name, sig);
4542                 g_free (name);
4543         } else {
4544                 g_error ("requested method token for %s\n", klass->name);
4545         }
4546
4547         return token;
4548 }
4549
4550 /*
4551  * mono_image_create_token:
4552  * @assembly: a dynamic assembly
4553  * @obj:
4554  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4555  *
4556  * Get a token to insert in the IL code stream for the given MemberInfo.
4557  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4558  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4559  * entry.
4560  */
4561 guint32
4562 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4563                                                  gboolean create_methodspec, gboolean register_token)
4564 {
4565         MonoClass *klass;
4566         guint32 token = 0;
4567
4568         klass = obj->vtable->klass;
4569
4570         /* Check for user defined reflection objects */
4571         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4572         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4573                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4574
4575         if (strcmp (klass->name, "MethodBuilder") == 0) {
4576                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4577                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4578
4579                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4580                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4581                 else
4582                         token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4583                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4584         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4585                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4586                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4587
4588                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4589                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4590                 else
4591                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4592                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4593         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4594                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4595                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4596                 if (tb->generic_params) {
4597                         token = mono_image_get_generic_field_token (assembly, fb);
4598                 } else {
4599                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4600                 }
4601         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4602                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4603                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4604         } else if (strcmp (klass->name, "MonoType") == 0) {
4605                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4606                 MonoClass *mc = mono_class_from_mono_type (tb->type);
4607                 token = mono_metadata_token_from_dor (
4608                         mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4609         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4610                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4611                 token = mono_metadata_token_from_dor (
4612                         mono_image_typedef_or_ref (assembly, tb->type));
4613         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4614                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4615                 token = mono_metadata_token_from_dor (
4616                         mono_image_typedef_or_ref (assembly, tb->type));
4617         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4618                    strcmp (klass->name, "MonoMethod") == 0 ||
4619                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4620                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4621                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4622                 if (m->method->is_inflated) {
4623                         if (create_methodspec)
4624                                 token = mono_image_get_methodspec_token (assembly, m->method);
4625                         else
4626                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4627                 } else if ((m->method->klass->image == &assembly->image) &&
4628                          !m->method->klass->generic_class) {
4629                         static guint32 method_table_idx = 0xffffff;
4630                         if (m->method->klass->wastypebuilder) {
4631                                 /* we use the same token as the one that was assigned
4632                                  * to the Methodbuilder.
4633                                  * FIXME: do the equivalent for Fields.
4634                                  */
4635                                 token = m->method->token;
4636                         } else {
4637                                 /*
4638                                  * Each token should have a unique index, but the indexes are
4639                                  * assigned by managed code, so we don't know about them. An
4640                                  * easy solution is to count backwards...
4641                                  */
4642                                 method_table_idx --;
4643                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4644                         }
4645                 } else {
4646                         token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4647                 }
4648                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4649         } else if (strcmp (klass->name, "MonoField") == 0) {
4650                 MonoReflectionField *f = (MonoReflectionField *)obj;
4651                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4652                         static guint32 field_table_idx = 0xffffff;
4653                         field_table_idx --;
4654                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4655                 } else {
4656                         token = mono_image_get_fieldref_token (assembly, f);
4657                 }
4658                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4659         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4660                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4661                 token = mono_image_get_array_token (assembly, m);
4662         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4663                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4664                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4665         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4666                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4667                 token = mono_metadata_token_from_dor (
4668                         mono_image_typedef_or_ref (assembly, tb->type));
4669         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4670                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4671                 token = mono_image_get_field_on_inst_token (assembly, f);
4672         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4673                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4674                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4675         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4676                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4677                 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4678         } else {
4679                 g_error ("requested token for %s\n", klass->name);
4680         }
4681
4682         if (register_token)
4683                 mono_image_register_token (assembly, token, obj);
4684
4685         return token;
4686 }
4687
4688 /*
4689  * mono_image_register_token:
4690  *
4691  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4692  * the Module.ResolveXXXToken () methods to work.
4693  */
4694 void
4695 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4696 {
4697         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4698         if (prev) {
4699                 /* There could be multiple MethodInfo objects with the same token */
4700                 //g_assert (prev == obj);
4701         } else {
4702                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4703         }
4704 }
4705
4706 #endif /* DISABLE_REFLECTION_EMIT */
4707
4708 typedef struct {
4709         guint32 import_lookup_table;
4710         guint32 timestamp;
4711         guint32 forwarder;
4712         guint32 name_rva;
4713         guint32 import_address_table_rva;
4714 } MonoIDT;
4715
4716 typedef struct {
4717         guint32 name_rva;
4718         guint32 flags;
4719 } MonoILT;
4720
4721 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4722
4723 static MonoDynamicImage*
4724 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4725 {
4726         static const guchar entrycode [16] = {0xff, 0x25, 0};
4727         MonoDynamicImage *image;
4728         int i;
4729
4730         const char *version;
4731
4732         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4733                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4734         else
4735                 version = mono_get_runtime_info ()->runtime_version;
4736
4737 #if HAVE_BOEHM_GC
4738         image = GC_MALLOC (sizeof (MonoDynamicImage));
4739 #else
4740         image = g_new0 (MonoDynamicImage, 1);
4741 #endif
4742         
4743         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4744         
4745         /*g_print ("created image %p\n", image);*/
4746         /* keep in sync with image.c */
4747         image->image.name = assembly_name;
4748         image->image.assembly_name = image->image.name; /* they may be different */
4749         image->image.module_name = module_name;
4750         image->image.version = g_strdup (version);
4751         image->image.md_version_major = 1;
4752         image->image.md_version_minor = 1;
4753         image->image.dynamic = TRUE;
4754
4755         image->image.references = g_new0 (MonoAssembly*, 1);
4756         image->image.references [0] = NULL;
4757
4758         mono_image_init (&image->image);
4759
4760         image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4761         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4762         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4763         image->method_aux_hash = g_hash_table_new (NULL, NULL);
4764         image->handleref = g_hash_table_new (NULL, NULL);
4765         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4766         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4767         image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4768         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4769         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4770         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4771         image->gen_params = g_ptr_array_new ();
4772
4773         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4774         string_heap_init (&image->sheap);
4775         mono_image_add_stream_data (&image->us, "", 1);
4776         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4777         /* import tables... */
4778         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4779         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4780         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4781         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4782         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4783         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4784         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4785         stream_data_align (&image->code);
4786
4787         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4788
4789         for (i=0; i < MONO_TABLE_NUM; ++i) {
4790                 image->tables [i].next_idx = 1;
4791                 image->tables [i].columns = table_sizes [i];
4792         }
4793
4794         image->image.assembly = (MonoAssembly*)assembly;
4795         image->run = assembly->run;
4796         image->save = assembly->save;
4797         image->pe_kind = 0x1; /* ILOnly */
4798         image->machine = 0x14c; /* I386 */
4799         
4800         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4801
4802         return image;
4803 }
4804
4805 static void
4806 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4807 {
4808         g_free (key);
4809 }
4810
4811 void
4812 mono_dynamic_image_free (MonoDynamicImage *image)
4813 {
4814         MonoDynamicImage *di = image;
4815         GList *list;
4816         int i;
4817
4818         if (di->methodspec)
4819                 mono_g_hash_table_destroy (di->methodspec);
4820         if (di->typespec)
4821                 g_hash_table_destroy (di->typespec);
4822         if (di->typeref)
4823                 g_hash_table_destroy (di->typeref);
4824         if (di->handleref)
4825                 g_hash_table_destroy (di->handleref);
4826         if (di->tokens)
4827                 mono_g_hash_table_destroy (di->tokens);
4828         if (di->generic_def_objects)
4829                 mono_g_hash_table_destroy (di->generic_def_objects);
4830         if (di->blob_cache) {
4831                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4832                 g_hash_table_destroy (di->blob_cache);
4833         }
4834         if (di->standalonesig_cache)
4835                 g_hash_table_destroy (di->standalonesig_cache);
4836         for (list = di->array_methods; list; list = list->next) {
4837                 ArrayMethod *am = (ArrayMethod *)list->data;
4838                 g_free (am->sig);
4839                 g_free (am->name);
4840                 g_free (am);
4841         }
4842         g_list_free (di->array_methods);
4843         if (di->gen_params) {
4844                 for (i = 0; i < di->gen_params->len; i++) {
4845                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4846                         if (entry->gparam->type.type) {
4847                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4848                                 g_free ((char*)mono_generic_param_info (param)->name);
4849                                 g_free (param);
4850                         }
4851                         g_free (entry);
4852                 }
4853                 g_ptr_array_free (di->gen_params, TRUE);
4854         }
4855         if (di->token_fixups)
4856                 mono_g_hash_table_destroy (di->token_fixups);
4857         if (di->method_to_table_idx)
4858                 g_hash_table_destroy (di->method_to_table_idx);
4859         if (di->field_to_table_idx)
4860                 g_hash_table_destroy (di->field_to_table_idx);
4861         if (di->method_aux_hash)
4862                 g_hash_table_destroy (di->method_aux_hash);
4863         g_free (di->strong_name);
4864         g_free (di->win32_res);
4865         if (di->public_key)
4866                 g_free (di->public_key);
4867
4868         /*g_print ("string heap destroy for image %p\n", di);*/
4869         mono_dynamic_stream_reset (&di->sheap);
4870         mono_dynamic_stream_reset (&di->code);
4871         mono_dynamic_stream_reset (&di->resources);
4872         mono_dynamic_stream_reset (&di->us);
4873         mono_dynamic_stream_reset (&di->blob);
4874         mono_dynamic_stream_reset (&di->tstream);
4875         mono_dynamic_stream_reset (&di->guid);
4876         for (i = 0; i < MONO_TABLE_NUM; ++i) {
4877                 g_free (di->tables [i].values);
4878         }
4879 }       
4880
4881 #ifndef DISABLE_REFLECTION_EMIT
4882
4883 /*
4884  * mono_image_basic_init:
4885  * @assembly: an assembly builder object
4886  *
4887  * Create the MonoImage that represents the assembly builder and setup some
4888  * of the helper hash table and the basic metadata streams.
4889  */
4890 void
4891 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4892 {
4893         MonoDynamicAssembly *assembly;
4894         MonoDynamicImage *image;
4895         MonoDomain *domain = mono_object_domain (assemblyb);
4896         
4897         MONO_ARCH_SAVE_REGS;
4898
4899         if (assemblyb->dynamic_assembly)
4900                 return;
4901
4902 #if HAVE_BOEHM_GC
4903         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4904 #else
4905         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4906 #endif
4907
4908         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4909         
4910         assembly->assembly.ref_count = 1;
4911         assembly->assembly.dynamic = TRUE;
4912         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4913         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4914         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4915         if (assemblyb->culture)
4916                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4917         else
4918                 assembly->assembly.aname.culture = g_strdup ("");
4919
4920         if (assemblyb->version) {
4921                         char *vstr = mono_string_to_utf8 (assemblyb->version);
4922                         char **version = g_strsplit (vstr, ".", 4);
4923                         char **parts = version;
4924                         assembly->assembly.aname.major = atoi (*parts++);
4925                         assembly->assembly.aname.minor = atoi (*parts++);
4926                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4927                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4928
4929                         g_strfreev (version);
4930                         g_free (vstr);
4931         } else {
4932                         assembly->assembly.aname.major = 0;
4933                         assembly->assembly.aname.minor = 0;
4934                         assembly->assembly.aname.build = 0;
4935                         assembly->assembly.aname.revision = 0;
4936         }
4937
4938         assembly->run = assemblyb->access != 2;
4939         assembly->save = assemblyb->access != 1;
4940
4941         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4942         image->initial_image = TRUE;
4943         assembly->assembly.aname.name = image->image.name;
4944         assembly->assembly.image = &image->image;
4945
4946         mono_domain_assemblies_lock (domain);
4947         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4948         mono_domain_assemblies_unlock (domain);
4949
4950         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4951         
4952         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4953         
4954         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4955 }
4956
4957 #endif /* DISABLE_REFLECTION_EMIT */
4958
4959 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4960
4961 static int
4962 calc_section_size (MonoDynamicImage *assembly)
4963 {
4964         int nsections = 0;
4965
4966         /* alignment constraints */
4967         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4968         g_assert ((assembly->code.index % 4) == 0);
4969         assembly->meta_size += 3;
4970         assembly->meta_size &= ~3;
4971         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4972         g_assert ((assembly->resources.index % 4) == 0);
4973
4974         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4975         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4976         nsections++;
4977
4978         if (assembly->win32_res) {
4979                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4980
4981                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4982                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4983                 nsections++;
4984         }
4985
4986         assembly->sections [MONO_SECTION_RELOC].size = 12;
4987         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4988         nsections++;
4989
4990         return nsections;
4991 }
4992
4993 typedef struct {
4994         guint32 id;
4995         guint32 offset;
4996         GSList *children;
4997         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4998 } ResTreeNode;
4999
5000 static int
5001 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5002 {
5003         ResTreeNode *t1 = (ResTreeNode*)a;
5004         ResTreeNode *t2 = (ResTreeNode*)b;
5005
5006         return t1->id - t2->id;
5007 }
5008
5009 /*
5010  * resource_tree_create:
5011  *
5012  *  Organize the resources into a resource tree.
5013  */
5014 static ResTreeNode *
5015 resource_tree_create (MonoArray *win32_resources)
5016 {
5017         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5018         GSList *l;
5019         int i;
5020
5021         tree = g_new0 (ResTreeNode, 1);
5022         
5023         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5024                 MonoReflectionWin32Resource *win32_res =
5025                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5026
5027                 /* Create node */
5028
5029                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5030                 lang_node = g_new0 (ResTreeNode, 1);
5031                 lang_node->id = win32_res->lang_id;
5032                 lang_node->win32_res = win32_res;
5033
5034                 /* Create type node if neccesary */
5035                 type_node = NULL;
5036                 for (l = tree->children; l; l = l->next)
5037                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5038                                 type_node = (ResTreeNode*)l->data;
5039                                 break;
5040                         }
5041
5042                 if (!type_node) {
5043                         type_node = g_new0 (ResTreeNode, 1);
5044                         type_node->id = win32_res->res_type;
5045
5046                         /* 
5047                          * The resource types have to be sorted otherwise
5048                          * Windows Explorer can't display the version information.
5049                          */
5050                         tree->children = g_slist_insert_sorted (tree->children, 
5051                                 type_node, resource_tree_compare_by_id);
5052                 }
5053
5054                 /* Create res node if neccesary */
5055                 res_node = NULL;
5056                 for (l = type_node->children; l; l = l->next)
5057                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5058                                 res_node = (ResTreeNode*)l->data;
5059                                 break;
5060                         }
5061
5062                 if (!res_node) {
5063                         res_node = g_new0 (ResTreeNode, 1);
5064                         res_node->id = win32_res->res_id;
5065                         type_node->children = g_slist_append (type_node->children, res_node);
5066                 }
5067
5068                 res_node->children = g_slist_append (res_node->children, lang_node);
5069         }
5070
5071         return tree;
5072 }
5073
5074 /*
5075  * resource_tree_encode:
5076  * 
5077  *   Encode the resource tree into the format used in the PE file.
5078  */
5079 static void
5080 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5081 {
5082         char *entries;
5083         MonoPEResourceDir dir;
5084         MonoPEResourceDirEntry dir_entry;
5085         MonoPEResourceDataEntry data_entry;
5086         GSList *l;
5087         guint32 res_id_entries;
5088
5089         /*
5090          * For the format of the resource directory, see the article
5091          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5092          * Matt Pietrek
5093          */
5094
5095         memset (&dir, 0, sizeof (dir));
5096         memset (&dir_entry, 0, sizeof (dir_entry));
5097         memset (&data_entry, 0, sizeof (data_entry));
5098
5099         g_assert (sizeof (dir) == 16);
5100         g_assert (sizeof (dir_entry) == 8);
5101         g_assert (sizeof (data_entry) == 16);
5102
5103         node->offset = p - begin;
5104
5105         /* IMAGE_RESOURCE_DIRECTORY */
5106         res_id_entries = g_slist_length (node->children);
5107         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5108
5109         memcpy (p, &dir, sizeof (dir));
5110         p += sizeof (dir);
5111
5112         /* Reserve space for entries */
5113         entries = p;
5114         p += sizeof (dir_entry) * res_id_entries;
5115
5116         /* Write children */
5117         for (l = node->children; l; l = l->next) {
5118                 ResTreeNode *child = (ResTreeNode*)l->data;
5119
5120                 if (child->win32_res) {
5121                         guint32 size;
5122
5123                         child->offset = p - begin;
5124
5125                         /* IMAGE_RESOURCE_DATA_ENTRY */
5126                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5127                         size = mono_array_length (child->win32_res->res_data);
5128                         data_entry.rde_size = GUINT32_TO_LE (size);
5129
5130                         memcpy (p, &data_entry, sizeof (data_entry));
5131                         p += sizeof (data_entry);
5132
5133                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5134                         p += size;
5135                 } else {
5136                         resource_tree_encode (child, begin, p, &p);
5137                 }
5138         }
5139
5140         /* IMAGE_RESOURCE_ENTRY */
5141         for (l = node->children; l; l = l->next) {
5142                 ResTreeNode *child = (ResTreeNode*)l->data;
5143
5144                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5145                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5146
5147                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5148                 entries += sizeof (dir_entry);
5149         }
5150
5151         *endbuf = p;
5152 }
5153
5154 static void
5155 resource_tree_free (ResTreeNode * node)
5156 {
5157         GSList * list;
5158         for (list = node->children; list; list = list->next)
5159                 resource_tree_free ((ResTreeNode*)list->data);
5160         g_slist_free(node->children);
5161         g_free (node);
5162 }
5163
5164 static void
5165 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5166 {
5167         char *buf;
5168         char *p;
5169         guint32 size, i;
5170         MonoReflectionWin32Resource *win32_res;
5171         ResTreeNode *tree;
5172
5173         if (!assemblyb->win32_resources)
5174                 return;
5175
5176         /*
5177          * Resources are stored in a three level tree inside the PE file.
5178          * - level one contains a node for each type of resource
5179          * - level two contains a node for each resource
5180          * - level three contains a node for each instance of a resource for a
5181          *   specific language.
5182          */
5183
5184         tree = resource_tree_create (assemblyb->win32_resources);
5185
5186         /* Estimate the size of the encoded tree */
5187         size = 0;
5188         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5189                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5190                 size += mono_array_length (win32_res->res_data);
5191         }
5192         /* Directory structure */
5193         size += mono_array_length (assemblyb->win32_resources) * 256;
5194         p = buf = g_malloc (size);
5195
5196         resource_tree_encode (tree, p, p, &p);
5197
5198         g_assert (p - buf <= size);
5199
5200         assembly->win32_res = g_malloc (p - buf);
5201         assembly->win32_res_size = p - buf;
5202         memcpy (assembly->win32_res, buf, p - buf);
5203
5204         g_free (buf);
5205         resource_tree_free (tree);
5206 }
5207
5208 static void
5209 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5210 {
5211         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5212         int i;
5213
5214         p += sizeof (MonoPEResourceDir);
5215         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5216                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5217                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5218                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5219                         fixup_resource_directory (res_section, child, rva);
5220                 } else {
5221                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5222                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5223                 }
5224
5225                 p += sizeof (MonoPEResourceDirEntry);
5226         }
5227 }
5228
5229 static void
5230 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5231 {
5232         guint32 dummy;
5233         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5234                 g_error ("WriteFile returned %d\n", GetLastError ());
5235 }
5236
5237 /*
5238  * mono_image_create_pefile:
5239  * @mb: a module builder object
5240  * 
5241  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5242  * assembly->pefile where it can be easily retrieved later in chunks.
5243  */
5244 void
5245 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5246 {
5247         MonoMSDOSHeader *msdos;
5248         MonoDotNetHeader *header;
5249         MonoSectionTable *section;
5250         MonoCLIHeader *cli_header;
5251         guint32 size, image_size, virtual_base, text_offset;
5252         guint32 header_start, section_start, file_offset, virtual_offset;
5253         MonoDynamicImage *assembly;
5254         MonoReflectionAssemblyBuilder *assemblyb;
5255         MonoDynamicStream pefile_stream = {0};
5256         MonoDynamicStream *pefile = &pefile_stream;
5257         int i, nsections;
5258         guint32 *rva, value;
5259         guchar *p;
5260         static const unsigned char msheader[] = {
5261                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5262                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5263                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5264                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5265                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5266                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5267                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5268                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5269         };
5270
5271         assemblyb = mb->assemblyb;
5272
5273         mono_image_basic_init (assemblyb);
5274         assembly = mb->dynamic_image;
5275
5276         assembly->pe_kind = assemblyb->pe_kind;
5277         assembly->machine = assemblyb->machine;
5278         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5279         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5280         
5281         mono_image_build_metadata (mb);
5282
5283         if (mb->is_main && assemblyb->resources) {
5284                 int len = mono_array_length (assemblyb->resources);
5285                 for (i = 0; i < len; ++i)
5286                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5287         }
5288
5289         if (mb->resources) {
5290                 int len = mono_array_length (mb->resources);
5291                 for (i = 0; i < len; ++i)
5292                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5293         }
5294
5295         build_compressed_metadata (assembly);
5296
5297         if (mb->is_main)
5298                 assembly_add_win32_resources (assembly, assemblyb);
5299
5300         nsections = calc_section_size (assembly);
5301         
5302         /* The DOS header and stub */
5303         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5304         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5305
5306         /* the dotnet header */
5307         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5308
5309         /* the section tables */
5310         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5311
5312         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5313         virtual_offset = VIRT_ALIGN;
5314         image_size = 0;
5315
5316         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5317                 if (!assembly->sections [i].size)
5318                         continue;
5319                 /* align offsets */
5320                 file_offset += FILE_ALIGN - 1;
5321                 file_offset &= ~(FILE_ALIGN - 1);
5322                 virtual_offset += VIRT_ALIGN - 1;
5323                 virtual_offset &= ~(VIRT_ALIGN - 1);
5324
5325                 assembly->sections [i].offset = file_offset;
5326                 assembly->sections [i].rva = virtual_offset;
5327
5328                 file_offset += assembly->sections [i].size;
5329                 virtual_offset += assembly->sections [i].size;
5330                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5331         }
5332
5333         file_offset += FILE_ALIGN - 1;
5334         file_offset &= ~(FILE_ALIGN - 1);
5335
5336         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5337
5338         /* back-patch info */
5339         msdos = (MonoMSDOSHeader*)pefile->data;
5340         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5341
5342         header = (MonoDotNetHeader*)(pefile->data + header_start);
5343         header->pesig [0] = 'P';
5344         header->pesig [1] = 'E';
5345         
5346         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5347         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5348         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5349         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5350         if (assemblyb->pekind == 1) {
5351                 /* it's a dll */
5352                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5353         } else {
5354                 /* it's an exe */
5355                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5356         }
5357
5358         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5359
5360         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5361         header->pe.pe_major = 6;
5362         header->pe.pe_minor = 0;
5363         size = assembly->sections [MONO_SECTION_TEXT].size;
5364         size += FILE_ALIGN - 1;
5365         size &= ~(FILE_ALIGN - 1);
5366         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5367         size = assembly->sections [MONO_SECTION_RSRC].size;
5368         size += FILE_ALIGN - 1;
5369         size &= ~(FILE_ALIGN - 1);
5370         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5371         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5372         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5373         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5374         /* pe_rva_entry_point always at the beginning of the text section */
5375         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5376
5377         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5378         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5379         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5380         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5381         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5382         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5383         size = section_start;
5384         size += FILE_ALIGN - 1;
5385         size &= ~(FILE_ALIGN - 1);
5386         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5387         size = image_size;
5388         size += VIRT_ALIGN - 1;
5389         size &= ~(VIRT_ALIGN - 1);
5390         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5391
5392         /*
5393         // Translate the PEFileKind value to the value expected by the Windows loader
5394         */
5395         {
5396                 short kind;
5397
5398                 /*
5399                 // PEFileKinds.Dll == 1
5400                 // PEFileKinds.ConsoleApplication == 2
5401                 // PEFileKinds.WindowApplication == 3
5402                 //
5403                 // need to get:
5404                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5405                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5406                 */
5407                 if (assemblyb->pekind == 3)
5408                         kind = 2;
5409                 else
5410                         kind = 3;
5411                 
5412                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5413         }    
5414         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5415         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5416         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5417         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5418         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5419         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5420
5421         /* fill data directory entries */
5422
5423         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5424         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5425
5426         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5427         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5428
5429         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5430         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5431         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5432         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5433         /* patch entrypoint name */
5434         if (assemblyb->pekind == 1)
5435                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5436         else
5437                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5438         /* patch imported function RVA name */
5439         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5440         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5441
5442         /* the import table */
5443         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5444         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5445         /* patch imported dll RVA name and other entries in the dir */
5446         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5447         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5448         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5449         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5450         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5451         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5452
5453         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5454         value = (assembly->text_rva + assembly->imp_names_offset);
5455         *p++ = (value) & 0xff;
5456         *p++ = (value >> 8) & (0xff);
5457         *p++ = (value >> 16) & (0xff);
5458         *p++ = (value >> 24) & (0xff);
5459
5460         /* the CLI header info */
5461         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5462         cli_header->ch_size = GUINT32_FROM_LE (72);
5463         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5464         if (mono_framework_version () > 1)
5465                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5466         else 
5467                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5468         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5469         if (assemblyb->entry_point) {
5470                 guint32 table_idx = 0;
5471                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5472                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5473                         table_idx = methodb->table_idx;
5474                 } else {
5475                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5476                 }
5477                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5478         } else {
5479                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5480         }
5481         /* The embedded managed resources */
5482         text_offset = assembly->text_rva + assembly->code.index;
5483         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5484         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5485         text_offset += assembly->resources.index;
5486         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5487         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5488         text_offset += assembly->meta_size;
5489         if (assembly->strong_name_size) {
5490                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5491                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5492                 text_offset += assembly->strong_name_size;
5493         }
5494
5495         /* write the section tables and section content */
5496         section = (MonoSectionTable*)(pefile->data + section_start);
5497         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5498                 static const char section_names [][7] = {
5499                         ".text", ".rsrc", ".reloc"
5500                 };
5501                 if (!assembly->sections [i].size)
5502                         continue;
5503                 strcpy (section->st_name, section_names [i]);
5504                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5505                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5506                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5507                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5508                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5509                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5510                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5511                 section ++;
5512         }
5513         
5514         checked_write_file (file, pefile->data, pefile->index);
5515         
5516         mono_dynamic_stream_reset (pefile);
5517         
5518         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5519                 if (!assembly->sections [i].size)
5520                         continue;
5521                 
5522                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5523                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5524                 
5525                 switch (i) {
5526                 case MONO_SECTION_TEXT:
5527                         /* patch entry point */
5528                         p = (guchar*)(assembly->code.data + 2);
5529                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5530                         *p++ = (value) & 0xff;
5531                         *p++ = (value >> 8) & 0xff;
5532                         *p++ = (value >> 16) & 0xff;
5533                         *p++ = (value >> 24) & 0xff;
5534                 
5535                         checked_write_file (file, assembly->code.data, assembly->code.index);
5536                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5537                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5538                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5539                                 
5540
5541                         g_free (assembly->image.raw_metadata);
5542                         break;
5543                 case MONO_SECTION_RELOC: {
5544                         struct {
5545                                 guint32 page_rva;
5546                                 guint32 block_size;
5547                                 guint16 type_and_offset;
5548                                 guint16 term;
5549                         } reloc;
5550                         
5551                         g_assert (sizeof (reloc) == 12);
5552                         
5553                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5554                         reloc.block_size = GUINT32_FROM_LE (12);
5555                         
5556                         /* 
5557                          * the entrypoint is always at the start of the text section 
5558                          * 3 is IMAGE_REL_BASED_HIGHLOW
5559                          * 2 is patch_size_rva - text_rva
5560                          */
5561                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5562                         reloc.term = 0;
5563                         
5564                         checked_write_file (file, &reloc, sizeof (reloc));
5565                         
5566                         break;
5567                 }
5568                 case MONO_SECTION_RSRC:
5569                         if (assembly->win32_res) {
5570
5571                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5572                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5573                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5574                         }
5575                         break;
5576                 default:
5577                         g_assert_not_reached ();
5578                 }
5579         }
5580         
5581         /* check that the file is properly padded */
5582         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5583                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5584         if (! SetEndOfFile (file))
5585                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5586         
5587         mono_dynamic_stream_reset (&assembly->code);
5588         mono_dynamic_stream_reset (&assembly->us);
5589         mono_dynamic_stream_reset (&assembly->blob);
5590         mono_dynamic_stream_reset (&assembly->guid);
5591         mono_dynamic_stream_reset (&assembly->sheap);
5592
5593         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5594         g_hash_table_destroy (assembly->blob_cache);
5595         assembly->blob_cache = NULL;
5596 }
5597
5598 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5599
5600 void
5601 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5602 {
5603         g_assert_not_reached ();
5604 }
5605
5606 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5607
5608 #ifndef DISABLE_REFLECTION_EMIT
5609
5610 MonoReflectionModule *
5611 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5612 {
5613         char *name;
5614         MonoImage *image;
5615         MonoImageOpenStatus status;
5616         MonoDynamicAssembly *assembly;
5617         guint32 module_count;
5618         MonoImage **new_modules;
5619         gboolean *new_modules_loaded;
5620         
5621         name = mono_string_to_utf8 (fileName);
5622
5623         image = mono_image_open (name, &status);
5624         if (!image) {
5625                 MonoException *exc;
5626                 if (status == MONO_IMAGE_ERROR_ERRNO)
5627                         exc = mono_get_exception_file_not_found (fileName);
5628                 else
5629                         exc = mono_get_exception_bad_image_format (name);
5630                 g_free (name);
5631                 mono_raise_exception (exc);
5632         }
5633
5634         g_free (name);
5635
5636         assembly = ab->dynamic_assembly;
5637         image->assembly = (MonoAssembly*)assembly;
5638
5639         module_count = image->assembly->image->module_count;
5640         new_modules = g_new0 (MonoImage *, module_count + 1);
5641         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5642
5643         if (image->assembly->image->modules)
5644                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5645         if (image->assembly->image->modules_loaded)
5646                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5647         new_modules [module_count] = image;
5648         new_modules_loaded [module_count] = TRUE;
5649         mono_image_addref (image);
5650
5651         g_free (image->assembly->image->modules);
5652         image->assembly->image->modules = new_modules;
5653         image->assembly->image->modules_loaded = new_modules_loaded;
5654         image->assembly->image->module_count ++;
5655
5656         mono_assembly_load_references (image, &status);
5657         if (status) {
5658                 mono_image_close (image);
5659                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5660         }
5661
5662         return mono_module_get_object (mono_domain_get (), image);
5663 }
5664
5665 #endif /* DISABLE_REFLECTION_EMIT */
5666
5667 /*
5668  * We need to return always the same object for MethodInfo, FieldInfo etc..
5669  * but we need to consider the reflected type.
5670  * type uses a different hash, since it uses custom hash/equal functions.
5671  */
5672
5673 typedef struct {
5674         gpointer item;
5675         MonoClass *refclass;
5676 } ReflectedEntry;
5677
5678 static gboolean
5679 reflected_equal (gconstpointer a, gconstpointer b) {
5680         const ReflectedEntry *ea = a;
5681         const ReflectedEntry *eb = b;
5682
5683         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5684 }
5685
5686 static guint
5687 reflected_hash (gconstpointer a) {
5688         const ReflectedEntry *ea = a;
5689         return mono_aligned_addr_hash (ea->item);
5690 }
5691
5692 #define CHECK_OBJECT(t,p,k)     \
5693         do {    \
5694                 t _obj; \
5695                 ReflectedEntry e;       \
5696                 e.item = (p);   \
5697                 e.refclass = (k);       \
5698                 mono_domain_lock (domain);      \
5699                 if (!domain->refobject_hash)    \
5700                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5701                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5702                         mono_domain_unlock (domain);    \
5703                         return _obj;    \
5704                 }       \
5705         mono_domain_unlock (domain); \
5706         } while (0)
5707
5708 #ifdef HAVE_BOEHM_GC
5709 /* ReflectedEntry doesn't need to be GC tracked */
5710 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5711 #define FREE_REFENTRY(entry) g_free ((entry))
5712 #else
5713 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5714 /* FIXME: */
5715 #define FREE_REFENTRY(entry)
5716 #endif
5717
5718 #define CACHE_OBJECT(t,p,o,k)   \
5719         do {    \
5720                 t _obj; \
5721         ReflectedEntry pe; \
5722         pe.item = (p); \
5723         pe.refclass = (k); \
5724         mono_domain_lock (domain); \
5725                 if (!domain->refobject_hash)    \
5726                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5727         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5728         if (!_obj) { \
5729                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5730                     e->item = (p);      \
5731                     e->refclass = (k);  \
5732                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5733             _obj = o; \
5734         } \
5735                 mono_domain_unlock (domain);    \
5736         return _obj; \
5737         } while (0)
5738
5739 static void
5740 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5741 {
5742         mono_domain_lock (domain);
5743         if (domain->refobject_hash) {
5744         ReflectedEntry pe;
5745                 gpointer orig_pe, orig_value;
5746
5747                 pe.item = o;
5748                 pe.refclass = klass;
5749                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5750                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
5751                         FREE_REFENTRY (orig_pe);
5752                 }
5753         }
5754         mono_domain_unlock (domain);
5755 }
5756
5757 static gpointer
5758 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5759 {
5760         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5761 }
5762
5763 static gpointer
5764 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5765 {
5766         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5767 }
5768
5769 #ifndef DISABLE_REFLECTION_EMIT
5770
5771 void
5772 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5773 {
5774         MonoDynamicImage *image = moduleb->dynamic_image;
5775         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5776         if (!image) {
5777                 int module_count;
5778                 MonoImage **new_modules;
5779                 MonoImage *ass;
5780                 /*
5781                  * FIXME: we already created an image in mono_image_basic_init (), but
5782                  * we don't know which module it belongs to, since that is only 
5783                  * determined at assembly save time.
5784                  */
5785                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5786                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5787
5788                 moduleb->module.image = &image->image;
5789                 moduleb->dynamic_image = image;
5790                 register_module (mono_object_domain (moduleb), moduleb, image);
5791
5792                 /* register the module with the assembly */
5793                 ass = ab->dynamic_assembly->assembly.image;
5794                 module_count = ass->module_count;
5795                 new_modules = g_new0 (MonoImage *, module_count + 1);
5796
5797                 if (ass->modules)
5798                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5799                 new_modules [module_count] = &image->image;
5800                 mono_image_addref (&image->image);
5801
5802                 g_free (ass->modules);
5803                 ass->modules = new_modules;
5804                 ass->module_count ++;
5805         }
5806 }
5807
5808 #endif
5809
5810 /*
5811  * mono_assembly_get_object:
5812  * @domain: an app domain
5813  * @assembly: an assembly
5814  *
5815  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5816  */
5817 MonoReflectionAssembly*
5818 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5819 {
5820         static MonoClass *System_Reflection_Assembly;
5821         MonoReflectionAssembly *res;
5822         
5823         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5824         if (!System_Reflection_Assembly)
5825                 System_Reflection_Assembly = mono_class_from_name (
5826                         mono_defaults.corlib, "System.Reflection", "Assembly");
5827         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5828         res->assembly = assembly;
5829
5830         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5831 }
5832
5833
5834
5835 MonoReflectionModule*   
5836 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5837 {
5838         static MonoClass *System_Reflection_Module;
5839         MonoReflectionModule *res;
5840         char* basename;
5841         
5842         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5843         if (!System_Reflection_Module)
5844                 System_Reflection_Module = mono_class_from_name (
5845                         mono_defaults.corlib, "System.Reflection", "Module");
5846         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5847
5848         res->image = image;
5849         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5850
5851         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5852         basename = g_path_get_basename (image->name);
5853         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5854         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5855         
5856         g_free (basename);
5857
5858         if (image->assembly->image == image) {
5859                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5860         } else {
5861                 int i;
5862                 res->token = 0;
5863                 if (image->assembly->image->modules) {
5864                         for (i = 0; i < image->assembly->image->module_count; i++) {
5865                                 if (image->assembly->image->modules [i] == image)
5866                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5867                         }
5868                         g_assert (res->token);
5869                 }
5870         }
5871
5872         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5873 }
5874
5875 MonoReflectionModule*   
5876 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5877 {
5878         static MonoClass *System_Reflection_Module;
5879         MonoReflectionModule *res;
5880         MonoTableInfo *table;
5881         guint32 cols [MONO_FILE_SIZE];
5882         const char *name;
5883         guint32 i, name_idx;
5884         const char *val;
5885         
5886         if (!System_Reflection_Module)
5887                 System_Reflection_Module = mono_class_from_name (
5888                         mono_defaults.corlib, "System.Reflection", "Module");
5889         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5890
5891         table = &image->tables [MONO_TABLE_FILE];
5892         g_assert (table_index < table->rows);
5893         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5894
5895         res->image = NULL;
5896         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5897         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5898
5899         /* Check whenever the row has a corresponding row in the moduleref table */
5900         table = &image->tables [MONO_TABLE_MODULEREF];
5901         for (i = 0; i < table->rows; ++i) {
5902                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5903                 val = mono_metadata_string_heap (image, name_idx);
5904                 if (strcmp (val, name) == 0)
5905                         res->image = image->modules [i];
5906         }
5907
5908         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5909         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5910         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5911         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5912         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5913
5914         return res;
5915 }
5916
5917 static gboolean
5918 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5919 {
5920         if ((t1->type != t2->type) ||
5921             (t1->byref != t2->byref))
5922                 return FALSE;
5923
5924         switch (t1->type) {
5925         case MONO_TYPE_VOID:
5926         case MONO_TYPE_BOOLEAN:
5927         case MONO_TYPE_CHAR:
5928         case MONO_TYPE_I1:
5929         case MONO_TYPE_U1:
5930         case MONO_TYPE_I2:
5931         case MONO_TYPE_U2:
5932         case MONO_TYPE_I4:
5933         case MONO_TYPE_U4:
5934         case MONO_TYPE_I8:
5935         case MONO_TYPE_U8:
5936         case MONO_TYPE_R4:
5937         case MONO_TYPE_R8:
5938         case MONO_TYPE_STRING:
5939         case MONO_TYPE_I:
5940         case MONO_TYPE_U:
5941         case MONO_TYPE_OBJECT:
5942         case MONO_TYPE_TYPEDBYREF:
5943                 return TRUE;
5944         case MONO_TYPE_VALUETYPE:
5945         case MONO_TYPE_CLASS:
5946         case MONO_TYPE_SZARRAY:
5947                 return t1->data.klass == t2->data.klass;
5948         case MONO_TYPE_PTR:
5949                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5950         case MONO_TYPE_ARRAY:
5951                 if (t1->data.array->rank != t2->data.array->rank)
5952                         return FALSE;
5953                 return t1->data.array->eklass == t2->data.array->eklass;
5954         case MONO_TYPE_GENERICINST: {
5955                 int i;
5956                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5957                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5958                 if (i1->type_argc != i2->type_argc)
5959                         return FALSE;
5960                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5961                                                &t2->data.generic_class->container_class->byval_arg))
5962                         return FALSE;
5963                 /* FIXME: we should probably just compare the instance pointers directly.  */
5964                 for (i = 0; i < i1->type_argc; ++i) {
5965                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5966                                 return FALSE;
5967                 }
5968                 return TRUE;
5969         }
5970         case MONO_TYPE_VAR:
5971         case MONO_TYPE_MVAR:
5972                 return t1->data.generic_param == t2->data.generic_param;
5973         default:
5974                 g_error ("implement type compare for %0x!", t1->type);
5975                 return FALSE;
5976         }
5977
5978         return FALSE;
5979 }
5980
5981 static guint
5982 mymono_metadata_type_hash (MonoType *t1)
5983 {
5984         guint hash;
5985
5986         hash = t1->type;
5987
5988         hash |= t1->byref << 6; /* do not collide with t1->type values */
5989         switch (t1->type) {
5990         case MONO_TYPE_VALUETYPE:
5991         case MONO_TYPE_CLASS:
5992         case MONO_TYPE_SZARRAY:
5993                 /* check if the distribution is good enough */
5994                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5995         case MONO_TYPE_PTR:
5996                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5997         case MONO_TYPE_GENERICINST: {
5998                 int i;
5999                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6000                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6001                 hash *= 13;
6002                 for (i = 0; i < inst->type_argc; ++i) {
6003                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6004                         hash *= 13;
6005                 }
6006                 return hash;
6007         }
6008         }
6009         return hash;
6010 }
6011
6012 static MonoReflectionGenericClass*
6013 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6014 {
6015         static MonoClass *System_Reflection_MonoGenericClass;
6016         MonoReflectionGenericClass *res;
6017         MonoClass *klass, *gklass;
6018
6019         if (!System_Reflection_MonoGenericClass) {
6020                 System_Reflection_MonoGenericClass = mono_class_from_name (
6021                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6022                 g_assert (System_Reflection_MonoGenericClass);
6023         }
6024
6025         klass = mono_class_from_mono_type (geninst);
6026         gklass = klass->generic_class->container_class;
6027
6028         mono_class_init (klass);
6029
6030 #ifdef HAVE_SGEN_GC
6031         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6032 #else
6033         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6034 #endif
6035
6036         res->type.type = geninst;
6037         g_assert (gklass->reflection_info);
6038         g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6039         MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6040
6041         return res;
6042 }
6043
6044 static gboolean
6045 verify_safe_for_managed_space (MonoType *type)
6046 {
6047         switch (type->type) {
6048 #ifdef DEBUG_HARDER
6049         case MONO_TYPE_ARRAY:
6050                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6051         case MONO_TYPE_PTR:
6052                 return verify_safe_for_managed_space (type->data.type);
6053         case MONO_TYPE_SZARRAY:
6054                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6055         case MONO_TYPE_GENERICINST: {
6056                 MonoGenericInst *inst = type->data.generic_class->inst;
6057                 int i;
6058                 if (!inst->is_open)
6059                         break;
6060                 for (i = 0; i < inst->type_argc; ++i)
6061                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6062                                 return FALSE;
6063                 break;
6064         }
6065 #endif
6066         case MONO_TYPE_VAR:
6067         case MONO_TYPE_MVAR:
6068                 return TRUE;
6069         }
6070         return TRUE;
6071 }
6072
6073 /*
6074  * mono_type_get_object:
6075  * @domain: an app domain
6076  * @type: a type
6077  *
6078  * Return an System.MonoType object representing the type @type.
6079  */
6080 MonoReflectionType*
6081 mono_type_get_object (MonoDomain *domain, MonoType *type)
6082 {
6083         MonoReflectionType *res;
6084         MonoClass *klass = mono_class_from_mono_type (type);
6085
6086         /*we must avoid using @type as it might have come
6087          * from a mono_metadata_type_dup and the caller
6088          * expects that is can be freed.
6089          * Using the right type from 
6090          */
6091         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6092
6093         /* void is very common */
6094         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6095                 return (MonoReflectionType*)domain->typeof_void;
6096
6097         /*
6098          * If the vtable of the given class was already created, we can use
6099          * the MonoType from there and avoid all locking and hash table lookups.
6100          * 
6101          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6102          * that the resulting object is diferent.   
6103          */
6104         if (type == &klass->byval_arg && !klass->image->dynamic) {
6105                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6106                 if (vtable && vtable->type)
6107                         return vtable->type;
6108         }
6109
6110         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6111         mono_domain_lock (domain);
6112         if (!domain->type_hash)
6113                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6114                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6115         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6116                 mono_domain_unlock (domain);
6117                 mono_loader_unlock ();
6118                 return res;
6119         }
6120         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6121         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6122                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6123                 mono_g_hash_table_insert (domain->type_hash, type, res);
6124                 mono_domain_unlock (domain);
6125                 mono_loader_unlock ();
6126                 return res;
6127         }
6128
6129         if (!verify_safe_for_managed_space (type)) {
6130                 mono_domain_unlock (domain);
6131                 mono_loader_unlock ();
6132                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6133         }
6134
6135         if (klass->reflection_info && !klass->wastypebuilder) {
6136                 /* g_assert_not_reached (); */
6137                 /* should this be considered an error condition? */
6138                 if (!type->byref) {
6139                         mono_domain_unlock (domain);
6140                         mono_loader_unlock ();
6141                         return klass->reflection_info;
6142                 }
6143         }
6144         // FIXME: Get rid of this, do it in the icalls for Type
6145         mono_class_init (klass);
6146 #ifdef HAVE_SGEN_GC
6147         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6148 #else
6149         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6150 #endif
6151         res->type = type;
6152         mono_g_hash_table_insert (domain->type_hash, type, res);
6153
6154         if (type->type == MONO_TYPE_VOID)
6155                 MONO_OBJECT_SETREF (domain, typeof_void, res);
6156
6157         mono_domain_unlock (domain);
6158         mono_loader_unlock ();
6159         return res;
6160 }
6161
6162 /*
6163  * mono_method_get_object:
6164  * @domain: an app domain
6165  * @method: a method
6166  * @refclass: the reflected type (can be NULL)
6167  *
6168  * Return an System.Reflection.MonoMethod object representing the method @method.
6169  */
6170 MonoReflectionMethod*
6171 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6172 {
6173         /*
6174          * We use the same C representation for methods and constructors, but the type 
6175          * name in C# is different.
6176          */
6177         static MonoClass *System_Reflection_MonoMethod = NULL;
6178         static MonoClass *System_Reflection_MonoCMethod = NULL;
6179         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6180         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6181         MonoClass *klass;
6182         MonoReflectionMethod *ret;
6183
6184         /*
6185          * Don't let static RGCTX invoke wrappers get into
6186          * MonoReflectionMethods.
6187          */
6188         if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6189                 method = mono_marshal_method_from_wrapper (method);
6190
6191         if (method->is_inflated) {
6192                 MonoReflectionGenericMethod *gret;
6193
6194                 refclass = method->klass;
6195                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6196                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6197                         if (!System_Reflection_MonoGenericCMethod)
6198                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6199                         klass = System_Reflection_MonoGenericCMethod;
6200                 } else {
6201                         if (!System_Reflection_MonoGenericMethod)
6202                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6203                         klass = System_Reflection_MonoGenericMethod;
6204                 }
6205                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6206                 gret->method.method = method;
6207                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6208                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6209                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6210         }
6211
6212         if (!refclass)
6213                 refclass = method->klass;
6214
6215         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6216         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6217                 if (!System_Reflection_MonoCMethod)
6218                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6219                 klass = System_Reflection_MonoCMethod;
6220         }
6221         else {
6222                 if (!System_Reflection_MonoMethod)
6223                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6224                 klass = System_Reflection_MonoMethod;
6225         }
6226         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6227         ret->method = method;
6228         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6229         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6230 }
6231
6232 /*
6233  * mono_method_clear_object:
6234  *
6235  *   Clear the cached reflection objects for the dynamic method METHOD.
6236  */
6237 void
6238 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6239 {
6240         g_assert (method->dynamic);
6241
6242         clear_cached_object (domain, method, method->klass);
6243         /* Added by mono_param_get_objects () */
6244         clear_cached_object (domain, &(method->signature), NULL);
6245 }
6246
6247 /*
6248  * mono_field_get_object:
6249  * @domain: an app domain
6250  * @klass: a type
6251  * @field: a field
6252  *
6253  * Return an System.Reflection.MonoField object representing the field @field
6254  * in class @klass.
6255  */
6256 MonoReflectionField*
6257 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6258 {
6259         MonoReflectionField *res;
6260         static MonoClass *monofield_klass;
6261
6262         CHECK_OBJECT (MonoReflectionField *, field, klass);
6263         if (!monofield_klass)
6264                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6265         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6266         res->klass = klass;
6267         res->field = field;
6268         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6269         if (is_field_on_inst (field))
6270                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6271         else
6272                 res->attrs = field->type->attrs;
6273         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6274         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6275 }
6276
6277 /*
6278  * mono_property_get_object:
6279  * @domain: an app domain
6280  * @klass: a type
6281  * @property: a property
6282  *
6283  * Return an System.Reflection.MonoProperty object representing the property @property
6284  * in class @klass.
6285  */
6286 MonoReflectionProperty*
6287 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6288 {
6289         MonoReflectionProperty *res;
6290         static MonoClass *monoproperty_klass;
6291
6292         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6293         if (!monoproperty_klass)
6294                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6295         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6296         res->klass = klass;
6297         res->property = property;
6298         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6299 }
6300
6301 /*
6302  * mono_event_get_object:
6303  * @domain: an app domain
6304  * @klass: a type
6305  * @event: a event
6306  *
6307  * Return an System.Reflection.MonoEvent object representing the event @event
6308  * in class @klass.
6309  */
6310 MonoReflectionEvent*
6311 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6312 {
6313         MonoReflectionEvent *res;
6314         MonoReflectionMonoEvent *mono_event;
6315         static MonoClass *monoevent_klass;
6316
6317         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6318         if (!monoevent_klass)
6319                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6320         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6321         mono_event->klass = klass;
6322         mono_event->event = event;
6323         res = (MonoReflectionEvent*)mono_event;
6324         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6325 }
6326
6327 /**
6328  * mono_get_reflection_missing_object:
6329  * @domain: Domain where the object lives
6330  *
6331  * Returns the System.Reflection.Missing.Value singleton object
6332  * (of type System.Reflection.Missing).
6333  *
6334  * Used as the value for ParameterInfo.DefaultValue when Optional
6335  * is present
6336  */
6337 static MonoObject *
6338 mono_get_reflection_missing_object (MonoDomain *domain)
6339 {
6340         MonoObject *obj;
6341         static MonoClassField *missing_value_field = NULL;
6342         
6343         if (!missing_value_field) {
6344                 MonoClass *missing_klass;
6345                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6346                 mono_class_init (missing_klass);
6347                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6348                 g_assert (missing_value_field);
6349         }
6350         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6351         g_assert (obj);
6352         return obj;
6353 }
6354
6355 static MonoObject*
6356 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6357 {
6358         if (!*dbnull)
6359                 *dbnull = mono_get_dbnull_object (domain);
6360         return *dbnull;
6361 }
6362
6363 static MonoObject*
6364 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6365 {
6366         if (!*reflection_missing)
6367                 *reflection_missing = mono_get_reflection_missing_object (domain);
6368         return *reflection_missing;
6369 }
6370
6371 /*
6372  * mono_param_get_objects:
6373  * @domain: an app domain
6374  * @method: a method
6375  *
6376  * Return an System.Reflection.ParameterInfo array object representing the parameters
6377  * in the method @method.
6378  */
6379 MonoArray*
6380 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6381 {
6382         static MonoClass *System_Reflection_ParameterInfo;
6383         static MonoClass *System_Reflection_ParameterInfo_array;
6384         MonoArray *res = NULL;
6385         MonoReflectionMethod *member = NULL;
6386         MonoReflectionParameter *param = NULL;
6387         char **names, **blobs = NULL;
6388         guint32 *types = NULL;
6389         MonoType *type = NULL;
6390         MonoObject *dbnull = NULL;
6391         MonoObject *missing = NULL;
6392         MonoMarshalSpec **mspecs;
6393         MonoMethodSignature *sig;
6394         MonoVTable *pinfo_vtable;
6395         int i;
6396
6397         if (!System_Reflection_ParameterInfo_array) {
6398                 MonoClass *klass;
6399
6400                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6401                 mono_memory_barrier ();
6402                 System_Reflection_ParameterInfo = klass; 
6403         
6404                 klass = mono_array_class_get (klass, 1);
6405                 mono_memory_barrier ();
6406                 System_Reflection_ParameterInfo_array = klass;
6407         }
6408         
6409         if (!mono_method_signature (method)->param_count)
6410                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6411
6412         /* Note: the cache is based on the address of the signature into the method
6413          * since we already cache MethodInfos with the method as keys.
6414          */
6415         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6416
6417         sig = mono_method_signature (method);
6418         member = mono_method_get_object (domain, method, refclass);
6419         names = g_new (char *, sig->param_count);
6420         mono_method_get_param_names (method, (const char **) names);
6421
6422         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6423         mono_method_get_marshal_info (method, mspecs);
6424
6425         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6426         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6427         for (i = 0; i < sig->param_count; ++i) {
6428                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6429                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6430                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6431                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6432                 param->PositionImpl = i;
6433                 param->AttrsImpl = sig->params [i]->attrs;
6434
6435                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6436                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6437                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6438                         else
6439                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6440                 } else {
6441
6442                         if (!blobs) {
6443                                 blobs = g_new0 (char *, sig->param_count);
6444                                 types = g_new0 (guint32, sig->param_count);
6445                                 get_default_param_value_blobs (method, blobs, types); 
6446                         }
6447
6448                         /* Build MonoType for the type from the Constant Table */
6449                         if (!type)
6450                                 type = g_new0 (MonoType, 1);
6451                         type->type = types [i];
6452                         type->data.klass = NULL;
6453                         if (types [i] == MONO_TYPE_CLASS)
6454                                 type->data.klass = mono_defaults.object_class;
6455                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6456                                 /* For enums, types [i] contains the base type */
6457
6458                                         type->type = MONO_TYPE_VALUETYPE;
6459                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6460                         } else
6461                                 type->data.klass = mono_class_from_mono_type (type);
6462
6463                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6464
6465                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6466                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6467                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6468                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6469                                 else
6470                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6471                         }
6472                         
6473                 }
6474
6475                 if (mspecs [i + 1])
6476                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6477                 
6478                 mono_array_setref (res, i, param);
6479         }
6480         g_free (names);
6481         g_free (blobs);
6482         g_free (types);
6483         g_free (type);
6484
6485         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6486                 if (mspecs [i])
6487                         mono_metadata_free_marshal_spec (mspecs [i]);
6488         g_free (mspecs);
6489         
6490         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6491 }
6492
6493 MonoArray*
6494 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6495 {
6496         return mono_param_get_objects_internal (domain, method, NULL);
6497 }
6498
6499 /*
6500  * mono_method_body_get_object:
6501  * @domain: an app domain
6502  * @method: a method
6503  *
6504  * Return an System.Reflection.MethodBody object representing the method @method.
6505  */
6506 MonoReflectionMethodBody*
6507 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6508 {
6509         static MonoClass *System_Reflection_MethodBody = NULL;
6510         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6511         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6512         MonoReflectionMethodBody *ret;
6513         MonoMethodNormal *mn;
6514         MonoMethodHeader *header;
6515         guint32 method_rva, local_var_sig_token;
6516     char *ptr;
6517         unsigned char format, flags;
6518         int i;
6519
6520         if (!System_Reflection_MethodBody)
6521                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6522         if (!System_Reflection_LocalVariableInfo)
6523                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6524         if (!System_Reflection_ExceptionHandlingClause)
6525                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6526
6527         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6528
6529         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6530                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6531             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6532             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6533                 return NULL;
6534         mn = (MonoMethodNormal *)method;
6535         header = mono_method_get_header (method);
6536         
6537         /* Obtain local vars signature token */
6538         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6539         ptr = mono_image_rva_map (method->klass->image, method_rva);
6540         flags = *(const unsigned char *) ptr;
6541         format = flags & METHOD_HEADER_FORMAT_MASK;
6542         switch (format){
6543         case METHOD_HEADER_TINY_FORMAT:
6544         case METHOD_HEADER_TINY_FORMAT1:
6545                 local_var_sig_token = 0;
6546                 break;
6547         case METHOD_HEADER_FAT_FORMAT:
6548                 ptr += 2;
6549                 ptr += 2;
6550                 ptr += 4;
6551                 local_var_sig_token = read32 (ptr);
6552                 break;
6553         default:
6554                 g_assert_not_reached ();
6555         }
6556
6557         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6558
6559         ret->init_locals = header->init_locals;
6560         ret->max_stack = header->max_stack;
6561         ret->local_var_sig_token = local_var_sig_token;
6562         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6563         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6564
6565         /* Locals */
6566         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6567         for (i = 0; i < header->num_locals; ++i) {
6568                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6569                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6570                 info->is_pinned = header->locals [i]->pinned;
6571                 info->local_index = i;
6572                 mono_array_setref (ret->locals, i, info);
6573         }
6574
6575         /* Exceptions */
6576         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6577         for (i = 0; i < header->num_clauses; ++i) {
6578                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6579                 MonoExceptionClause *clause = &header->clauses [i];
6580
6581                 info->flags = clause->flags;
6582                 info->try_offset = clause->try_offset;
6583                 info->try_length = clause->try_len;
6584                 info->handler_offset = clause->handler_offset;
6585                 info->handler_length = clause->handler_len;
6586                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6587                         info->filter_offset = clause->data.filter_offset;
6588                 else if (clause->data.catch_class)
6589                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6590
6591                 mono_array_setref (ret->clauses, i, info);
6592         }
6593
6594         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6595         return ret;
6596 }
6597
6598 /**
6599  * mono_get_dbnull_object:
6600  * @domain: Domain where the object lives
6601  *
6602  * Returns the System.DBNull.Value singleton object
6603  *
6604  * Used as the value for ParameterInfo.DefaultValue 
6605  */
6606 MonoObject *
6607 mono_get_dbnull_object (MonoDomain *domain)
6608 {
6609         MonoObject *obj;
6610         static MonoClassField *dbnull_value_field = NULL;
6611         
6612         if (!dbnull_value_field) {
6613                 MonoClass *dbnull_klass;
6614                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6615                 mono_class_init (dbnull_klass);
6616                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6617                 g_assert (dbnull_value_field);
6618         }
6619         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6620         g_assert (obj);
6621         return obj;
6622 }
6623
6624 static void
6625 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6626 {
6627         guint32 param_index, i, lastp, crow = 0;
6628         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6629         gint32 idx;
6630
6631         MonoClass *klass = method->klass;
6632         MonoImage *image = klass->image;
6633         MonoMethodSignature *methodsig = mono_method_signature (method);
6634
6635         MonoTableInfo *constt;
6636         MonoTableInfo *methodt;
6637         MonoTableInfo *paramt;
6638
6639         if (!methodsig->param_count)
6640                 return;
6641
6642         mono_class_init (klass);
6643
6644         if (klass->image->dynamic) {
6645                 MonoReflectionMethodAux *aux;
6646                 if (method->is_inflated)
6647                         method = ((MonoMethodInflated*)method)->declaring;
6648                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6649                 if (aux && aux->param_defaults) {
6650                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6651                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6652                 }
6653                 return;
6654         }
6655
6656         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6657         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6658         constt = &image->tables [MONO_TABLE_CONSTANT];
6659
6660         idx = mono_method_get_index (method) - 1;
6661         g_assert (idx != -1);
6662
6663         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6664         if (idx + 1 < methodt->rows)
6665                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6666         else
6667                 lastp = paramt->rows + 1;
6668
6669         for (i = param_index; i < lastp; ++i) {
6670                 guint32 paramseq;
6671
6672                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6673                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6674
6675                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
6676                         continue;
6677
6678                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6679                 if (!crow) {
6680                         continue;
6681                 }
6682         
6683                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6684                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6685                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6686         }
6687
6688         return;
6689 }
6690
6691 static MonoObject *
6692 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6693 {
6694         void *retval;
6695         MonoClass *klass;
6696         MonoObject *object;
6697         MonoType *basetype = type;
6698
6699         if (!blob)
6700                 return NULL;
6701         
6702         klass = mono_class_from_mono_type (type);
6703         if (klass->valuetype) {
6704                 object = mono_object_new (domain, klass);
6705                 retval = ((gchar *) object + sizeof (MonoObject));
6706                 if (klass->enumtype)
6707                         basetype = mono_class_enum_basetype (klass);
6708         } else {
6709                 retval = &object;
6710         }
6711                         
6712         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6713                 return object;
6714         else
6715                 return NULL;
6716 }
6717
6718 static int
6719 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6720         int found_sep;
6721         char *s;
6722
6723         memset (assembly, 0, sizeof (MonoAssemblyName));
6724         assembly->name = p;
6725         assembly->culture = "";
6726         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6727
6728         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6729                 p++;
6730         found_sep = 0;
6731         while (g_ascii_isspace (*p) || *p == ',') {
6732                 *p++ = 0;
6733                 found_sep = 1;
6734                 continue;
6735         }
6736         /* failed */
6737         if (!found_sep)
6738                 return 1;
6739         while (*p) {
6740                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6741                         p += 8;
6742                         assembly->major = strtoul (p, &s, 10);
6743                         if (s == p || *s != '.')
6744                                 return 1;
6745                         p = ++s;
6746                         assembly->minor = strtoul (p, &s, 10);
6747                         if (s == p || *s != '.')
6748                                 return 1;
6749                         p = ++s;
6750                         assembly->build = strtoul (p, &s, 10);
6751                         if (s == p || *s != '.')
6752                                 return 1;
6753                         p = ++s;
6754                         assembly->revision = strtoul (p, &s, 10);
6755                         if (s == p)
6756                                 return 1;
6757                         p = s;
6758                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6759                         p += 8;
6760                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6761                                 assembly->culture = "";
6762                                 p += 7;
6763                         } else {
6764                                 assembly->culture = p;
6765                                 while (*p && *p != ',') {
6766                                         p++;
6767                                 }
6768                         }
6769                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6770                         p += 15;
6771                         if (strncmp (p, "null", 4) == 0) {
6772                                 p += 4;
6773                         } else {
6774                                 int len;
6775                                 gchar *start = p;
6776                                 while (*p && *p != ',') {
6777                                         p++;
6778                                 }
6779                                 len = (p - start + 1);
6780                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6781                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6782                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
6783                         }
6784                 } else {
6785                         while (*p && *p != ',')
6786                                 p++;
6787                 }
6788                 found_sep = 0;
6789                 while (g_ascii_isspace (*p) || *p == ',') {
6790                         *p++ = 0;
6791                         found_sep = 1;
6792                         continue;
6793                 }
6794                 /* failed */
6795                 if (!found_sep)
6796                         return 1;
6797         }
6798
6799         return 0;
6800 }
6801
6802 /*
6803  * mono_reflection_parse_type:
6804  * @name: type name
6805  *
6806  * Parse a type name as accepted by the GetType () method and output the info
6807  * extracted in the info structure.
6808  * the name param will be mangled, so, make a copy before passing it to this function.
6809  * The fields in info will be valid until the memory pointed to by name is valid.
6810  *
6811  * See also mono_type_get_name () below.
6812  *
6813  * Returns: 0 on parse error.
6814  */
6815 static int
6816 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6817                              MonoTypeNameParse *info)
6818 {
6819         char *start, *p, *w, *temp, *last_point, *startn;
6820         int in_modifiers = 0;
6821         int isbyref = 0, rank, arity = 0, i;
6822
6823         start = p = w = name;
6824
6825         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6826         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6827         info->name = info->name_space = NULL;
6828         info->nested = NULL;
6829         info->modifiers = NULL;
6830         info->type_arguments = NULL;
6831
6832         /* last_point separates the namespace from the name */
6833         last_point = NULL;
6834         /* Skips spaces */
6835         while (*p == ' ') p++, start++, w++, name++;
6836
6837         while (*p) {
6838                 switch (*p) {
6839                 case '+':
6840                         *p = 0; /* NULL terminate the name */
6841                         startn = p + 1;
6842                         info->nested = g_list_append (info->nested, startn);
6843                         /* we have parsed the nesting namespace + name */
6844                         if (info->name)
6845                                 break;
6846                         if (last_point) {
6847                                 info->name_space = start;
6848                                 *last_point = 0;
6849                                 info->name = last_point + 1;
6850                         } else {
6851                                 info->name_space = (char *)"";
6852                                 info->name = start;
6853                         }
6854                         break;
6855                 case '.':
6856                         last_point = p;
6857                         break;
6858                 case '\\':
6859                         ++p;
6860                         break;
6861                 case '&':
6862                 case '*':
6863                 case '[':
6864                 case ',':
6865                 case ']':
6866                         in_modifiers = 1;
6867                         break;
6868                 case '`':
6869                         ++p;
6870                         i = strtol (p, &temp, 10);
6871                         arity += i;
6872                         if (p == temp)
6873                                 return 0;
6874                         p = temp-1;
6875                         break;
6876                 default:
6877                         break;
6878                 }
6879                 if (in_modifiers)
6880                         break;
6881                 // *w++ = *p++;
6882                 p++;
6883         }
6884         
6885         if (!info->name) {
6886                 if (last_point) {
6887                         info->name_space = start;
6888                         *last_point = 0;
6889                         info->name = last_point + 1;
6890                 } else {
6891                         info->name_space = (char *)"";
6892                         info->name = start;
6893                 }
6894         }
6895         while (*p) {
6896                 switch (*p) {
6897                 case '&':
6898                         if (isbyref) /* only one level allowed by the spec */
6899                                 return 0;
6900                         isbyref = 1;
6901                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6902                         *p++ = 0;
6903                         break;
6904                 case '*':
6905                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6906                         *p++ = 0;
6907                         break;
6908                 case '[':
6909                         if (arity != 0) {
6910                                 *p++ = 0;
6911                                 info->type_arguments = g_ptr_array_new ();
6912                                 for (i = 0; i < arity; i++) {
6913                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6914                                         gboolean fqname = FALSE;
6915
6916                                         g_ptr_array_add (info->type_arguments, subinfo);
6917
6918                                         if (*p == '[') {
6919                                                 p++;
6920                                                 fqname = TRUE;
6921                                         }
6922
6923                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6924                                                 return 0;
6925
6926                                         if (fqname) {
6927                                                 char *aname;
6928
6929                                                 if (*p != ',')
6930                                                         return 0;
6931                                                 *p++ = 0;
6932
6933                                                 aname = p;
6934                                                 while (*p && (*p != ']'))
6935                                                         p++;
6936
6937                                                 if (*p != ']')
6938                                                         return 0;
6939
6940                                                 *p++ = 0;
6941                                                 while (*aname) {
6942                                                         if (g_ascii_isspace (*aname)) {
6943                                                                 ++aname;
6944                                                                 continue;
6945                                                         }
6946                                                         break;
6947                                                 }
6948                                                 if (!*aname ||
6949                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6950                                                         return 0;
6951                                         }
6952
6953                                         if (i + 1 < arity) {
6954                                                 if (*p != ',')
6955                                                         return 0;
6956                                         } else {
6957                                                 if (*p != ']')
6958                                                         return 0;
6959                                         }
6960                                         *p++ = 0;
6961                                 }
6962
6963                                 arity = 0;
6964                                 break;
6965                         }
6966                         rank = 1;
6967                         *p++ = 0;
6968                         while (*p) {
6969                                 if (*p == ']')
6970                                         break;
6971                                 if (*p == ',')
6972                                         rank++;
6973                                 else if (*p == '*') /* '*' means unknown lower bound */
6974                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6975                                 else
6976                                         return 0;
6977                                 ++p;
6978                         }
6979                         if (*p++ != ']')
6980                                 return 0;
6981                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6982                         break;
6983                 case ']':
6984                         if (is_recursed)
6985                                 goto end;
6986                         return 0;
6987                 case ',':
6988                         if (is_recursed)
6989                                 goto end;
6990                         *p++ = 0;
6991                         while (*p) {
6992                                 if (g_ascii_isspace (*p)) {
6993                                         ++p;
6994                                         continue;
6995                                 }
6996                                 break;
6997                         }
6998                         if (!*p)
6999                                 return 0; /* missing assembly name */
7000                         if (!assembly_name_to_aname (&info->assembly, p))
7001                                 return 0;
7002                         break;
7003                 default:
7004                         return 0;
7005                 }
7006                 if (info->assembly.name)
7007                         break;
7008         }
7009         // *w = 0; /* terminate class name */
7010  end:
7011         if (!info->name || !*info->name)
7012                 return 0;
7013         if (endptr)
7014                 *endptr = p;
7015         /* add other consistency checks */
7016         return 1;
7017 }
7018
7019 int
7020 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7021 {
7022         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7023 }
7024
7025 static MonoType*
7026 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7027 {
7028         gboolean type_resolve = FALSE;
7029         MonoType *type;
7030         MonoImage *rootimage = image;
7031
7032         if (info->assembly.name) {
7033                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7034                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7035                         /* 
7036                          * This could happen in the AOT compiler case when the search hook is not
7037                          * installed.
7038                          */
7039                         assembly = image->assembly;
7040                 if (!assembly) {
7041                         /* then we must load the assembly ourselve - see #60439 */
7042                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7043                         if (!assembly)
7044                                 return NULL;
7045                 }
7046                 image = assembly->image;
7047         } else if (!image) {
7048                 image = mono_defaults.corlib;
7049         }
7050
7051         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7052         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7053                 image = mono_defaults.corlib;
7054                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7055         }
7056
7057         return type;
7058 }
7059
7060 static MonoType*
7061 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7062 {
7063         MonoClass *klass;
7064         GList *mod;
7065         int modval;
7066         gboolean bounded = FALSE;
7067         
7068         if (!image)
7069                 image = mono_defaults.corlib;
7070
7071         if (ignorecase)
7072                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7073         else
7074                 klass = mono_class_from_name (image, info->name_space, info->name);
7075         if (!klass)
7076                 return NULL;
7077         for (mod = info->nested; mod; mod = mod->next) {
7078                 gpointer iter = NULL;
7079                 MonoClass *parent;
7080
7081                 parent = klass;
7082                 mono_class_init (parent);
7083
7084                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7085                         if (ignorecase) {
7086                                 if (g_strcasecmp (klass->name, mod->data) == 0)
7087                                         break;
7088                         } else {
7089                                 if (strcmp (klass->name, mod->data) == 0)
7090                                         break;
7091                         }
7092                 }
7093                 if (!klass)
7094                         break;
7095         }
7096         if (!klass)
7097                 return NULL;
7098         mono_class_init (klass);
7099
7100         if (info->type_arguments) {
7101                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7102                 MonoReflectionType *the_type;
7103                 MonoType *instance;
7104                 int i;
7105
7106                 for (i = 0; i < info->type_arguments->len; i++) {
7107                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7108
7109                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7110                         if (!type_args [i]) {
7111                                 g_free (type_args);
7112                                 return NULL;
7113                         }
7114                 }
7115
7116                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7117
7118                 instance = mono_reflection_bind_generic_parameters (
7119                         the_type, info->type_arguments->len, type_args);
7120
7121                 g_free (type_args);
7122                 if (!instance)
7123                         return NULL;
7124
7125                 klass = mono_class_from_mono_type (instance);
7126         }
7127
7128         for (mod = info->modifiers; mod; mod = mod->next) {
7129                 modval = GPOINTER_TO_UINT (mod->data);
7130                 if (!modval) { /* byref: must be last modifier */
7131                         return &klass->this_arg;
7132                 } else if (modval == -1) {
7133                         klass = mono_ptr_class_get (&klass->byval_arg);
7134                 } else if (modval == -2) {
7135                         bounded = TRUE;
7136                 } else { /* array rank */
7137                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7138                 }
7139                 mono_class_init (klass);
7140         }
7141
7142         return &klass->byval_arg;
7143 }
7144
7145 /*
7146  * mono_reflection_get_type:
7147  * @image: a metadata context
7148  * @info: type description structure
7149  * @ignorecase: flag for case-insensitive string compares
7150  * @type_resolve: whenever type resolve was already tried
7151  *
7152  * Build a MonoType from the type description in @info.
7153  * 
7154  */
7155
7156 MonoType*
7157 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7158         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7159 }
7160
7161 static MonoType*
7162 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7163 {
7164         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7165         MonoType *type;
7166         int i;
7167
7168         g_assert (assembly->dynamic);
7169
7170         /* Enumerate all modules */
7171
7172         type = NULL;
7173         if (abuilder->modules) {
7174                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7175                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7176                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7177                         if (type)
7178                                 break;
7179                 }
7180         }
7181
7182         if (!type && abuilder->loaded_modules) {
7183                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7184                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7185                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7186                         if (type)
7187                                 break;
7188                 }
7189         }
7190
7191         return type;
7192 }
7193         
7194 MonoType*
7195 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7196 {
7197         MonoType *type;
7198         MonoReflectionAssembly *assembly;
7199         GString *fullName;
7200         GList *mod;
7201
7202         if (image && image->dynamic)
7203                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7204         else
7205                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7206         if (type)
7207                 return type;
7208         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7209                 return NULL;
7210
7211         if (type_resolve) {
7212                 if (*type_resolve) 
7213                         return NULL;
7214                 else
7215                         *type_resolve = TRUE;
7216         }
7217         
7218         /* Reconstruct the type name */
7219         fullName = g_string_new ("");
7220         if (info->name_space && (info->name_space [0] != '\0'))
7221                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7222         else
7223                 g_string_printf (fullName, info->name);
7224         for (mod = info->nested; mod; mod = mod->next)
7225                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7226
7227         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7228         if (assembly) {
7229                 if (assembly->assembly->dynamic)
7230                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7231                 else
7232                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7233                                                                                                           info, ignorecase);
7234         }
7235         g_string_free (fullName, TRUE);
7236         return type;
7237 }
7238
7239 void
7240 mono_reflection_free_type_info (MonoTypeNameParse *info)
7241 {
7242         g_list_free (info->modifiers);
7243         g_list_free (info->nested);
7244
7245         if (info->type_arguments) {
7246                 int i;
7247
7248                 for (i = 0; i < info->type_arguments->len; i++) {
7249                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7250
7251                         mono_reflection_free_type_info (subinfo);
7252                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7253                         g_free (subinfo);
7254                 }
7255
7256                 g_ptr_array_free (info->type_arguments, TRUE);
7257         }
7258 }
7259
7260 /*
7261  * mono_reflection_type_from_name:
7262  * @name: type name.
7263  * @image: a metadata context (can be NULL).
7264  *
7265  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7266  * it defaults to get the type from @image or, if @image is NULL or loading
7267  * from it fails, uses corlib.
7268  * 
7269  */
7270 MonoType*
7271 mono_reflection_type_from_name (char *name, MonoImage *image)
7272 {
7273         MonoType *type = NULL;
7274         MonoTypeNameParse info;
7275         char *tmp;
7276
7277         /* Make a copy since parse_type modifies its argument */
7278         tmp = g_strdup (name);
7279         
7280         /*g_print ("requested type %s\n", str);*/
7281         if (mono_reflection_parse_type (tmp, &info)) {
7282                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7283         }
7284
7285         g_free (tmp);
7286         mono_reflection_free_type_info (&info);
7287         return type;
7288 }
7289
7290 /*
7291  * mono_reflection_get_token:
7292  *
7293  *   Return the metadata token of OBJ which should be an object
7294  * representing a metadata element.
7295  */
7296 guint32
7297 mono_reflection_get_token (MonoObject *obj)
7298 {
7299         MonoClass *klass;
7300         guint32 token = 0;
7301
7302         klass = obj->vtable->klass;
7303
7304         if (strcmp (klass->name, "MethodBuilder") == 0) {
7305                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7306
7307                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7308         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7309                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7310
7311                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7312         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7313                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7314
7315                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7316                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7317         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7318                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7319                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7320         } else if (strcmp (klass->name, "MonoType") == 0) {
7321                 MonoReflectionType *tb = (MonoReflectionType *)obj;
7322                 token = mono_class_from_mono_type (tb->type)->type_token;
7323         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7324                    strcmp (klass->name, "MonoMethod") == 0 ||
7325                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7326                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7327                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7328                 if (m->method->is_inflated) {
7329                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7330                         return inflated->declaring->token;
7331                 } else {
7332                         token = m->method->token;
7333                 }
7334         } else if (strcmp (klass->name, "MonoField") == 0) {
7335                 MonoReflectionField *f = (MonoReflectionField*)obj;
7336
7337                 if (is_field_on_inst (f->field)) {
7338                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7339                         int field_index = f->field - dgclass->fields;
7340                         MonoObject *obj;
7341
7342                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7343                         obj = dgclass->field_objects [field_index];
7344                         return mono_reflection_get_token (obj);
7345                 }
7346                 token = mono_class_get_field_token (f->field);
7347         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7348                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7349
7350                 token = mono_class_get_property_token (p->property);
7351         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7352                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7353
7354                 token = mono_class_get_event_token (p->event);
7355         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7356                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7357
7358                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7359         } else if (strcmp (klass->name, "Module") == 0) {
7360                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7361
7362                 token = m->token;
7363         } else if (strcmp (klass->name, "Assembly") == 0) {
7364                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7365         } else {
7366                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7367                 MonoException *ex = mono_get_exception_not_implemented (msg);
7368                 g_free (msg);
7369                 mono_raise_exception (ex);
7370         }
7371
7372         return token;
7373 }
7374
7375 static void*
7376 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7377 {
7378         int slen, type = t->type;
7379         MonoClass *tklass = t->data.klass;
7380
7381 handle_enum:
7382         switch (type) {
7383         case MONO_TYPE_U1:
7384         case MONO_TYPE_I1:
7385         case MONO_TYPE_BOOLEAN: {
7386                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7387                 *bval = *p;
7388                 *end = p + 1;
7389                 return bval;
7390         }
7391         case MONO_TYPE_CHAR:
7392         case MONO_TYPE_U2:
7393         case MONO_TYPE_I2: {
7394                 guint16 *val = g_malloc (sizeof (guint16));
7395                 *val = read16 (p);
7396                 *end = p + 2;
7397                 return val;
7398         }
7399 #if SIZEOF_VOID_P == 4
7400         case MONO_TYPE_U:
7401         case MONO_TYPE_I:
7402 #endif
7403         case MONO_TYPE_R4:
7404         case MONO_TYPE_U4:
7405         case MONO_TYPE_I4: {
7406                 guint32 *val = g_malloc (sizeof (guint32));
7407                 *val = read32 (p);
7408                 *end = p + 4;
7409                 return val;
7410         }
7411 #if SIZEOF_VOID_P == 8
7412         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7413         case MONO_TYPE_I:
7414 #endif
7415         case MONO_TYPE_U8:
7416         case MONO_TYPE_I8: {
7417                 guint64 *val = g_malloc (sizeof (guint64));
7418                 *val = read64 (p);
7419                 *end = p + 8;
7420                 return val;
7421         }
7422         case MONO_TYPE_R8: {
7423                 double *val = g_malloc (sizeof (double));
7424                 readr8 (p, val);
7425                 *end = p + 8;
7426                 return val;
7427         }
7428         case MONO_TYPE_VALUETYPE:
7429                 if (t->data.klass->enumtype) {
7430                         type = mono_class_enum_basetype (t->data.klass)->type;
7431                         goto handle_enum;
7432                 } else {
7433                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7434                 }
7435                 break;
7436         case MONO_TYPE_STRING:
7437                 if (*p == (char)0xFF) {
7438                         *end = p + 1;
7439                         return NULL;
7440                 }
7441                 slen = mono_metadata_decode_value (p, &p);
7442                 *end = p + slen;
7443                 return mono_string_new_len (mono_domain_get (), p, slen);
7444         case MONO_TYPE_CLASS: {
7445                 char *n;
7446                 MonoType *t;
7447                 if (*p == (char)0xFF) {
7448                         *end = p + 1;
7449                         return NULL;
7450                 }
7451 handle_type:
7452                 slen = mono_metadata_decode_value (p, &p);
7453                 n = g_memdup (p, slen + 1);
7454                 n [slen] = 0;
7455                 t = mono_reflection_type_from_name (n, image);
7456                 if (!t)
7457                         g_warning ("Cannot load type '%s'", n);
7458                 g_free (n);
7459                 *end = p + slen;
7460                 if (t)
7461                         return mono_type_get_object (mono_domain_get (), t);
7462                 else
7463                         return NULL;
7464         }
7465         case MONO_TYPE_OBJECT: {
7466                 char subt = *p++;
7467                 MonoObject *obj;
7468                 MonoClass *subc = NULL;
7469                 void *val;
7470
7471                 if (subt == 0x50) {
7472                         goto handle_type;
7473                 } else if (subt == 0x0E) {
7474                         type = MONO_TYPE_STRING;
7475                         goto handle_enum;
7476                 } else if (subt == 0x1D) {
7477                         MonoType simple_type = {{0}};
7478                         int etype = *p;
7479                         p ++;
7480
7481                         if (etype == 0x51)
7482                                 /* See Partition II, Appendix B3 */
7483                                 etype = MONO_TYPE_OBJECT;
7484                         type = MONO_TYPE_SZARRAY;
7485                         simple_type.type = etype;
7486                         tklass = mono_class_from_mono_type (&simple_type);
7487                         goto handle_enum;
7488                 } else if (subt == 0x55) {
7489                         char *n;
7490                         MonoType *t;
7491                         slen = mono_metadata_decode_value (p, &p);
7492                         n = g_memdup (p, slen + 1);
7493                         n [slen] = 0;
7494                         t = mono_reflection_type_from_name (n, image);
7495                         if (!t)
7496                                 g_error ("Cannot load type '%s'", n);
7497                         g_free (n);
7498                         p += slen;
7499                         subc = mono_class_from_mono_type (t);
7500                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7501                         MonoType simple_type = {{0}};
7502                         simple_type.type = subt;
7503                         subc = mono_class_from_mono_type (&simple_type);
7504                 } else {
7505                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7506                 }
7507                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7508                 obj = mono_object_new (mono_domain_get (), subc);
7509                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7510                 g_free (val);
7511                 return obj;
7512         }
7513         case MONO_TYPE_SZARRAY: {
7514                 MonoArray *arr;
7515                 guint32 i, alen, basetype;
7516                 alen = read32 (p);
7517                 p += 4;
7518                 if (alen == 0xffffffff) {
7519                         *end = p;
7520                         return NULL;
7521                 }
7522                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7523                 basetype = tklass->byval_arg.type;
7524                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7525                         basetype = mono_class_enum_basetype (tklass)->type;
7526                 switch (basetype)
7527                 {
7528                         case MONO_TYPE_U1:
7529                         case MONO_TYPE_I1:
7530                         case MONO_TYPE_BOOLEAN:
7531                                 for (i = 0; i < alen; i++) {
7532                                         MonoBoolean val = *p++;
7533                                         mono_array_set (arr, MonoBoolean, i, val);
7534                                 }
7535                                 break;
7536                         case MONO_TYPE_CHAR:
7537                         case MONO_TYPE_U2:
7538                         case MONO_TYPE_I2:
7539                                 for (i = 0; i < alen; i++) {
7540                                         guint16 val = read16 (p);
7541                                         mono_array_set (arr, guint16, i, val);
7542                                         p += 2;
7543                                 }
7544                                 break;
7545                         case MONO_TYPE_R4:
7546                         case MONO_TYPE_U4:
7547                         case MONO_TYPE_I4:
7548                                 for (i = 0; i < alen; i++) {
7549                                         guint32 val = read32 (p);
7550                                         mono_array_set (arr, guint32, i, val);
7551                                         p += 4;
7552                                 }
7553                                 break;
7554                         case MONO_TYPE_R8:
7555                                 for (i = 0; i < alen; i++) {
7556                                         double val;
7557                                         readr8 (p, &val);
7558                                         mono_array_set (arr, double, i, val);
7559                                         p += 8;
7560                                 }
7561                                 break;
7562                         case MONO_TYPE_U8:
7563                         case MONO_TYPE_I8:
7564                                 for (i = 0; i < alen; i++) {
7565                                         guint64 val = read64 (p);
7566                                         mono_array_set (arr, guint64, i, val);
7567                                         p += 8;
7568                                 }
7569                                 break;
7570                         case MONO_TYPE_CLASS:
7571                         case MONO_TYPE_OBJECT:
7572                         case MONO_TYPE_STRING:
7573                                 for (i = 0; i < alen; i++) {
7574                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7575                                         mono_array_setref (arr, i, item);
7576                                 }
7577                                 break;
7578                         default:
7579                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7580                 }
7581                 *end=p;
7582                 return arr;
7583         }
7584         default:
7585                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7586         }
7587         return NULL;
7588 }
7589
7590 static MonoObject*
7591 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7592 {
7593         static MonoClass *klass;
7594         static MonoMethod *ctor;
7595         MonoObject *retval;
7596         void *params [2], *unboxed;
7597
7598         if (!klass)
7599                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7600         if (!ctor)
7601                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7602         
7603         params [0] = mono_type_get_object (mono_domain_get (), t);
7604         params [1] = val;
7605         retval = mono_object_new (mono_domain_get (), klass);
7606         unboxed = mono_object_unbox (retval);
7607         mono_runtime_invoke (ctor, unboxed, params, NULL);
7608
7609         return retval;
7610 }
7611
7612 static MonoObject*
7613 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7614 {
7615         static MonoClass *klass;
7616         static MonoMethod *ctor;
7617         MonoObject *retval;
7618         void *unboxed, *params [2];
7619
7620         if (!klass)
7621                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7622         if (!ctor)
7623                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7624
7625         params [0] = minfo;
7626         params [1] = typedarg;
7627         retval = mono_object_new (mono_domain_get (), klass);
7628         unboxed = mono_object_unbox (retval);
7629         mono_runtime_invoke (ctor, unboxed, params, NULL);
7630
7631         return retval;
7632 }
7633
7634 static gboolean
7635 type_is_reference (MonoType *type)
7636 {
7637         switch (type->type) {
7638         case MONO_TYPE_BOOLEAN:
7639         case MONO_TYPE_CHAR:
7640         case MONO_TYPE_U:
7641         case MONO_TYPE_I:
7642         case MONO_TYPE_U1:
7643         case MONO_TYPE_I1:
7644         case MONO_TYPE_U2:
7645         case MONO_TYPE_I2:
7646         case MONO_TYPE_U4:
7647         case MONO_TYPE_I4:
7648         case MONO_TYPE_U8:
7649         case MONO_TYPE_I8:
7650         case MONO_TYPE_R8:
7651         case MONO_TYPE_R4:
7652         case MONO_TYPE_VALUETYPE:
7653                 return FALSE;
7654         default:
7655                 return TRUE;
7656         }
7657 }
7658
7659 static void
7660 free_param_data (MonoMethodSignature *sig, void **params) {
7661         int i;
7662         for (i = 0; i < sig->param_count; ++i) {
7663                 if (!type_is_reference (sig->params [i]))
7664                         g_free (params [i]);
7665         }
7666 }
7667
7668 /*
7669  * Find the field index in the metadata FieldDef table.
7670  */
7671 static guint32
7672 find_field_index (MonoClass *klass, MonoClassField *field) {
7673         int i;
7674
7675         for (i = 0; i < klass->field.count; ++i) {
7676                 if (field == &klass->fields [i])
7677                         return klass->field.first + 1 + i;
7678         }
7679         return 0;
7680 }
7681
7682 /*
7683  * Find the property index in the metadata Property table.
7684  */
7685 static guint32
7686 find_property_index (MonoClass *klass, MonoProperty *property) {
7687         int i;
7688
7689         for (i = 0; i < klass->ext->property.count; ++i) {
7690                 if (property == &klass->ext->properties [i])
7691                         return klass->ext->property.first + 1 + i;
7692         }
7693         return 0;
7694 }
7695
7696 /*
7697  * Find the event index in the metadata Event table.
7698  */
7699 static guint32
7700 find_event_index (MonoClass *klass, MonoEvent *event) {
7701         int i;
7702
7703         for (i = 0; i < klass->ext->event.count; ++i) {
7704                 if (event == &klass->ext->events [i])
7705                         return klass->ext->event.first + 1 + i;
7706         }
7707         return 0;
7708 }
7709
7710 static MonoObject*
7711 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7712 {
7713         const char *p = (const char*)data;
7714         const char *named;
7715         guint32 i, j, num_named;
7716         MonoObject *attr;
7717         void *params_buf [32];
7718         void **params;
7719         MonoMethodSignature *sig;
7720
7721         mono_class_init (method->klass);
7722
7723         if (len == 0) {
7724                 attr = mono_object_new (mono_domain_get (), method->klass);
7725                 mono_runtime_invoke (method, attr, NULL, NULL);
7726                 return attr;
7727         }
7728
7729         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7730                 return NULL;
7731
7732         /*g_print ("got attr %s\n", method->klass->name);*/
7733
7734         sig = mono_method_signature (method);
7735         if (sig->param_count < 32)
7736                 params = params_buf;
7737         else
7738                 /* Allocate using GC so it gets GC tracking */
7739                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7740
7741         /* skip prolog */
7742         p += 2;
7743         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7744                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7745         }
7746
7747         named = p;
7748         attr = mono_object_new (mono_domain_get (), method->klass);
7749         mono_runtime_invoke (method, attr, params, NULL);
7750         free_param_data (method->signature, params);
7751         num_named = read16 (named);
7752         named += 2;
7753         for (j = 0; j < num_named; j++) {
7754                 gint name_len;
7755                 char *name, named_type, data_type;
7756                 named_type = *named++;
7757                 data_type = *named++; /* type of data */
7758                 if (data_type == MONO_TYPE_SZARRAY)
7759                         data_type = *named++;
7760                 if (data_type == MONO_TYPE_ENUM) {
7761                         gint type_len;
7762                         char *type_name;
7763                         type_len = mono_metadata_decode_blob_size (named, &named);
7764                         type_name = g_malloc (type_len + 1);
7765                         memcpy (type_name, named, type_len);
7766                         type_name [type_len] = 0;
7767                         named += type_len;
7768                         /* FIXME: lookup the type and check type consistency */
7769                         g_free (type_name);
7770                 }
7771                 name_len = mono_metadata_decode_blob_size (named, &named);
7772                 name = g_malloc (name_len + 1);
7773                 memcpy (name, named, name_len);
7774                 name [name_len] = 0;
7775                 named += name_len;
7776                 if (named_type == 0x53) {
7777                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7778                         void *val = load_cattr_value (image, field->type, named, &named);
7779                         mono_field_set_value (attr, field, val);
7780                         if (!type_is_reference (field->type))
7781                                 g_free (val);
7782                 } else if (named_type == 0x54) {
7783                         MonoProperty *prop;
7784                         void *pparams [1];
7785                         MonoType *prop_type;
7786
7787                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7788                         /* can we have more that 1 arg in a custom attr named property? */
7789                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7790                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7791                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7792                         mono_property_set_value (prop, attr, pparams, NULL);
7793                         if (!type_is_reference (prop_type))
7794                                 g_free (pparams [0]);
7795                 }
7796                 g_free (name);
7797         }
7798
7799         if (params != params_buf)
7800                 mono_gc_free_fixed (params);
7801
7802         return attr;
7803 }
7804
7805 static MonoObject*
7806 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7807 {
7808         MonoArray *typedargs, *namedargs;
7809         MonoClass *attrklass;
7810         static MonoMethod *ctor;
7811         MonoDomain *domain;
7812         MonoObject *attr;
7813         const char *p = (const char*)data;
7814         const char *named;
7815         guint32 i, j, num_named;
7816         void *params [3];
7817
7818         mono_class_init (method->klass);
7819
7820         if (!ctor)
7821                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7822
7823         domain = mono_domain_get ();
7824         if (len == 0) {
7825                 /* This is for Attributes with no parameters */
7826                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7827                 params [0] = mono_method_get_object (domain, method, NULL);
7828                 params [1] = params [2] = NULL;
7829                 mono_runtime_invoke (method, attr, params, NULL);
7830                 return attr;
7831         }
7832
7833         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7834                 return NULL;
7835
7836         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7837         
7838         /* skip prolog */
7839         p += 2;
7840         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7841                 MonoObject *obj, *typedarg;
7842                 void *val;
7843
7844                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7845                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7846                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7847                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7848                 mono_array_setref (typedargs, i, typedarg);
7849
7850                 if (!type_is_reference (mono_method_signature (method)->params [i]))
7851                         g_free (val);
7852         }
7853
7854         named = p;
7855         num_named = read16 (named);
7856         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7857         named += 2;
7858         attrklass = method->klass;
7859         for (j = 0; j < num_named; j++) {
7860                 gint name_len;
7861                 char *name, named_type, data_type;
7862                 named_type = *named++;
7863                 data_type = *named++; /* type of data */
7864                 if (data_type == MONO_TYPE_SZARRAY)
7865                         data_type = *named++;
7866                 if (data_type == MONO_TYPE_ENUM) {
7867                         gint type_len;
7868                         char *type_name;
7869                         type_len = mono_metadata_decode_blob_size (named, &named);
7870                         type_name = g_malloc (type_len + 1);
7871                         memcpy (type_name, named, type_len);
7872                         type_name [type_len] = 0;
7873                         named += type_len;
7874                         /* FIXME: lookup the type and check type consistency */
7875                         g_free (type_name);
7876                 }
7877                 name_len = mono_metadata_decode_blob_size (named, &named);
7878                 name = g_malloc (name_len + 1);
7879                 memcpy (name, named, name_len);
7880                 name [name_len] = 0;
7881                 named += name_len;
7882                 if (named_type == 0x53) {
7883                         MonoObject *obj, *typedarg, *namedarg;
7884                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7885                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7886                         
7887                         minfo = mono_field_get_object (domain, NULL, field);
7888                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7889                         typedarg = create_cattr_typed_arg (field->type, obj);
7890                         namedarg = create_cattr_named_arg (minfo, typedarg);
7891                         mono_array_setref (namedargs, j, namedarg);
7892                         if (!type_is_reference (field->type))
7893                                 g_free (val);
7894                 } else if (named_type == 0x54) {
7895                         MonoObject *obj, *typedarg, *namedarg;
7896                         MonoType *prop_type;
7897                         void *val, *minfo;
7898                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7899
7900                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7901                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7902                         minfo =  mono_property_get_object (domain, NULL, prop);
7903                         val = load_cattr_value (image, prop_type, named, &named);
7904                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7905                         typedarg = create_cattr_typed_arg (prop_type, obj);
7906                         namedarg = create_cattr_named_arg (minfo, typedarg);
7907                         mono_array_setref (namedargs, j, namedarg);
7908                         if (!type_is_reference (prop_type))
7909                                 g_free (val);
7910                 }
7911                 g_free (name);
7912         }
7913         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7914         params [0] = mono_method_get_object (domain, method, NULL);
7915         params [1] = typedargs;
7916         params [2] = namedargs;
7917         mono_runtime_invoke (ctor, attr, params, NULL);
7918         return attr;
7919 }
7920
7921 MonoArray*
7922 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7923 {
7924         MonoArray *result;
7925         MonoObject *attr;
7926         int i;
7927
7928         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7929         for (i = 0; i < cinfo->num_attrs; ++i) {
7930                 if (!cinfo->attrs [i].ctor)
7931                         /* The cattr type is not finished yet */
7932                         /* We should include the type name but cinfo doesn't contain it */
7933                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7934                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7935                 mono_array_setref (result, i, attr);
7936         }
7937         return result;
7938 }
7939
7940 static MonoArray*
7941 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7942 {
7943         MonoArray *result;
7944         MonoObject *attr;
7945         int i, n;
7946
7947         n = 0;
7948         for (i = 0; i < cinfo->num_attrs; ++i) {
7949                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7950                         n ++;
7951         }
7952
7953         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
7954         n = 0;
7955         for (i = 0; i < cinfo->num_attrs; ++i) {
7956                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7957                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7958                         mono_array_setref (result, n, attr);
7959                         n ++;
7960                 }
7961         }
7962         return result;
7963 }
7964
7965 static MonoArray*
7966 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7967 {
7968         MonoArray *result;
7969         MonoObject *attr;
7970         int i;
7971         
7972         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7973         for (i = 0; i < cinfo->num_attrs; ++i) {
7974                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7975                 mono_array_setref (result, i, attr);
7976         }
7977         return result;
7978 }
7979
7980 /**
7981  * mono_custom_attrs_from_index:
7982  *
7983  * Returns: NULL if no attributes are found or if a loading error occurs.
7984  */
7985 MonoCustomAttrInfo*
7986 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7987 {
7988         guint32 mtoken, i, len;
7989         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7990         MonoTableInfo *ca;
7991         MonoCustomAttrInfo *ainfo;
7992         GList *tmp, *list = NULL;
7993         const char *data;
7994
7995         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7996
7997         i = mono_metadata_custom_attrs_from_index (image, idx);
7998         if (!i)
7999                 return NULL;
8000         i --;
8001         while (i < ca->rows) {
8002                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8003                         break;
8004                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8005                 ++i;
8006         }
8007         len = g_list_length (list);
8008         if (!len)
8009                 return NULL;
8010         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
8011         ainfo->num_attrs = len;
8012         ainfo->image = image;
8013         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8014                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8015                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8016                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8017                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8018                         mtoken |= MONO_TOKEN_METHOD_DEF;
8019                         break;
8020                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8021                         mtoken |= MONO_TOKEN_MEMBER_REF;
8022                         break;
8023                 default:
8024                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8025                         break;
8026                 }
8027                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8028                 if (!ainfo->attrs [i].ctor) {
8029                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8030                         g_list_free (list);
8031                         g_free (ainfo);
8032                         return NULL;
8033                 }
8034                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8035                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8036                 ainfo->attrs [i].data = (guchar*)data;
8037         }
8038         g_list_free (list);
8039
8040         return ainfo;
8041 }
8042
8043 MonoCustomAttrInfo*
8044 mono_custom_attrs_from_method (MonoMethod *method)
8045 {
8046         guint32 idx;
8047
8048         /*
8049          * An instantiated method has the same cattrs as the generic method definition.
8050          *
8051          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8052          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8053          */
8054         if (method->is_inflated)
8055                 method = ((MonoMethodInflated *) method)->declaring;
8056         
8057         if (method->dynamic || method->klass->image->dynamic)
8058                 return lookup_custom_attr (method->klass->image, method);
8059
8060         idx = mono_method_get_index (method);
8061         idx <<= MONO_CUSTOM_ATTR_BITS;
8062         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8063         return mono_custom_attrs_from_index (method->klass->image, idx);
8064 }
8065
8066 MonoCustomAttrInfo*
8067 mono_custom_attrs_from_class (MonoClass *klass)
8068 {
8069         guint32 idx;
8070
8071         if (klass->generic_class)
8072                 klass = klass->generic_class->container_class;
8073
8074         if (klass->image->dynamic)
8075                 return lookup_custom_attr (klass->image, klass);
8076
8077         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8078                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8079                 idx <<= MONO_CUSTOM_ATTR_BITS;
8080                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8081         } else {
8082                 idx = mono_metadata_token_index (klass->type_token);
8083                 idx <<= MONO_CUSTOM_ATTR_BITS;
8084                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8085         }
8086         return mono_custom_attrs_from_index (klass->image, idx);
8087 }
8088
8089 MonoCustomAttrInfo*
8090 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8091 {
8092         guint32 idx;
8093         
8094         if (assembly->image->dynamic)
8095                 return lookup_custom_attr (assembly->image, assembly);
8096         idx = 1; /* there is only one assembly */
8097         idx <<= MONO_CUSTOM_ATTR_BITS;
8098         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8099         return mono_custom_attrs_from_index (assembly->image, idx);
8100 }
8101
8102 static MonoCustomAttrInfo*
8103 mono_custom_attrs_from_module (MonoImage *image)
8104 {
8105         guint32 idx;
8106         
8107         if (image->dynamic)
8108                 return lookup_custom_attr (image, image);
8109         idx = 1; /* there is only one module */
8110         idx <<= MONO_CUSTOM_ATTR_BITS;
8111         idx |= MONO_CUSTOM_ATTR_MODULE;
8112         return mono_custom_attrs_from_index (image, idx);
8113 }
8114
8115 MonoCustomAttrInfo*
8116 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8117 {
8118         guint32 idx;
8119         
8120         if (klass->image->dynamic) {
8121                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8122                 return lookup_custom_attr (klass->image, property);
8123         }
8124         idx = find_property_index (klass, property);
8125         idx <<= MONO_CUSTOM_ATTR_BITS;
8126         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8127         return mono_custom_attrs_from_index (klass->image, idx);
8128 }
8129
8130 MonoCustomAttrInfo*
8131 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8132 {
8133         guint32 idx;
8134         
8135         if (klass->image->dynamic) {
8136                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8137                 return lookup_custom_attr (klass->image, event);
8138         }
8139         idx = find_event_index (klass, event);
8140         idx <<= MONO_CUSTOM_ATTR_BITS;
8141         idx |= MONO_CUSTOM_ATTR_EVENT;
8142         return mono_custom_attrs_from_index (klass->image, idx);
8143 }
8144
8145 MonoCustomAttrInfo*
8146 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8147 {
8148         guint32 idx;
8149         if (klass->image->dynamic) {
8150                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8151                 return lookup_custom_attr (klass->image, field);
8152         }
8153         idx = find_field_index (klass, field);
8154         idx <<= MONO_CUSTOM_ATTR_BITS;
8155         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8156         return mono_custom_attrs_from_index (klass->image, idx);
8157 }
8158
8159 MonoCustomAttrInfo*
8160 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8161 {
8162         MonoTableInfo *ca;
8163         guint32 i, idx, method_index;
8164         guint32 param_list, param_last, param_pos, found;
8165         MonoImage *image;
8166         MonoReflectionMethodAux *aux;
8167
8168         /*
8169          * An instantiated method has the same cattrs as the generic method definition.
8170          *
8171          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8172          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8173          */
8174         if (method->is_inflated)
8175                 method = ((MonoMethodInflated *) method)->declaring;
8176
8177         if (method->klass->image->dynamic) {
8178                 MonoCustomAttrInfo *res, *ainfo;
8179                 int size;
8180
8181                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8182                 if (!aux || !aux->param_cattr)
8183                         return NULL;
8184
8185                 /* Need to copy since it will be freed later */
8186                 ainfo = aux->param_cattr [param];
8187                 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8188                 res = g_malloc0 (size);
8189                 memcpy (res, ainfo, size);
8190                 return res;
8191         }
8192
8193         image = method->klass->image;
8194         method_index = mono_method_get_index (method);
8195         ca = &image->tables [MONO_TABLE_METHOD];
8196
8197         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8198         if (method_index == ca->rows) {
8199                 ca = &image->tables [MONO_TABLE_PARAM];
8200                 param_last = ca->rows + 1;
8201         } else {
8202                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8203                 ca = &image->tables [MONO_TABLE_PARAM];
8204         }
8205         found = FALSE;
8206         for (i = param_list; i < param_last; ++i) {
8207                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8208                 if (param_pos == param) {
8209                         found = TRUE;
8210                         break;
8211                 }
8212         }
8213         if (!found)
8214                 return NULL;
8215         idx = i;
8216         idx <<= MONO_CUSTOM_ATTR_BITS;
8217         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8218         return mono_custom_attrs_from_index (image, idx);
8219 }
8220
8221 gboolean
8222 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8223 {
8224         int i;
8225         MonoClass *klass;
8226         for (i = 0; i < ainfo->num_attrs; ++i) {
8227                 klass = ainfo->attrs [i].ctor->klass;
8228                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8229                         return TRUE;
8230         }
8231         return FALSE;
8232 }
8233
8234 MonoObject*
8235 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8236 {
8237         int i, attr_index;
8238         MonoClass *klass;
8239         MonoArray *attrs;
8240
8241         attr_index = -1;
8242         for (i = 0; i < ainfo->num_attrs; ++i) {
8243                 klass = ainfo->attrs [i].ctor->klass;
8244                 if (mono_class_has_parent (klass, attr_klass)) {
8245                         attr_index = i;
8246                         break;
8247                 }
8248         }
8249         if (attr_index == -1)
8250                 return NULL;
8251
8252         attrs = mono_custom_attrs_construct (ainfo);
8253         if (attrs)
8254                 return mono_array_get (attrs, MonoObject*, attr_index);
8255         else
8256                 return NULL;
8257 }
8258
8259 /*
8260  * mono_reflection_get_custom_attrs_info:
8261  * @obj: a reflection object handle
8262  *
8263  * Return the custom attribute info for attributes defined for the
8264  * reflection handle @obj. The objects.
8265  *
8266  * FIXME this function leaks like a sieve for SRE objects.
8267  */
8268 MonoCustomAttrInfo*
8269 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8270 {
8271         MonoClass *klass;
8272         MonoCustomAttrInfo *cinfo = NULL;
8273         
8274         klass = obj->vtable->klass;
8275         if (klass == mono_defaults.monotype_class) {
8276                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8277                 klass = mono_class_from_mono_type (rtype->type);
8278                 cinfo = mono_custom_attrs_from_class (klass);
8279         } else if (strcmp ("Assembly", klass->name) == 0) {
8280                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8281                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8282         } else if (strcmp ("Module", klass->name) == 0) {
8283                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8284                 cinfo = mono_custom_attrs_from_module (module->image);
8285         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8286                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8287                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8288         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8289                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8290                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8291         } else if (strcmp ("MonoField", klass->name) == 0) {
8292                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8293                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8294         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8295                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8296                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8297         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8298                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8299                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8300         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8301                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8302                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8303                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8304         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8305                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8306                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8307         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8308                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8309                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8310         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8311                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8312                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8313         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8314                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8315                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8316         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8317                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8318                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8319         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8320                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8321                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8322         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8323                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8324                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8325         } else { /* handle other types here... */
8326                 g_error ("get custom attrs not yet supported for %s", klass->name);
8327         }
8328
8329         return cinfo;
8330 }
8331
8332 /*
8333  * mono_reflection_get_custom_attrs_by_type:
8334  * @obj: a reflection object handle
8335  *
8336  * Return an array with all the custom attributes defined of the
8337  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8338  * of that type are returned. The objects are fully build. Return NULL if a loading error
8339  * occurs.
8340  */
8341 MonoArray*
8342 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8343 {
8344         MonoArray *result;
8345         MonoCustomAttrInfo *cinfo;
8346
8347         cinfo = mono_reflection_get_custom_attrs_info (obj);
8348         if (cinfo) {
8349                 if (attr_klass)
8350                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8351                 else
8352                         result = mono_custom_attrs_construct (cinfo);
8353                 if (!cinfo->cached)
8354                         mono_custom_attrs_free (cinfo);
8355         } else {
8356                 if (mono_loader_get_last_error ())
8357                         return NULL;
8358                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8359         }
8360
8361         return result;
8362 }
8363
8364 /*
8365  * mono_reflection_get_custom_attrs:
8366  * @obj: a reflection object handle
8367  *
8368  * Return an array with all the custom attributes defined of the
8369  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8370  * occurs.
8371  */
8372 MonoArray*
8373 mono_reflection_get_custom_attrs (MonoObject *obj)
8374 {
8375         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8376 }
8377
8378 /*
8379  * mono_reflection_get_custom_attrs_data:
8380  * @obj: a reflection obj handle
8381  *
8382  * Returns an array of System.Reflection.CustomAttributeData,
8383  * which include information about attributes reflected on
8384  * types loaded using the Reflection Only methods
8385  */
8386 MonoArray*
8387 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8388 {
8389         MonoArray *result;
8390         MonoCustomAttrInfo *cinfo;
8391
8392         cinfo = mono_reflection_get_custom_attrs_info (obj);
8393         if (cinfo) {
8394                 result = mono_custom_attrs_data_construct (cinfo);
8395                 if (!cinfo->cached)
8396                         mono_custom_attrs_free (cinfo);
8397         } else
8398                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8399
8400         return result;
8401 }
8402
8403 static MonoReflectionType*
8404 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8405 {
8406         MonoMethod *method_get_underlying_system_type;
8407
8408         method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8409                                                                             mono_class_get_method_from_name (mono_object_class (t),
8410                                                                                                              "get_UnderlyingSystemType",
8411                                                                                                              0));
8412         return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8413 }
8414
8415 static MonoType*
8416 mono_reflection_type_get_handle (MonoReflectionType* t)
8417 {
8418         if (t->type)
8419             return t->type;
8420
8421         t = mono_reflection_type_get_underlying_system_type (t);
8422         if (t)
8423             return t->type;
8424
8425         return NULL;
8426 }
8427
8428 /**
8429  * LOCKING: Assumes the loader lock is held.
8430  */
8431 static MonoMethodSignature*
8432 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8433         MonoMethodSignature *sig;
8434         int count, i;
8435
8436         count = parameters? mono_array_length (parameters): 0;
8437
8438         sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8439         sig->param_count = count;
8440         sig->sentinelpos = -1; /* FIXME */
8441         for (i = 0; i < count; ++i) {
8442                 MonoReflectionType *pt = mono_type_array_get (parameters, i);
8443                 sig->params [i] = mono_reflection_type_get_handle (pt);
8444         }
8445         return sig;
8446 }
8447
8448 /**
8449  * LOCKING: Assumes the loader lock is held.
8450  */
8451 static MonoMethodSignature*
8452 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8453         MonoMethodSignature *sig;
8454
8455         sig = parameters_to_signature (image, ctor->parameters);
8456         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8457         sig->ret = &mono_defaults.void_class->byval_arg;
8458         return sig;
8459 }
8460
8461 /**
8462  * LOCKING: Assumes the loader lock is held.
8463  */
8464 static MonoMethodSignature*
8465 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8466         MonoMethodSignature *sig;
8467
8468         sig = parameters_to_signature (image, method->parameters);
8469         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8470         sig->ret = method->rtype? monotype_cast (method->rtype)->type: &mono_defaults.void_class->byval_arg;
8471         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8472         return sig;
8473 }
8474
8475 static MonoMethodSignature*
8476 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8477         MonoMethodSignature *sig;
8478
8479         sig = parameters_to_signature (NULL, method->parameters);
8480         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8481         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8482         sig->generic_param_count = 0;
8483         return sig;
8484 }
8485
8486 static void
8487 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8488 {
8489         MonoClass *klass = mono_object_class (prop);
8490         if (strcmp (klass->name, "PropertyBuilder") == 0) {
8491                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8492                 *name = mono_string_to_utf8 (pb->name);
8493                 *type = monotype_cast (pb->type)->type;
8494         } else {
8495                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8496                 *name = g_strdup (p->property->name);
8497                 if (p->property->get)
8498                         *type = mono_method_signature (p->property->get)->ret;
8499                 else
8500                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8501         }
8502 }
8503
8504 static void
8505 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8506 {
8507         MonoClass *klass = mono_object_class (field);
8508         if (strcmp (klass->name, "FieldBuilder") == 0) {
8509                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8510                 *name = mono_string_to_utf8 (fb->name);
8511                 *type = monotype_cast (fb->type)->type;
8512         } else {
8513                 MonoReflectionField *f = (MonoReflectionField *)field;
8514                 *name = g_strdup (mono_field_get_name (f->field));
8515                 *type = f->field->type;
8516         }
8517 }
8518
8519 /*
8520  * Encode a value in a custom attribute stream of bytes.
8521  * The value to encode is either supplied as an object in argument val
8522  * (valuetypes are boxed), or as a pointer to the data in the
8523  * argument argval.
8524  * @type represents the type of the value
8525  * @buffer is the start of the buffer
8526  * @p the current position in the buffer
8527  * @buflen contains the size of the buffer and is used to return the new buffer size
8528  * if this needs to be realloced.
8529  * @retbuffer and @retp return the start and the position of the buffer
8530  */
8531 static void
8532 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8533 {
8534         MonoTypeEnum simple_type;
8535         
8536         if ((p-buffer) + 10 >= *buflen) {
8537                 char *newbuf;
8538                 *buflen *= 2;
8539                 newbuf = g_realloc (buffer, *buflen);
8540                 p = newbuf + (p-buffer);
8541                 buffer = newbuf;
8542         }
8543         if (!argval)
8544                 argval = ((char*)arg + sizeof (MonoObject));
8545         simple_type = type->type;
8546 handle_enum:
8547         switch (simple_type) {
8548         case MONO_TYPE_BOOLEAN:
8549         case MONO_TYPE_U1:
8550         case MONO_TYPE_I1:
8551                 *p++ = *argval;
8552                 break;
8553         case MONO_TYPE_CHAR:
8554         case MONO_TYPE_U2:
8555         case MONO_TYPE_I2:
8556                 swap_with_size (p, argval, 2, 1);
8557                 p += 2;
8558                 break;
8559         case MONO_TYPE_U4:
8560         case MONO_TYPE_I4:
8561         case MONO_TYPE_R4:
8562                 swap_with_size (p, argval, 4, 1);
8563                 p += 4;
8564                 break;
8565         case MONO_TYPE_R8:
8566 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8567                 p [0] = argval [4];
8568                 p [1] = argval [5];
8569                 p [2] = argval [6];
8570                 p [3] = argval [7];
8571                 p [4] = argval [0];
8572                 p [5] = argval [1];
8573                 p [6] = argval [2];
8574                 p [7] = argval [3];
8575 #else
8576                 swap_with_size (p, argval, 8, 1);
8577 #endif
8578                 p += 8;
8579                 break;
8580         case MONO_TYPE_U8:
8581         case MONO_TYPE_I8:
8582                 swap_with_size (p, argval, 8, 1);
8583                 p += 8;
8584                 break;
8585         case MONO_TYPE_VALUETYPE:
8586                 if (type->data.klass->enumtype) {
8587                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
8588                         goto handle_enum;
8589                 } else {
8590                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8591                 }
8592                 break;
8593         case MONO_TYPE_STRING: {
8594                 char *str;
8595                 guint32 slen;
8596                 if (!arg) {
8597                         *p++ = 0xFF;
8598                         break;
8599                 }
8600                 str = mono_string_to_utf8 ((MonoString*)arg);
8601                 slen = strlen (str);
8602                 if ((p-buffer) + 10 + slen >= *buflen) {
8603                         char *newbuf;
8604                         *buflen *= 2;
8605                         *buflen += slen;
8606                         newbuf = g_realloc (buffer, *buflen);
8607                         p = newbuf + (p-buffer);
8608                         buffer = newbuf;
8609                 }
8610                 mono_metadata_encode_value (slen, p, &p);
8611                 memcpy (p, str, slen);
8612                 p += slen;
8613                 g_free (str);
8614                 break;
8615         }
8616         case MONO_TYPE_CLASS: {
8617                 char *str;
8618                 guint32 slen;
8619                 MonoClass *k;
8620                 if (!arg) {
8621                         *p++ = 0xFF;
8622                         break;
8623                 }
8624                 k = mono_object_class (arg);
8625                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8626                         (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8627                         MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8628                         MonoClass *rtc;
8629                         
8630                         if (rt && (rtc = mono_object_class (rt)) &&
8631                                    (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8632                                     !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8633                                 arg = (MonoObject *) rt;
8634                                 k = rtc;
8635                         } else
8636                                 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8637                 }
8638 handle_type:
8639                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8640                 slen = strlen (str);
8641                 if ((p-buffer) + 10 + slen >= *buflen) {
8642                         char *newbuf;
8643                         *buflen *= 2;
8644                         *buflen += slen;
8645                         newbuf = g_realloc (buffer, *buflen);
8646                         p = newbuf + (p-buffer);
8647                         buffer = newbuf;
8648                 }
8649                 mono_metadata_encode_value (slen, p, &p);
8650                 memcpy (p, str, slen);
8651                 p += slen;
8652                 g_free (str);
8653                 break;
8654         }
8655         case MONO_TYPE_SZARRAY: {
8656                 int len, i;
8657                 MonoClass *eclass, *arg_eclass;
8658
8659                 if (!arg) {
8660                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8661                         break;
8662                 }
8663                 len = mono_array_length ((MonoArray*)arg);
8664                 *p++ = len & 0xff;
8665                 *p++ = (len >> 8) & 0xff;
8666                 *p++ = (len >> 16) & 0xff;
8667                 *p++ = (len >> 24) & 0xff;
8668                 *retp = p;
8669                 *retbuffer = buffer;
8670                 eclass = type->data.klass;
8671                 arg_eclass = mono_object_class (arg)->element_class;
8672
8673                 if (!eclass) {
8674                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8675                         eclass = mono_defaults.object_class;
8676                 }
8677                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8678                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8679                         int elsize = mono_class_array_element_size (arg_eclass);
8680                         for (i = 0; i < len; ++i) {
8681                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8682                                 elptr += elsize;
8683                         }
8684                 } else if (eclass->valuetype && arg_eclass->valuetype) {
8685                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8686                         int elsize = mono_class_array_element_size (eclass);
8687                         for (i = 0; i < len; ++i) {
8688                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8689                                 elptr += elsize;
8690                         }
8691                 } else {
8692                         for (i = 0; i < len; ++i) {
8693                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8694                         }
8695                 }
8696                 break;
8697         }
8698         case MONO_TYPE_OBJECT: {
8699                 MonoClass *klass;
8700                 char *str;
8701                 guint32 slen;
8702
8703                 /*
8704                  * The parameter type is 'object' but the type of the actual
8705                  * argument is not. So we have to add type information to the blob
8706                  * too. This is completely undocumented in the spec.
8707                  */
8708
8709                 if (arg == NULL) {
8710                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
8711                         *p++ = 0xFF;
8712                         break;
8713                 }
8714                 
8715                 klass = mono_object_class (arg);
8716
8717                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8718                         *p++ = 0x50;
8719                         goto handle_type;
8720                 } else if (klass->enumtype) {
8721                         *p++ = 0x55;
8722                 } else if (klass == mono_defaults.string_class) {
8723                         simple_type = MONO_TYPE_STRING;
8724                         *p++ = 0x0E;
8725                         goto handle_enum;
8726                 } else if (klass->rank == 1) {
8727                         *p++ = 0x1D;
8728                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8729                                 /* See Partition II, Appendix B3 */
8730                                 *p++ = 0x51;
8731                         else
8732                                 *p++ = klass->element_class->byval_arg.type;
8733                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8734                         break;
8735                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8736                         *p++ = simple_type = klass->byval_arg.type;
8737                         goto handle_enum;
8738                 } else {
8739                         g_error ("unhandled type in custom attr");
8740                 }
8741                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8742                 slen = strlen (str);
8743                 if ((p-buffer) + 10 + slen >= *buflen) {
8744                         char *newbuf;
8745                         *buflen *= 2;
8746                         *buflen += slen;
8747                         newbuf = g_realloc (buffer, *buflen);
8748                         p = newbuf + (p-buffer);
8749                         buffer = newbuf;
8750                 }
8751                 mono_metadata_encode_value (slen, p, &p);
8752                 memcpy (p, str, slen);
8753                 p += slen;
8754                 g_free (str);
8755                 simple_type = mono_class_enum_basetype (klass)->type;
8756                 goto handle_enum;
8757         }
8758         default:
8759                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8760         }
8761         *retp = p;
8762         *retbuffer = buffer;
8763 }
8764
8765 static void
8766 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8767 {
8768         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8769                 char *str = type_get_qualified_name (type, NULL);
8770                 int slen = strlen (str);
8771
8772                 *p++ = 0x55;
8773                 /*
8774                  * This seems to be optional...
8775                  * *p++ = 0x80;
8776                  */
8777                 mono_metadata_encode_value (slen, p, &p);
8778                 memcpy (p, str, slen);
8779                 p += slen;
8780                 g_free (str);
8781         } else if (type->type == MONO_TYPE_OBJECT) {
8782                 *p++ = 0x51;
8783         } else if (type->type == MONO_TYPE_CLASS) {
8784                 /* it should be a type: encode_cattr_value () has the check */
8785                 *p++ = 0x50;
8786         } else {
8787                 mono_metadata_encode_value (type->type, p, &p);
8788                 if (type->type == MONO_TYPE_SZARRAY)
8789                         /* See the examples in Partition VI, Annex B */
8790                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8791         }
8792
8793         *retp = p;
8794 }
8795
8796 static void
8797 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8798 {
8799         int len;
8800         /* Preallocate a large enough buffer */
8801         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8802                 char *str = type_get_qualified_name (type, NULL);
8803                 len = strlen (str);
8804                 g_free (str);
8805         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8806                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8807                 len = strlen (str);
8808                 g_free (str);
8809         } else {
8810                 len = 0;
8811         }
8812         len += strlen (name);
8813
8814         if ((p-buffer) + 20 + len >= *buflen) {
8815                 char *newbuf;
8816                 *buflen *= 2;
8817                 *buflen += len;
8818                 newbuf = g_realloc (buffer, *buflen);
8819                 p = newbuf + (p-buffer);
8820                 buffer = newbuf;
8821         }
8822
8823         encode_field_or_prop_type (type, p, &p);
8824
8825         len = strlen (name);
8826         mono_metadata_encode_value (len, p, &p);
8827         memcpy (p, name, len);
8828         p += len;
8829         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8830         *retp = p;
8831         *retbuffer = buffer;
8832 }
8833
8834 #ifndef DISABLE_REFLECTION_EMIT
8835
8836 /*
8837  * mono_reflection_get_custom_attrs_blob:
8838  * @ctor: custom attribute constructor
8839  * @ctorArgs: arguments o the constructor
8840  * @properties:
8841  * @propValues:
8842  * @fields:
8843  * @fieldValues:
8844  * 
8845  * Creates the blob of data that needs to be saved in the metadata and that represents
8846  * the custom attributed described by @ctor, @ctorArgs etc.
8847  * Returns: a Byte array representing the blob of data.
8848  */
8849 MonoArray*
8850 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
8851 {
8852         MonoArray *result;
8853         MonoMethodSignature *sig;
8854         MonoObject *arg;
8855         char *buffer, *p;
8856         guint32 buflen, i;
8857
8858         MONO_ARCH_SAVE_REGS;
8859
8860         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8861                 /* sig is freed later so allocate it in the heap */
8862                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8863         } else {
8864                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8865         }
8866
8867         g_assert (mono_array_length (ctorArgs) == sig->param_count);
8868         buflen = 256;
8869         p = buffer = g_malloc (buflen);
8870         /* write the prolog */
8871         *p++ = 1;
8872         *p++ = 0;
8873         for (i = 0; i < sig->param_count; ++i) {
8874                 arg = mono_array_get (ctorArgs, MonoObject*, i);
8875                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8876         }
8877         i = 0;
8878         if (properties)
8879                 i += mono_array_length (properties);
8880         if (fields)
8881                 i += mono_array_length (fields);
8882         *p++ = i & 0xff;
8883         *p++ = (i >> 8) & 0xff;
8884         if (properties) {
8885                 MonoObject *prop;
8886                 for (i = 0; i < mono_array_length (properties); ++i) {
8887                         MonoType *ptype;
8888                         char *pname;
8889
8890                         prop = mono_array_get (properties, gpointer, i);
8891                         get_prop_name_and_type (prop, &pname, &ptype);
8892                         *p++ = 0x54; /* PROPERTY signature */
8893                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8894                         g_free (pname);
8895                 }
8896         }
8897
8898         if (fields) {
8899                 MonoObject *field;
8900                 for (i = 0; i < mono_array_length (fields); ++i) {
8901                         MonoType *ftype;
8902                         char *fname;
8903
8904                         field = mono_array_get (fields, gpointer, i);
8905                         get_field_name_and_type (field, &fname, &ftype);
8906                         *p++ = 0x53; /* FIELD signature */
8907                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8908                         g_free (fname);
8909                 }
8910         }
8911
8912         g_assert (p - buffer <= buflen);
8913         buflen = p - buffer;
8914         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8915         p = mono_array_addr (result, char, 0);
8916         memcpy (p, buffer, buflen);
8917         g_free (buffer);
8918         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8919                 g_free (sig);
8920         return result;
8921 }
8922
8923 /*
8924  * mono_reflection_setup_internal_class:
8925  * @tb: a TypeBuilder object
8926  *
8927  * Creates a MonoClass that represents the TypeBuilder.
8928  * This is a trick that lets us simplify a lot of reflection code
8929  * (and will allow us to support Build and Run assemblies easier).
8930  */
8931 void
8932 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8933 {
8934         MonoClass *klass, *parent;
8935
8936         MONO_ARCH_SAVE_REGS;
8937
8938         CHECK_MONOTYPE (tb->parent);
8939
8940         mono_loader_lock ();
8941
8942         if (tb->parent) {
8943                 /* check so we can compile corlib correctly */
8944                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8945                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8946                         parent = monotype_cast (tb->parent)->type->data.klass;
8947                 } else {
8948                         parent = mono_class_from_mono_type (monotype_cast (tb->parent)->type);
8949                 }
8950         } else {
8951                 parent = NULL;
8952         }
8953         
8954         /* the type has already being created: it means we just have to change the parent */
8955         if (tb->type.type) {
8956                 klass = mono_class_from_mono_type (tb->type.type);
8957                 klass->parent = NULL;
8958                 /* fool mono_class_setup_parent */
8959                 klass->supertypes = NULL;
8960                 mono_class_setup_parent (klass, parent);
8961                 mono_class_setup_mono_type (klass);
8962                 mono_loader_unlock ();
8963                 return;
8964         }
8965
8966         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8967
8968         klass->image = &tb->module->dynamic_image->image;
8969
8970         klass->inited = 1; /* we lie to the runtime */
8971         klass->name = mono_string_to_utf8_image (klass->image, tb->name);
8972         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
8973         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8974         klass->flags = tb->attrs;
8975         
8976         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8977
8978         klass->element_class = klass;
8979
8980         MOVING_GC_REGISTER (&klass->reflection_info);
8981         klass->reflection_info = tb;
8982
8983         /* Put into cache so mono_class_get () will find it */
8984         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8985
8986         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8987                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8988
8989         if (parent != NULL) {
8990                 mono_class_setup_parent (klass, parent);
8991         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8992                 const char *old_n = klass->name;
8993                 /* trick to get relative numbering right when compiling corlib */
8994                 klass->name = "BuildingObject";
8995                 mono_class_setup_parent (klass, mono_defaults.object_class);
8996                 klass->name = old_n;
8997         }
8998
8999         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9000                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9001                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9002                 klass->instance_size = sizeof (MonoObject);
9003                 klass->size_inited = 1;
9004                 mono_class_setup_vtable_general (klass, NULL, 0);
9005         }
9006
9007         mono_class_setup_mono_type (klass);
9008
9009         mono_class_setup_supertypes (klass);
9010
9011         /*
9012          * FIXME: handle interfaces.
9013          */
9014
9015         tb->type.type = &klass->byval_arg;
9016
9017         if (tb->nesting_type) {
9018                 g_assert (tb->nesting_type->type);
9019                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9020         }
9021
9022         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9023
9024         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9025         
9026         mono_loader_unlock ();
9027 }
9028
9029 /*
9030  * mono_reflection_setup_generic_class:
9031  * @tb: a TypeBuilder object
9032  *
9033  * Setup the generic class before adding the first generic parameter.
9034  */
9035 void
9036 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9037 {
9038 }
9039
9040 /*
9041  * mono_reflection_create_generic_class:
9042  * @tb: a TypeBuilder object
9043  *
9044  * Creates the generic class after all generic parameters have been added.
9045  */
9046 void
9047 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9048 {
9049         MonoClass *klass;
9050         int count, i;
9051
9052         MONO_ARCH_SAVE_REGS;
9053
9054         klass = mono_class_from_mono_type (tb->type.type);
9055
9056         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9057
9058         if (klass->generic_container || (count == 0))
9059                 return;
9060
9061         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9062
9063         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9064
9065         klass->generic_container->owner.klass = klass;
9066         klass->generic_container->type_argc = count;
9067         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9068
9069         klass->is_generic = 1;
9070
9071         for (i = 0; i < count; i++) {
9072                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9073                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9074                 /*Make sure we are a diferent type instance */
9075                 klass->generic_container->type_params [i].owner = klass->generic_container;
9076                 klass->generic_container->type_params [i].info.pklass = NULL;
9077
9078                 g_assert (klass->generic_container->type_params [i].owner);
9079         }
9080
9081         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9082 }
9083
9084 /*
9085  * mono_reflection_create_internal_class:
9086  * @tb: a TypeBuilder object
9087  *
9088  * Actually create the MonoClass that is associated with the TypeBuilder.
9089  */
9090 void
9091 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9092 {
9093         MonoClass *klass;
9094
9095         MONO_ARCH_SAVE_REGS;
9096
9097         klass = mono_class_from_mono_type (tb->type.type);
9098
9099         mono_loader_lock ();
9100         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9101                 MonoReflectionFieldBuilder *fb;
9102                 MonoClass *ec;
9103                 MonoType *enum_basetype;
9104
9105                 g_assert (tb->fields != NULL);
9106                 g_assert (mono_array_length (tb->fields) >= 1);
9107
9108                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9109
9110                 if (!mono_type_is_valid_enum_basetype (monotype_cast (fb->type)->type)) {
9111                         mono_loader_unlock ();
9112                         return;
9113                 }
9114
9115                 enum_basetype = monotype_cast (fb->type)->type;
9116                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9117                 if (!klass->element_class)
9118                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9119
9120                 /*
9121                  * get the element_class from the current corlib.
9122                  */
9123                 ec = default_class_from_mono_type (enum_basetype);
9124                 klass->instance_size = ec->instance_size;
9125                 klass->size_inited = 1;
9126                 /* 
9127                  * this is almost safe to do with enums and it's needed to be able
9128                  * to create objects of the enum type (for use in SetConstant).
9129                  */
9130                 /* FIXME: Does this mean enums can't have method overrides ? */
9131                 mono_class_setup_vtable_general (klass, NULL, 0);
9132         }
9133         mono_loader_unlock ();
9134 }
9135
9136 #endif /* DISABLE_REFLECTION_EMIT */
9137
9138 static MonoMarshalSpec*
9139 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9140                                                                 MonoReflectionMarshal *minfo)
9141 {
9142         MonoMarshalSpec *res;
9143
9144         res = image_g_new0 (image, MonoMarshalSpec, 1);
9145         res->native = minfo->type;
9146
9147         switch (minfo->type) {
9148         case MONO_NATIVE_LPARRAY:
9149                 res->data.array_data.elem_type = minfo->eltype;
9150                 if (minfo->has_size) {
9151                         res->data.array_data.param_num = minfo->param_num;
9152                         res->data.array_data.num_elem = minfo->count;
9153                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9154                 }
9155                 else {
9156                         res->data.array_data.param_num = -1;
9157                         res->data.array_data.num_elem = -1;
9158                         res->data.array_data.elem_mult = -1;
9159                 }
9160                 break;
9161
9162         case MONO_NATIVE_BYVALTSTR:
9163         case MONO_NATIVE_BYVALARRAY:
9164                 res->data.array_data.num_elem = minfo->count;
9165                 break;
9166
9167         case MONO_NATIVE_CUSTOM:
9168                 if (minfo->marshaltyperef)
9169                         res->data.custom_data.custom_name =
9170                                 type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
9171                 if (minfo->mcookie)
9172                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9173                 break;
9174
9175         default:
9176                 break;
9177         }
9178
9179         return res;
9180 }
9181
9182 MonoReflectionMarshal*
9183 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9184                                                                                    MonoMarshalSpec *spec)
9185 {
9186         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9187         MonoReflectionMarshal *minfo;
9188         MonoType *mtype;
9189
9190         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9191                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9192                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9193                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9194         }
9195
9196         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9197         minfo->type = spec->native;
9198
9199         switch (minfo->type) {
9200         case MONO_NATIVE_LPARRAY:
9201                 minfo->eltype = spec->data.array_data.elem_type;
9202                 minfo->count = spec->data.array_data.num_elem;
9203                 minfo->param_num = spec->data.array_data.param_num;
9204                 break;
9205
9206         case MONO_NATIVE_BYVALTSTR:
9207         case MONO_NATIVE_BYVALARRAY:
9208                 minfo->count = spec->data.array_data.num_elem;
9209                 break;
9210
9211         case MONO_NATIVE_CUSTOM:
9212                 if (spec->data.custom_data.custom_name) {
9213                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9214                         if (mtype)
9215                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9216
9217                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9218                 }
9219                 if (spec->data.custom_data.cookie)
9220                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9221                 break;
9222
9223         default:
9224                 break;
9225         }
9226
9227         return minfo;
9228 }
9229
9230 static MonoMethod*
9231 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9232                                          ReflectionMethodBuilder *rmb,
9233                                          MonoMethodSignature *sig)
9234 {
9235         MonoMethod *m;
9236         MonoMethodNormal *pm;
9237         MonoMarshalSpec **specs;
9238         MonoReflectionMethodAux *method_aux;
9239         MonoImage *image;
9240         gboolean dynamic;
9241         int i;
9242
9243         /*
9244          * Methods created using a MethodBuilder should have their memory allocated
9245          * inside the image mempool, while dynamic methods should have their memory
9246          * malloc'd.
9247          */
9248         dynamic = rmb->refs != NULL;
9249         image = dynamic ? NULL : klass->image;
9250
9251         if (!dynamic)
9252                 g_assert (!klass->generic_class);
9253
9254         mono_loader_lock ();
9255
9256         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9257                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9258                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9259         else if (rmb->refs)
9260                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9261         else
9262                 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9263
9264         pm = (MonoMethodNormal*)m;
9265
9266         m->dynamic = dynamic;
9267         m->slot = -1;
9268         m->flags = rmb->attrs;
9269         m->iflags = rmb->iattrs;
9270         m->name = mono_string_to_utf8_image (image, rmb->name);
9271         m->klass = klass;
9272         m->signature = sig;
9273         m->skip_visibility = rmb->skip_visibility;
9274         if (rmb->table_idx)
9275                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9276
9277         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9278                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9279                         m->string_ctor = 1;
9280
9281                 m->signature->pinvoke = 1;
9282         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9283                 m->signature->pinvoke = 1;
9284
9285                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9286
9287                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9288                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9289                 
9290                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9291
9292                 if (klass->image->dynamic)
9293                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9294
9295                 mono_loader_unlock ();
9296
9297                 return m;
9298         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9299                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9300                 MonoMethodHeader *header;
9301                 guint32 code_size;
9302                 gint32 max_stack, i;
9303                 gint32 num_locals = 0;
9304                 gint32 num_clauses = 0;
9305                 guint8 *code;
9306
9307                 if (rmb->ilgen) {
9308                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9309                         code_size = rmb->ilgen->code_len;
9310                         max_stack = rmb->ilgen->max_stack;
9311                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9312                         if (rmb->ilgen->ex_handlers)
9313                                 num_clauses = method_count_clauses (rmb->ilgen);
9314                 } else {
9315                         if (rmb->code) {
9316                                 code = mono_array_addr (rmb->code, guint8, 0);
9317                                 code_size = mono_array_length (rmb->code);
9318                                 /* we probably need to run a verifier on the code... */
9319                                 max_stack = 8; 
9320                         }
9321                         else {
9322                                 code = NULL;
9323                                 code_size = 0;
9324                                 max_stack = 8;
9325                         }
9326                 }
9327
9328                 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) + 
9329                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9330                 header->code_size = code_size;
9331                 header->code = image_g_malloc (image, code_size);
9332                 memcpy ((char*)header->code, code, code_size);
9333                 header->max_stack = max_stack;
9334                 header->init_locals = rmb->init_locals;
9335                 header->num_locals = num_locals;
9336
9337                 for (i = 0; i < num_locals; ++i) {
9338                         MonoReflectionLocalBuilder *lb = 
9339                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9340
9341                         header->locals [i] = image_g_new0 (image, MonoType, 1);
9342                         memcpy (header->locals [i], monotype_cast (lb->type)->type, sizeof (MonoType));
9343                 }
9344
9345                 header->num_clauses = num_clauses;
9346                 if (num_clauses) {
9347                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9348                                  rmb->ilgen, num_clauses);
9349                 }
9350
9351                 pm->header = header;
9352         }
9353
9354         if (rmb->generic_params) {
9355                 int count = mono_array_length (rmb->generic_params);
9356                 MonoGenericContainer *container;
9357
9358                 container = rmb->generic_container;
9359                 if (container) {
9360                         m->is_generic = TRUE;
9361                         mono_method_set_generic_container (m, container);
9362                 }
9363                 container->type_argc = count;
9364                 container->type_params = image_g_new0 (image, MonoGenericParam, count);
9365                 container->owner.method = m;
9366
9367                 for (i = 0; i < count; i++) {
9368                         MonoReflectionGenericParam *gp =
9369                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9370
9371                         container->type_params [i] = *gp->type.type->data.generic_param;
9372                 }
9373
9374                 if (klass->generic_container) {
9375                         container->parent = klass->generic_container;
9376                         container->context.class_inst = klass->generic_container->context.class_inst;
9377                 }
9378                 container->context.method_inst = mono_get_shared_generic_inst (container);
9379         }
9380
9381         if (rmb->refs) {
9382                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9383                 int i;
9384                 void **data;
9385
9386                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9387
9388                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9389                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9390                 for (i = 0; i < rmb->nrefs; ++i)
9391                         data [i + 1] = rmb->refs [i];
9392         }
9393
9394         method_aux = NULL;
9395
9396         /* Parameter info */
9397         if (rmb->pinfo) {
9398                 if (!method_aux)
9399                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9400                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9401                 for (i = 0; i <= m->signature->param_count; ++i) {
9402                         MonoReflectionParamBuilder *pb;
9403                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9404                                 if ((i > 0) && (pb->attrs)) {
9405                                         /* Make a copy since it might point to a shared type structure */
9406                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9407                                         m->signature->params [i - 1]->attrs = pb->attrs;
9408                                 }
9409
9410                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9411                                         MonoDynamicImage *assembly;
9412                                         guint32 idx, def_type, len;
9413                                         char *p;
9414                                         const char *p2;
9415
9416                                         if (!method_aux->param_defaults) {
9417                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9418                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9419                                         }
9420                                         assembly = (MonoDynamicImage*)klass->image;
9421                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9422                                         /* Copy the data from the blob since it might get realloc-ed */
9423                                         p = assembly->blob.data + idx;
9424                                         len = mono_metadata_decode_blob_size (p, &p2);
9425                                         len += p2 - p;
9426                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
9427                                         method_aux->param_default_types [i] = def_type;
9428                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9429                                 }
9430
9431                                 if (pb->name)
9432                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9433                                 if (pb->cattrs) {
9434                                         if (!method_aux->param_cattr)
9435                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9436                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9437                                 }
9438                         }
9439                 }
9440         }
9441
9442         /* Parameter marshalling */
9443         specs = NULL;
9444         if (rmb->pinfo)         
9445                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9446                         MonoReflectionParamBuilder *pb;
9447                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9448                                 if (pb->marshal_info) {
9449                                         if (specs == NULL)
9450                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9451                                         specs [pb->position] = 
9452                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9453                                 }
9454                         }
9455                 }
9456         if (specs != NULL) {
9457                 if (!method_aux)
9458                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9459                 method_aux->param_marshall = specs;
9460         }
9461
9462         if (klass->image->dynamic && method_aux)
9463                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9464
9465         mono_loader_unlock ();
9466
9467         return m;
9468 }       
9469
9470 static MonoMethod*
9471 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9472 {
9473         ReflectionMethodBuilder rmb;
9474         MonoMethodSignature *sig;
9475
9476         mono_loader_lock ();
9477         sig = ctor_builder_to_signature (klass->image, mb);
9478         mono_loader_unlock ();
9479
9480         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9481
9482         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9483         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9484
9485         /* If we are in a generic class, we might be called multiple times from inflate_method */
9486         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9487                 /* ilgen is no longer needed */
9488                 mb->ilgen = NULL;
9489         }
9490
9491         return mb->mhandle;
9492 }
9493
9494 static MonoMethod*
9495 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9496 {
9497         ReflectionMethodBuilder rmb;
9498         MonoMethodSignature *sig;
9499
9500         mono_loader_lock ();
9501         sig = method_builder_to_signature (klass->image, mb);
9502         mono_loader_unlock ();
9503
9504         reflection_methodbuilder_from_method_builder (&rmb, mb);
9505
9506         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9507         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9508
9509         /* If we are in a generic class, we might be called multiple times from inflate_method */
9510         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9511                 /* ilgen is no longer needed */
9512                 mb->ilgen = NULL;
9513         }
9514         return mb->mhandle;
9515 }
9516
9517 static MonoClassField*
9518 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9519 {
9520         MonoClassField *field;
9521         MonoType *custom;
9522
9523         field = g_new0 (MonoClassField, 1);
9524
9525         field->name = mono_string_to_utf8 (fb->name);
9526         if (fb->attrs || fb->modreq || fb->modopt) {
9527                 field->type = mono_metadata_type_dup (NULL, monotype_cast (fb->type)->type);
9528                 field->type->attrs = fb->attrs;
9529
9530                 g_assert (klass->image->dynamic);
9531                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9532                 g_free (field->type);
9533                 field->type = custom;
9534         } else {
9535                 field->type = monotype_cast (fb->type)->type;
9536         }
9537         if (fb->offset != -1)
9538                 field->offset = fb->offset;
9539         field->parent = klass;
9540         mono_save_custom_attrs (klass->image, field, fb->cattrs);
9541
9542         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9543
9544         return field;
9545 }
9546
9547 MonoType*
9548 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9549 {
9550         MonoClass *klass;
9551         MonoReflectionTypeBuilder *tb = NULL;
9552         gboolean is_dynamic = FALSE;
9553         MonoDomain *domain;
9554         MonoClass *geninst;
9555
9556         mono_loader_lock ();
9557
9558         domain = mono_object_domain (type);
9559
9560         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9561                 tb = (MonoReflectionTypeBuilder *) type;
9562
9563                 is_dynamic = TRUE;
9564         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9565                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9566
9567                 tb = rgi->generic_type;
9568                 is_dynamic = TRUE;
9569         }
9570
9571         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9572         if (tb && tb->generic_container)
9573                 mono_reflection_create_generic_class (tb);
9574
9575         klass = mono_class_from_mono_type (type->type);
9576         if (!klass->generic_container) {
9577                 mono_loader_unlock ();
9578                 return NULL;
9579         }
9580
9581         if (klass->wastypebuilder) {
9582                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9583
9584                 is_dynamic = TRUE;
9585         }
9586
9587         mono_loader_unlock ();
9588
9589         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9590
9591         return &geninst->byval_arg;
9592 }
9593
9594 MonoClass*
9595 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9596 {
9597         MonoGenericClass *gclass;
9598         MonoGenericInst *inst;
9599
9600         g_assert (klass->generic_container);
9601
9602         inst = mono_metadata_get_generic_inst (type_argc, types);
9603         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9604
9605         return mono_generic_class_get_class (gclass);
9606 }
9607
9608 MonoReflectionMethod*
9609 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9610 {
9611         MonoClass *klass;
9612         MonoMethod *method, *inflated;
9613         MonoMethodInflated *imethod;
9614         MonoReflectionMethodBuilder *mb = NULL;
9615         MonoGenericContext tmp_context;
9616         MonoGenericInst *ginst;
9617         MonoType **type_argv;
9618         int count, i;
9619
9620         MONO_ARCH_SAVE_REGS;
9621
9622         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9623 #ifndef DISABLE_REFLECTION_EMIT
9624                 MonoReflectionTypeBuilder *tb;
9625                 MonoClass *klass;
9626
9627                 mb = (MonoReflectionMethodBuilder *) rmethod;
9628                 tb = (MonoReflectionTypeBuilder *) mb->type;
9629                 klass = mono_class_from_mono_type (tb->type.type);
9630
9631                 method = methodbuilder_to_mono_method (klass, mb);
9632 #else
9633                 g_assert_not_reached ();
9634                 method = NULL;
9635 #endif
9636         } else {
9637                 method = rmethod->method;
9638         }
9639
9640         klass = method->klass;
9641
9642         if (method->is_inflated)
9643                 method = ((MonoMethodInflated *) method)->declaring;
9644
9645         count = mono_method_signature (method)->generic_param_count;
9646         if (count != mono_array_length (types))
9647                 return NULL;
9648
9649         type_argv = g_new0 (MonoType *, count);
9650         for (i = 0; i < count; i++) {
9651                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9652                 type_argv [i] = garg->type;
9653         }
9654         ginst = mono_metadata_get_generic_inst (count, type_argv);
9655         g_free (type_argv);
9656
9657         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9658         tmp_context.method_inst = ginst;
9659
9660         inflated = mono_class_inflate_generic_method (method, &tmp_context);
9661         imethod = (MonoMethodInflated *) inflated;
9662
9663         if (method->klass->image->dynamic) {
9664                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9665                 /*
9666                  * This table maps metadata structures representing inflated methods/fields
9667                  * to the reflection objects representing their generic definitions.
9668                  */
9669                 mono_loader_lock ();
9670                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9671                 mono_loader_unlock ();
9672         }
9673         
9674         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9675 }
9676
9677 #ifndef DISABLE_REFLECTION_EMIT
9678
9679 static MonoMethod *
9680 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9681 {
9682         MonoMethodInflated *imethod;
9683         MonoGenericContext *context;
9684         int i;
9685
9686         /*
9687          * With generic code sharing the klass might not be inflated.
9688          * This can happen because classes inflated with their own
9689          * type arguments are "normalized" to the uninflated class.
9690          */
9691         if (!klass->generic_class)
9692                 return method;
9693
9694         context = mono_class_get_context (klass);
9695
9696         if (klass->method.count) {
9697                 /* Find the already created inflated method */
9698                 for (i = 0; i < klass->method.count; ++i) {
9699                         g_assert (klass->methods [i]->is_inflated);
9700                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9701                                 break;
9702                 }
9703                 g_assert (i < klass->method.count);
9704                 imethod = (MonoMethodInflated*)klass->methods [i];
9705         } else {
9706                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9707         }
9708
9709         if (method->is_generic && method->klass->image->dynamic) {
9710                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9711
9712                 mono_loader_lock ();
9713                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9714                 mono_loader_unlock ();
9715         }
9716         return (MonoMethod *) imethod;
9717 }
9718
9719 static MonoMethod *
9720 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9721 {
9722         MonoMethod *method;
9723         MonoClass *gklass;
9724
9725         gklass = mono_class_from_mono_type (type->generic_type->type.type);
9726
9727         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9728                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9729                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9730                 else
9731                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9732         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9733                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9734         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9735                 method = ((MonoReflectionMethod *) obj)->method;
9736         else {
9737                 method = NULL; /* prevent compiler warning */
9738                 g_assert_not_reached ();
9739         }
9740
9741         return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9742 }
9743
9744 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9745 void
9746 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
9747                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9748                                           MonoArray *events)
9749 {
9750         MonoGenericClass *gclass;
9751         MonoDynamicGenericClass *dgclass;
9752         MonoClass *klass, *gklass;
9753         int i;
9754
9755         MONO_ARCH_SAVE_REGS;
9756
9757         klass = mono_class_from_mono_type (type->type.type);
9758         g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9759         gclass = type->type.type->data.generic_class;
9760
9761         g_assert (gclass->is_dynamic);
9762         dgclass = (MonoDynamicGenericClass *) gclass;
9763
9764         if (dgclass->initialized)
9765                 return;
9766
9767         gklass = gclass->container_class;
9768         mono_class_init (gklass);
9769
9770         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9771         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9772         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9773         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9774         dgclass->count_events = events ? mono_array_length (events) : 0;
9775
9776         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9777         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9778         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9779         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9780         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9781         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9782         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9783
9784         for (i = 0; i < dgclass->count_methods; i++) {
9785                 MonoObject *obj = mono_array_get (methods, gpointer, i);
9786
9787                 dgclass->methods [i] = inflate_method (type, obj);
9788         }
9789
9790         for (i = 0; i < dgclass->count_ctors; i++) {
9791                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9792
9793                 dgclass->ctors [i] = inflate_method (type, obj);
9794         }
9795
9796         for (i = 0; i < dgclass->count_fields; i++) {
9797                 MonoObject *obj = mono_array_get (fields, gpointer, i);
9798                 MonoClassField *field, *inflated_field = NULL;
9799
9800                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9801                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9802                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9803                         field = ((MonoReflectionField *) obj)->field;
9804                 else {
9805                         field = NULL; /* prevent compiler warning */
9806                         g_assert_not_reached ();
9807                 }
9808
9809                 dgclass->fields [i] = *field;
9810                 dgclass->fields [i].parent = klass;
9811                 dgclass->fields [i].type = mono_class_inflate_generic_type (
9812                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9813                 dgclass->field_generic_types [i] = field->type;
9814                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9815                 dgclass->field_objects [i] = obj;
9816
9817                 if (inflated_field) {
9818                         g_free (inflated_field);
9819                 } else {
9820                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9821                 }
9822         }
9823
9824         for (i = 0; i < dgclass->count_properties; i++) {
9825                 MonoObject *obj = mono_array_get (properties, gpointer, i);
9826                 MonoProperty *property = &dgclass->properties [i];
9827
9828                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9829                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9830
9831                         property->parent = klass;
9832                         property->attrs = pb->attrs;
9833                         property->name = mono_string_to_utf8 (pb->name);
9834                         if (pb->get_method)
9835                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9836                         if (pb->set_method)
9837                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9838                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9839                         *property = *((MonoReflectionProperty *) obj)->property;
9840                         property->name = g_strdup (property->name);
9841
9842                         if (property->get)
9843                                 property->get = inflate_mono_method (klass, property->get, NULL);
9844                         if (property->set)
9845                                 property->set = inflate_mono_method (klass, property->set, NULL);
9846                 } else
9847                         g_assert_not_reached ();
9848         }
9849
9850         for (i = 0; i < dgclass->count_events; i++) {
9851                 MonoObject *obj = mono_array_get (events, gpointer, i);
9852                 MonoEvent *event = &dgclass->events [i];
9853
9854                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9855                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9856
9857                         event->parent = klass;
9858                         event->attrs = eb->attrs;
9859                         event->name = mono_string_to_utf8 (eb->name);
9860                         if (eb->add_method)
9861                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9862                         if (eb->remove_method)
9863                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9864                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9865                         *event = *((MonoReflectionMonoEvent *) obj)->event;
9866                         event->name = g_strdup (event->name);
9867
9868                         if (event->add)
9869                                 event->add = inflate_mono_method (klass, event->add, NULL);
9870                         if (event->remove)
9871                                 event->remove = inflate_mono_method (klass, event->remove, NULL);
9872                 } else
9873                         g_assert_not_reached ();
9874         }
9875
9876         dgclass->initialized = TRUE;
9877 }
9878
9879 static void
9880 ensure_generic_class_runtime_vtable (MonoClass *klass)
9881 {
9882         MonoClass *gklass = klass->generic_class->container_class;
9883         int i;
9884
9885         if (klass->wastypebuilder)
9886                 return;
9887
9888         ensure_runtime_vtable (gklass);
9889
9890         klass->method.count = gklass->method.count;
9891         klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9892
9893         for (i = 0; i < klass->method.count; i++) {
9894                 klass->methods [i] = mono_class_inflate_generic_method_full (
9895                         gklass->methods [i], klass, mono_class_get_context (klass));
9896         }
9897
9898         klass->interface_count = gklass->interface_count;
9899         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9900         for (i = 0; i < klass->interface_count; ++i) {
9901                 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9902                 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9903                 mono_metadata_free_type (iface_type);
9904
9905                 ensure_runtime_vtable (klass->interfaces [i]);
9906         }
9907         klass->interfaces_inited = 1;
9908
9909         /*We can only finish with this klass once it's parent has as well*/
9910         if (gklass->wastypebuilder)
9911                 klass->wastypebuilder = TRUE;
9912         return;
9913 }
9914
9915 static void
9916 ensure_runtime_vtable (MonoClass *klass)
9917 {
9918         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9919         int i, num, j;
9920
9921         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9922                 return;
9923         if (klass->parent)
9924                 ensure_runtime_vtable (klass->parent);
9925
9926         if (tb) {
9927                 num = tb->ctors? mono_array_length (tb->ctors): 0;
9928                 num += tb->num_methods;
9929                 klass->method.count = num;
9930                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9931                 num = tb->ctors? mono_array_length (tb->ctors): 0;
9932                 for (i = 0; i < num; ++i)
9933                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9934                 num = tb->num_methods;
9935                 j = i;
9936                 for (i = 0; i < num; ++i)
9937                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9938         
9939                 if (tb->interfaces) {
9940                         klass->interface_count = mono_array_length (tb->interfaces);
9941                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9942                         for (i = 0; i < klass->interface_count; ++i) {
9943                                 MonoReflectionType *iface = mono_type_array_get (tb->interfaces, i);
9944                                 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9945                                 ensure_runtime_vtable (klass->interfaces [i]);
9946                         }
9947                         klass->interfaces_inited = 1;
9948                 }
9949         } else if (klass->generic_class){
9950                 ensure_generic_class_runtime_vtable (klass);
9951         }
9952
9953         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9954                 for (i = 0; i < klass->method.count; ++i)
9955                         klass->methods [i]->slot = i;
9956                 
9957                 mono_class_setup_interface_offsets (klass);
9958                 mono_class_setup_interface_id (klass);
9959         }
9960
9961         /*
9962          * The generic vtable is needed even if image->run is not set since some
9963          * runtime code like ves_icall_Type_GetMethodsByName depends on 
9964          * method->slot being defined.
9965          */
9966
9967         /* 
9968          * tb->methods could not be freed since it is used for determining 
9969          * overrides during dynamic vtable construction.
9970          */
9971 }
9972
9973 void
9974 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9975 {
9976         MonoReflectionTypeBuilder *tb;
9977         int i, onum;
9978
9979         *overrides = NULL;
9980         *num_overrides = 0;
9981
9982         g_assert (klass->image->dynamic);
9983
9984         if (!klass->reflection_info)
9985                 return;
9986
9987         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9988
9989         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9990
9991         onum = 0;
9992         if (tb->methods) {
9993                 for (i = 0; i < tb->num_methods; ++i) {
9994                         MonoReflectionMethodBuilder *mb = 
9995                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9996                         if (mb->override_method)
9997                                 onum ++;
9998                 }
9999         }
10000
10001         if (onum) {
10002                 *overrides = g_new0 (MonoMethod*, onum * 2);
10003
10004                 onum = 0;
10005                 for (i = 0; i < tb->num_methods; ++i) {
10006                         MonoReflectionMethodBuilder *mb = 
10007                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10008                         if (mb->override_method) {
10009                                 (*overrides) [onum * 2] = 
10010                                         mb->override_method->method;
10011                                 (*overrides) [onum * 2 + 1] =
10012                                         mb->mhandle;
10013
10014                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10015                                 g_assert (mb->override_method->method);
10016                                 g_assert (mb->mhandle);
10017
10018                                 onum ++;
10019                         }
10020                 }
10021         }
10022
10023         *num_overrides = onum;
10024 }
10025
10026 static void
10027 typebuilder_setup_fields (MonoClass *klass)
10028 {
10029         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10030         MonoReflectionFieldBuilder *fb;
10031         MonoClassField *field;
10032         MonoImage *image = klass->image;
10033         const char *p, *p2;
10034         int i;
10035         guint32 len, idx, real_size = 0;
10036
10037         klass->field.count = tb->num_fields;
10038         klass->field.first = 0;
10039
10040         if (tb->class_size) {
10041                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10042                 klass->packing_size = tb->packing_size;
10043                 real_size = klass->instance_size + tb->class_size;
10044         }
10045
10046         if (!klass->field.count) {
10047                 klass->instance_size = MAX (klass->instance_size, real_size);
10048                 return;
10049         }
10050         
10051         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10052         mono_class_alloc_ext (klass);
10053         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10054
10055         for (i = 0; i < klass->field.count; ++i) {
10056                 fb = mono_array_get (tb->fields, gpointer, i);
10057                 field = &klass->fields [i];
10058                 field->name = mono_string_to_utf8_image (image, fb->name);
10059                 if (fb->attrs) {
10060                         field->type = mono_metadata_type_dup (klass->image, monotype_cast (fb->type)->type);
10061                         field->type->attrs = fb->attrs;
10062                 } else {
10063                         field->type = monotype_cast (fb->type)->type;
10064                 }
10065                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10066                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10067                 if (fb->offset != -1)
10068                         field->offset = fb->offset;
10069                 field->parent = klass;
10070                 fb->handle = field;
10071                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10072
10073                 if (fb->def_value) {
10074                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10075                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10076                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10077                         /* Copy the data from the blob since it might get realloc-ed */
10078                         p = assembly->blob.data + idx;
10079                         len = mono_metadata_decode_blob_size (p, &p2);
10080                         len += p2 - p;
10081                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10082                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10083                 }
10084         }
10085
10086         klass->instance_size = MAX (klass->instance_size, real_size);
10087         mono_class_layout_fields (klass);
10088 }
10089
10090 static void
10091 typebuilder_setup_properties (MonoClass *klass)
10092 {
10093         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10094         MonoReflectionPropertyBuilder *pb;
10095         MonoImage *image = klass->image;
10096         MonoProperty *properties;
10097         int i;
10098
10099         if (!klass->ext)
10100                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10101
10102         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10103         klass->ext->property.first = 0;
10104
10105         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10106         klass->ext->properties = properties;
10107         for (i = 0; i < klass->ext->property.count; ++i) {
10108                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10109                 properties [i].parent = klass;
10110                 properties [i].attrs = pb->attrs;
10111                 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10112                 if (pb->get_method)
10113                         properties [i].get = pb->get_method->mhandle;
10114                 if (pb->set_method)
10115                         properties [i].set = pb->set_method->mhandle;
10116
10117                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10118         }
10119 }
10120
10121 MonoReflectionEvent *
10122 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10123 {
10124         MonoEvent *event = g_new0 (MonoEvent, 1);
10125         MonoClass *klass;
10126         int j;
10127
10128         klass = mono_class_from_mono_type (tb->type.type);
10129
10130         event->parent = klass;
10131         event->attrs = eb->attrs;
10132         event->name = mono_string_to_utf8 (eb->name);
10133         if (eb->add_method)
10134                 event->add = eb->add_method->mhandle;
10135         if (eb->remove_method)
10136                 event->remove = eb->remove_method->mhandle;
10137         if (eb->raise_method)
10138                 event->raise = eb->raise_method->mhandle;
10139
10140         if (eb->other_methods) {
10141                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10142                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10143                         MonoReflectionMethodBuilder *mb = 
10144                                 mono_array_get (eb->other_methods,
10145                                                 MonoReflectionMethodBuilder*, j);
10146                         event->other [j] = mb->mhandle;
10147                 }
10148         }
10149
10150         return mono_event_get_object (mono_object_domain (tb), klass, event);
10151 }
10152
10153 static void
10154 typebuilder_setup_events (MonoClass *klass)
10155 {
10156         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10157         MonoReflectionEventBuilder *eb;
10158         MonoImage *image = klass->image;
10159         MonoEvent *events;
10160         int i, j;
10161
10162         if (!klass->ext)
10163                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10164
10165         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10166         klass->ext->event.first = 0;
10167
10168         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10169         klass->ext->events = events;
10170         for (i = 0; i < klass->ext->event.count; ++i) {
10171                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10172                 events [i].parent = klass;
10173                 events [i].attrs = eb->attrs;
10174                 events [i].name = mono_string_to_utf8_image (image, eb->name);
10175                 if (eb->add_method)
10176                         events [i].add = eb->add_method->mhandle;
10177                 if (eb->remove_method)
10178                         events [i].remove = eb->remove_method->mhandle;
10179                 if (eb->raise_method)
10180                         events [i].raise = eb->raise_method->mhandle;
10181
10182                 if (eb->other_methods) {
10183                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10184                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10185                                 MonoReflectionMethodBuilder *mb = 
10186                                         mono_array_get (eb->other_methods,
10187                                                                         MonoReflectionMethodBuilder*, j);
10188                                 events [i].other [j] = mb->mhandle;
10189                         }
10190                 }
10191                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10192         }
10193 }
10194
10195 static gboolean
10196 remove_instantiations_of (gpointer key,
10197                                                   gpointer value,
10198                                                   gpointer user_data)
10199 {
10200         MonoType *type = (MonoType*)key;
10201         MonoClass *klass = (MonoClass*)user_data;
10202
10203         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10204                 return TRUE;
10205         else
10206                 return FALSE;
10207 }
10208
10209 MonoReflectionType*
10210 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10211 {
10212         MonoClass *klass;
10213         MonoDomain* domain;
10214         MonoReflectionType* res;
10215         int i, j;
10216
10217         MONO_ARCH_SAVE_REGS;
10218
10219         domain = mono_object_domain (tb);
10220         klass = mono_class_from_mono_type (tb->type.type);
10221
10222         /*
10223          * Check for user defined Type subclasses.
10224          */
10225         CHECK_MONOTYPE (tb->parent);
10226         check_array_for_usertypes (tb->interfaces);
10227         if (tb->fields) {
10228                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10229                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10230                         if (fb) {
10231                                 CHECK_MONOTYPE (fb->type);
10232                                 check_array_for_usertypes (fb->modreq);
10233                                 check_array_for_usertypes (fb->modopt);
10234                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10235                                         CHECK_MONOTYPE (fb->marshal_info->marshaltyperef);
10236                         }
10237                 }
10238         }
10239         if (tb->methods) {
10240                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10241                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10242                         if (mb) {
10243                                 CHECK_MONOTYPE (mb->rtype);
10244                                 check_array_for_usertypes (mb->return_modreq);
10245                                 check_array_for_usertypes (mb->return_modopt);
10246                                 check_array_for_usertypes (mb->parameters);
10247                                 if (mb->param_modreq)
10248                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10249                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10250                                 if (mb->param_modopt)
10251                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10252                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10253                         }
10254                 }
10255         }
10256         if (tb->ctors) {
10257                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10258                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10259                         if (mb) {
10260                                 check_array_for_usertypes (mb->parameters);
10261                                 if (mb->param_modreq)
10262                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10263                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10264                                 if (mb->param_modopt)
10265                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10266                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10267                         }
10268                 }
10269         }
10270
10271         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10272
10273         /* 
10274          * we need to lock the domain because the lock will be taken inside
10275          * So, we need to keep the locking order correct.
10276          */
10277         mono_loader_lock ();
10278         mono_domain_lock (domain);
10279         if (klass->wastypebuilder) {
10280                 mono_domain_unlock (domain);
10281                 mono_loader_unlock ();
10282                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10283         }
10284         /*
10285          * Fields to set in klass:
10286          * the various flags: delegate/unicode/contextbound etc.
10287          */
10288         klass->flags = tb->attrs;
10289         klass->has_cctor = 1;
10290         klass->has_finalize = 1;
10291
10292 #if 0
10293         if (!((MonoDynamicImage*)klass->image)->run) {
10294                 if (klass->generic_container) {
10295                         /* FIXME: The code below can't handle generic classes */
10296                         klass->wastypebuilder = TRUE;
10297                         mono_loader_unlock ();
10298                         mono_domain_unlock (domain);
10299                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10300                 }
10301         }
10302 #endif
10303
10304         /* enums are done right away */
10305         if (!klass->enumtype)
10306                 ensure_runtime_vtable (klass);
10307
10308         if (tb->subtypes) {
10309                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10310                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10311                         mono_class_alloc_ext (klass);
10312                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtb->type.type));
10313                 }
10314         }
10315
10316         klass->nested_classes_inited = TRUE;
10317
10318         /* fields and object layout */
10319         if (klass->parent) {
10320                 if (!klass->parent->size_inited)
10321                         mono_class_init (klass->parent);
10322                 klass->instance_size = klass->parent->instance_size;
10323                 klass->sizes.class_size = 0;
10324                 klass->min_align = klass->parent->min_align;
10325                 /* if the type has no fields we won't call the field_setup
10326                  * routine which sets up klass->has_references.
10327                  */
10328                 klass->has_references |= klass->parent->has_references;
10329         } else {
10330                 klass->instance_size = sizeof (MonoObject);
10331                 klass->min_align = 1;
10332         }
10333
10334         /* FIXME: handle packing_size and instance_size */
10335         typebuilder_setup_fields (klass);
10336
10337         typebuilder_setup_properties (klass);
10338
10339         typebuilder_setup_events (klass);
10340         
10341         klass->wastypebuilder = TRUE;
10342
10343         /* 
10344          * If we are a generic TypeBuilder, there might be instantiations in the type cache
10345          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
10346          * we want to return normal System.MonoType objects, so clear these out from the cache.
10347          */
10348         if (domain->type_hash && klass->generic_container)
10349                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10350
10351         mono_domain_unlock (domain);
10352         mono_loader_unlock ();
10353
10354         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10355                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10356                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10357         }
10358
10359         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10360         g_assert (res != (MonoReflectionType*)tb);
10361
10362         return res;
10363 }
10364
10365 void
10366 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10367 {
10368         MonoGenericParam *param;
10369         MonoImage *image;
10370         MonoClass *pklass;
10371
10372         MONO_ARCH_SAVE_REGS;
10373
10374         param = g_new0 (MonoGenericParam, 1);
10375
10376         if (gparam->mbuilder) {
10377                 if (!gparam->mbuilder->generic_container) {
10378                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10379                         MonoClass *klass = mono_class_from_mono_type (tb->type.type);
10380                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10381                         gparam->mbuilder->generic_container->is_method = TRUE;
10382                 }
10383                 param->owner = gparam->mbuilder->generic_container;
10384         } else if (gparam->tbuilder) {
10385                 if (!gparam->tbuilder->generic_container) {
10386                         MonoClass *klass = mono_class_from_mono_type (gparam->tbuilder->type.type);
10387                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10388                         gparam->tbuilder->generic_container->owner.klass = klass;
10389                 }
10390                 param->owner = gparam->tbuilder->generic_container;
10391         }
10392
10393         param->info.name = mono_string_to_utf8 (gparam->name);
10394         param->num = gparam->index;
10395
10396         image = &gparam->tbuilder->module->dynamic_image->image;
10397         pklass = mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10398
10399         gparam->type.type = &pklass->byval_arg;
10400
10401         MOVING_GC_REGISTER (&pklass->reflection_info);
10402         pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10403 }
10404
10405 MonoArray *
10406 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10407 {
10408         MonoDynamicImage *assembly = sig->module->dynamic_image;
10409         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10410         guint32 buflen, i;
10411         MonoArray *result;
10412         SigBuffer buf;
10413
10414         check_array_for_usertypes (sig->arguments);
10415
10416         sigbuffer_init (&buf, 32);
10417
10418         sigbuffer_add_value (&buf, 0x07);
10419         sigbuffer_add_value (&buf, na);
10420         for (i = 0; i < na; ++i) {
10421                 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10422                 encode_reflection_type (assembly, type, &buf);
10423         }
10424
10425         buflen = buf.p - buf.buf;
10426         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10427         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10428         sigbuffer_free (&buf);
10429
10430         return result;
10431 }
10432
10433 MonoArray *
10434 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10435 {
10436         MonoDynamicImage *assembly = sig->module->dynamic_image;
10437         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10438         guint32 buflen, i;
10439         MonoArray *result;
10440         SigBuffer buf;
10441
10442         check_array_for_usertypes (sig->arguments);
10443
10444         sigbuffer_init (&buf, 32);
10445
10446         sigbuffer_add_value (&buf, 0x06);
10447         for (i = 0; i < na; ++i) {
10448                 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10449                 encode_reflection_type (assembly, type, &buf);
10450         }
10451
10452         buflen = buf.p - buf.buf;
10453         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10454         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10455         sigbuffer_free (&buf);
10456
10457         return result;
10458 }
10459
10460 void 
10461 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10462 {
10463         ReflectionMethodBuilder rmb;
10464         MonoMethodSignature *sig;
10465         MonoClass *klass;
10466         GSList *l;
10467         int i;
10468
10469         sig = dynamic_method_to_signature (mb);
10470
10471         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10472
10473         /*
10474          * Resolve references.
10475          */
10476         /* 
10477          * Every second entry in the refs array is reserved for storing handle_class,
10478          * which is needed by the ldtoken implementation in the JIT.
10479          */
10480         rmb.nrefs = mb->nrefs;
10481         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10482         for (i = 0; i < mb->nrefs; i += 2) {
10483                 MonoClass *handle_class;
10484                 gpointer ref;
10485                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10486
10487                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10488                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10489                         /*
10490                          * The referenced DynamicMethod should already be created by the managed
10491                          * code, except in the case of circular references. In that case, we store
10492                          * method in the refs array, and fix it up later when the referenced 
10493                          * DynamicMethod is created.
10494                          */
10495                         if (method->mhandle) {
10496                                 ref = method->mhandle;
10497                         } else {
10498                                 /* FIXME: GC object stored in unmanaged memory */
10499                                 ref = method;
10500
10501                                 /* FIXME: GC object stored in unmanaged memory */
10502                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
10503                         }
10504                         handle_class = mono_defaults.methodhandle_class;
10505                 } else {
10506                         MonoException *ex = NULL;
10507                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10508                         if (!ref)
10509                                 ex = mono_get_exception_type_load (NULL, NULL);
10510                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10511                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10512
10513                         if (ex) {
10514                                 g_free (rmb.refs);
10515                                 mono_raise_exception (ex);
10516                                 return;
10517                         }
10518                 }
10519
10520                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10521                 rmb.refs [i + 1] = handle_class;
10522         }               
10523
10524         klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10525
10526         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10527
10528         /* Fix up refs entries pointing at us */
10529         for (l = mb->referenced_by; l; l = l->next) {
10530                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10531                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10532                 gpointer *data;
10533                 
10534                 g_assert (method->mhandle);
10535
10536                 data = (gpointer*)wrapper->method_data;
10537                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10538                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10539                                 data [i + 1] = mb->mhandle;
10540                 }
10541         }
10542         g_slist_free (mb->referenced_by);
10543
10544         g_free (rmb.refs);
10545
10546         /* ilgen is no longer needed */
10547         mb->ilgen = NULL;
10548 }
10549
10550 #endif /* DISABLE_REFLECTION_EMIT */
10551
10552 void
10553 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10554 {
10555         g_assert (mb);
10556
10557         if (mb->mhandle)
10558                 mono_runtime_free_method (
10559                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10560 }
10561
10562 /**
10563  * 
10564  * mono_reflection_is_valid_dynamic_token:
10565  * 
10566  * Returns TRUE if token is valid.
10567  * 
10568  */
10569 gboolean
10570 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10571 {
10572         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10573 }
10574
10575 #ifndef DISABLE_REFLECTION_EMIT
10576
10577 /**
10578  * mono_reflection_lookup_dynamic_token:
10579  *
10580  * Finish the Builder object pointed to by TOKEN and return the corresponding
10581  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
10582  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10583  * mapping table.
10584  *
10585  * LOCKING: Take the loader lock
10586  */
10587 gpointer
10588 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10589 {
10590         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10591         MonoObject *obj;
10592         MonoClass *klass;
10593
10594         mono_loader_lock ();
10595         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10596         mono_loader_unlock ();
10597         if (!obj) {
10598                 if (valid_token)
10599                         g_assert_not_reached ();
10600                 else
10601                         return NULL;
10602         }
10603
10604         if (!handle_class)
10605                 handle_class = &klass;
10606         return resolve_object (image, obj, handle_class, context);
10607 }
10608
10609 /*
10610  * ensure_complete_type:
10611  *
10612  *   Ensure that KLASS is completed if it is a dynamic type, or references
10613  * dynamic types.
10614  */
10615 static void
10616 ensure_complete_type (MonoClass *klass)
10617 {
10618         if (klass->image->dynamic && !klass->wastypebuilder) {
10619                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10620
10621                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10622
10623                 // Asserting here could break a lot of code
10624                 //g_assert (klass->wastypebuilder);
10625         }
10626
10627         if (klass->generic_class) {
10628                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10629                 int i;
10630
10631                 for (i = 0; i < inst->type_argc; ++i) {
10632                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10633                 }
10634         }
10635 }
10636
10637 static gpointer
10638 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10639 {
10640         gpointer result = NULL;
10641
10642         if (strcmp (obj->vtable->klass->name, "String") == 0) {
10643                 result = mono_string_intern ((MonoString*)obj);
10644                 *handle_class = NULL;
10645                 g_assert (result);
10646         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10647                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10648                 if (context) {
10649                         MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10650                         result = mono_class_from_mono_type (inflated);
10651                         mono_metadata_free_type (inflated);
10652                 } else {
10653                         result = mono_class_from_mono_type (tb->type);
10654                 }
10655                 *handle_class = mono_defaults.typehandle_class;
10656                 g_assert (result);
10657         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10658                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10659                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10660                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10661                 result = ((MonoReflectionMethod*)obj)->method;
10662                 if (context)
10663                         result = mono_class_inflate_generic_method (result, context);
10664                 *handle_class = mono_defaults.methodhandle_class;
10665                 g_assert (result);
10666         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10667                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10668                 result = mb->mhandle;
10669                 if (!result) {
10670                         /* Type is not yet created */
10671                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10672
10673                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10674
10675                         /*
10676                          * Hopefully this has been filled in by calling CreateType() on the
10677                          * TypeBuilder.
10678                          */
10679                         /*
10680                          * TODO: This won't work if the application finishes another 
10681                          * TypeBuilder instance instead of this one.
10682                          */
10683                         result = mb->mhandle;
10684                 }
10685                 if (context)
10686                         result = mono_class_inflate_generic_method (result, context);
10687                 *handle_class = mono_defaults.methodhandle_class;
10688         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10689                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10690
10691                 result = cb->mhandle;
10692                 if (!result) {
10693                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10694
10695                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10696                         result = cb->mhandle;
10697                 }
10698                 if (context)
10699                         result = mono_class_inflate_generic_method (result, context);
10700                 *handle_class = mono_defaults.methodhandle_class;
10701         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10702                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10703
10704                 ensure_complete_type (field->parent);
10705                 if (context) {
10706                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10707                         MonoClass *class = mono_class_from_mono_type (inflated);
10708                         MonoClassField *inflated_field;
10709                         gpointer iter = NULL;
10710                         mono_metadata_free_type (inflated);
10711                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
10712                                 if (!strcmp (field->name, inflated_field->name))
10713                                         break;
10714                         }
10715                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10716                         result = inflated_field;
10717                 } else {
10718                         result = field;
10719                 }
10720                 *handle_class = mono_defaults.fieldhandle_class;
10721                 g_assert (result);
10722         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10723                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10724                 result = fb->handle;
10725
10726                 if (!result) {
10727                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10728
10729                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10730                         result = fb->handle;
10731                 }
10732
10733                 if (fb->handle && fb->handle->parent->generic_container) {
10734                         MonoClass *klass = fb->handle->parent;
10735                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10736                         MonoClass *inflated = mono_class_from_mono_type (type);
10737
10738                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10739                         g_assert (result);
10740                         mono_metadata_free_type (type);
10741                 }
10742                 *handle_class = mono_defaults.fieldhandle_class;
10743         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10744                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10745                 MonoClass *klass;
10746
10747                 klass = tb->type.type->data.klass;
10748                 if (klass->wastypebuilder) {
10749                         /* Already created */
10750                         result = klass;
10751                 }
10752                 else {
10753                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10754                         result = tb->type.type->data.klass;
10755                         g_assert (result);
10756                 }
10757                 *handle_class = mono_defaults.typehandle_class;
10758         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10759                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10760                 MonoMethodSignature *sig;
10761                 int nargs, i;
10762
10763                 if (helper->arguments)
10764                         nargs = mono_array_length (helper->arguments);
10765                 else
10766                         nargs = 0;
10767
10768                 sig = mono_metadata_signature_alloc (image, nargs);
10769                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10770                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10771
10772                 if (helper->call_conv == 0) /* unmanaged */
10773                         sig->call_convention = helper->unmanaged_call_conv - 1;
10774                 else
10775                         if (helper->call_conv & 0x02)
10776                                 sig->call_convention = MONO_CALL_VARARG;
10777                 else
10778                         sig->call_convention = MONO_CALL_DEFAULT;
10779
10780                 sig->param_count = nargs;
10781                 /* TODO: Copy type ? */
10782                 sig->ret = helper->return_type->type;
10783                 for (i = 0; i < nargs; ++i) {
10784                         MonoReflectionType *rt = mono_type_array_get (helper->arguments, i);
10785                         sig->params [i] = rt->type;
10786                 }
10787
10788                 result = sig;
10789                 *handle_class = NULL;
10790         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10791                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10792                 /* Already created by the managed code */
10793                 g_assert (method->mhandle);
10794                 result = method->mhandle;
10795                 *handle_class = mono_defaults.methodhandle_class;
10796         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10797                 MonoReflectionType *tb = (MonoReflectionType*)obj;
10798                 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10799                 result = mono_class_from_mono_type (type);
10800                 *handle_class = mono_defaults.typehandle_class;
10801                 g_assert (result);
10802                 mono_metadata_free_type (type);
10803         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10804                 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10805                 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10806                 result = mono_class_from_mono_type (type);
10807                 *handle_class = mono_defaults.typehandle_class;
10808                 g_assert (result);
10809                 mono_metadata_free_type (type);
10810         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10811                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10812                 MonoClass *inflated;
10813                 MonoType *type;
10814
10815                 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10816                 inflated = mono_class_from_mono_type (type);
10817
10818                 g_assert (f->fb->handle);
10819                 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10820                 g_assert (result);
10821                 mono_metadata_free_type (type);
10822                 *handle_class = mono_defaults.fieldhandle_class;
10823         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10824                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10825                 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10826                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10827                 g_assert (c->cb->mhandle);
10828                 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10829                 *handle_class = mono_defaults.methodhandle_class;
10830                 mono_metadata_free_type (type);
10831         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10832                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10833                 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10834                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10835                 g_assert (m->mb->mhandle);
10836                 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10837                 *handle_class = mono_defaults.methodhandle_class;
10838                 mono_metadata_free_type (type);
10839         } else {
10840                 g_print (obj->vtable->klass->name);
10841                 g_assert_not_reached ();
10842         }
10843         return result;
10844 }
10845
10846 #else /* DISABLE_REFLECTION_EMIT */
10847
10848 MonoArray*
10849 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10850 {
10851         g_assert_not_reached ();
10852         return NULL;
10853 }
10854
10855 void
10856 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10857 {
10858         g_assert_not_reached ();
10859 }
10860
10861 void
10862 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10863 {
10864         g_assert_not_reached ();
10865 }
10866
10867 void
10868 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10869 {
10870         g_assert_not_reached ();
10871 }
10872
10873 void
10874 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10875 {
10876         g_assert_not_reached ();
10877 }
10878
10879 void
10880 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10881 {
10882         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10883 }
10884
10885 void
10886 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10887 {
10888         g_assert_not_reached ();
10889 }
10890
10891 MonoReflectionModule *
10892 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10893 {
10894         g_assert_not_reached ();
10895         return NULL;
10896 }
10897
10898 guint32
10899 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10900 {
10901         g_assert_not_reached ();
10902         return 0;
10903 }
10904
10905 guint32
10906 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10907 {
10908         g_assert_not_reached ();
10909         return 0;
10910 }
10911
10912 guint32
10913 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
10914                                                  gboolean create_methodspec, gboolean register_token)
10915 {
10916         g_assert_not_reached ();
10917         return 0;
10918 }
10919
10920 void
10921 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10922 {
10923 }
10924
10925 void
10926 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10927                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10928                                           MonoArray *events)
10929 {
10930         g_assert_not_reached ();
10931 }
10932
10933 void
10934 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10935 {
10936         *overrides = NULL;
10937         *num_overrides = 0;
10938 }
10939
10940 MonoReflectionEvent *
10941 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10942 {
10943         g_assert_not_reached ();
10944         return NULL;
10945 }
10946
10947 MonoReflectionType*
10948 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10949 {
10950         g_assert_not_reached ();
10951         return NULL;
10952 }
10953
10954 void
10955 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10956 {
10957         g_assert_not_reached ();
10958 }
10959
10960 MonoArray *
10961 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10962 {
10963         g_assert_not_reached ();
10964         return NULL;
10965 }
10966
10967 MonoArray *
10968 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10969 {
10970         g_assert_not_reached ();
10971         return NULL;
10972 }
10973
10974 void 
10975 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10976 {
10977 }
10978
10979 gpointer
10980 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10981 {
10982         return NULL;
10983 }
10984
10985 #endif /* DISABLE_REFLECTION_EMIT */
10986
10987 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10988 const static guint32 declsec_flags_map[] = {
10989         0x00000000,                                     /* empty */
10990         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
10991         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
10992         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
10993         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
10994         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
10995         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
10996         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
10997         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
10998         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
10999         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
11000         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
11001         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
11002         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
11003         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
11004         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
11005         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
11006         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
11007         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
11008 };
11009
11010 /*
11011  * Returns flags that includes all available security action associated to the handle.
11012  * @token: metadata token (either for a class or a method)
11013  * @image: image where resides the metadata.
11014  */
11015 static guint32
11016 mono_declsec_get_flags (MonoImage *image, guint32 token)
11017 {
11018         int index = mono_metadata_declsec_from_index (image, token);
11019         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11020         guint32 result = 0;
11021         guint32 action;
11022         int i;
11023
11024         /* HasSecurity can be present for other, not specially encoded, attributes,
11025            e.g. SuppressUnmanagedCodeSecurityAttribute */
11026         if (index < 0)
11027                 return 0;
11028
11029         for (i = index; i < t->rows; i++) {
11030                 guint32 cols [MONO_DECL_SECURITY_SIZE];
11031
11032                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11033                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11034                         break;
11035
11036                 action = cols [MONO_DECL_SECURITY_ACTION];
11037                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11038                         result |= declsec_flags_map [action];
11039                 } else {
11040                         g_assert_not_reached ();
11041                 }
11042         }
11043         return result;
11044 }
11045
11046 /*
11047  * Get the security actions (in the form of flags) associated with the specified method.
11048  *
11049  * @method: The method for which we want the declarative security flags.
11050  * Return the declarative security flags for the method (only).
11051  *
11052  * Note: To keep MonoMethod size down we do not cache the declarative security flags
11053  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
11054  */
11055 guint32
11056 mono_declsec_flags_from_method (MonoMethod *method)
11057 {
11058         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11059                 /* FIXME: No cache (for the moment) */
11060                 guint32 idx = mono_method_get_index (method);
11061                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11062                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11063                 return mono_declsec_get_flags (method->klass->image, idx);
11064         }
11065         return 0;
11066 }
11067
11068 /*
11069  * Get the security actions (in the form of flags) associated with the specified class.
11070  *
11071  * @klass: The class for which we want the declarative security flags.
11072  * Return the declarative security flags for the class.
11073  *
11074  * Note: We cache the flags inside the MonoClass structure as this will get 
11075  *       called very often (at least for each method).
11076  */
11077 guint32
11078 mono_declsec_flags_from_class (MonoClass *klass)
11079 {
11080         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11081                 if (!klass->ext || !klass->ext->declsec_flags) {
11082                         guint32 idx;
11083
11084                         idx = mono_metadata_token_index (klass->type_token);
11085                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11086                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11087                         mono_loader_lock ();
11088                         mono_class_alloc_ext (klass);
11089                         mono_loader_unlock ();
11090                         /* we cache the flags on classes */
11091                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11092                 }
11093                 return klass->ext->declsec_flags;
11094         }
11095         return 0;
11096 }
11097
11098 /*
11099  * Get the security actions (in the form of flags) associated with the specified assembly.
11100  *
11101  * @assembly: The assembly for which we want the declarative security flags.
11102  * Return the declarative security flags for the assembly.
11103  */
11104 guint32
11105 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11106 {
11107         guint32 idx = 1; /* there is only one assembly */
11108         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11109         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11110         return mono_declsec_get_flags (assembly->image, idx);
11111 }
11112
11113
11114 /*
11115  * Fill actions for the specific index (which may either be an encoded class token or
11116  * an encoded method token) from the metadata image.
11117  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11118  */
11119 static MonoBoolean
11120 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11121         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11122 {
11123         MonoBoolean result = FALSE;
11124         MonoTableInfo *t;
11125         guint32 cols [MONO_DECL_SECURITY_SIZE];
11126         int index = mono_metadata_declsec_from_index (image, token);
11127         int i;
11128
11129         t  = &image->tables [MONO_TABLE_DECLSECURITY];
11130         for (i = index; i < t->rows; i++) {
11131                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11132
11133                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11134                         return result;
11135
11136                 /* if present only replace (class) permissions with method permissions */
11137                 /* if empty accept either class or method permissions */
11138                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11139                         if (!actions->demand.blob) {
11140                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11141                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11142                                 actions->demand.blob = (char*) (blob + 2);
11143                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11144                                 result = TRUE;
11145                         }
11146                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11147                         if (!actions->noncasdemand.blob) {
11148                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11149                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11150                                 actions->noncasdemand.blob = (char*) (blob + 2);
11151                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11152                                 result = TRUE;
11153                         }
11154                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11155                         if (!actions->demandchoice.blob) {
11156                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11157                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11158                                 actions->demandchoice.blob = (char*) (blob + 2);
11159                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11160                                 result = TRUE;
11161                         }
11162                 }
11163         }
11164
11165         return result;
11166 }
11167
11168 static MonoBoolean
11169 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
11170         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11171 {
11172         guint32 idx = mono_metadata_token_index (klass->type_token);
11173         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11174         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11175         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11176 }
11177
11178 static MonoBoolean
11179 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
11180         guint32 id_std, guint32 id_noncas, guint32 id_choice)
11181 {
11182         guint32 idx = mono_method_get_index (method);
11183         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11184         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11185         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11186 }
11187
11188 /*
11189  * Collect all actions (that requires to generate code in mini) assigned for
11190  * the specified method.
11191  * Note: Don't use the content of actions if the function return FALSE.
11192  */
11193 MonoBoolean
11194 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11195 {
11196         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
11197                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11198         MonoBoolean result = FALSE;
11199         guint32 flags;
11200
11201         /* quick exit if no declarative security is present in the metadata */
11202         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11203                 return FALSE;
11204
11205         /* we want the original as the wrapper is "free" of the security informations */
11206         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11207                 method = mono_marshal_method_from_wrapper (method);
11208                 if (!method)
11209                         return FALSE;
11210         }
11211
11212         /* First we look for method-level attributes */
11213         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11214                 mono_class_init (method->klass);
11215                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11216
11217                 result = mono_declsec_get_method_demands_params (method, demands, 
11218                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11219         }
11220
11221         /* Here we use (or create) the class declarative cache to look for demands */
11222         flags = mono_declsec_flags_from_class (method->klass);
11223         if (flags & mask) {
11224                 if (!result) {
11225                         mono_class_init (method->klass);
11226                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
11227                 }
11228                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
11229                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11230         }
11231
11232         /* The boolean return value is used as a shortcut in case nothing needs to
11233            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11234         return result;
11235 }
11236
11237
11238 /*
11239  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11240  *
11241  * Note: Don't use the content of actions if the function return FALSE.
11242  */
11243 MonoBoolean
11244 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11245 {
11246         MonoBoolean result = FALSE;
11247         guint32 flags;
11248
11249         /* quick exit if no declarative security is present in the metadata */
11250         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11251                 return FALSE;
11252
11253         /* we want the original as the wrapper is "free" of the security informations */
11254         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11255                 method = mono_marshal_method_from_wrapper (method);
11256                 if (!method)
11257                         return FALSE;
11258         }
11259
11260         /* results are independant - zeroize both */
11261         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11262         memset (klass, 0, sizeof (MonoDeclSecurityActions));
11263
11264         /* First we look for method-level attributes */
11265         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11266                 mono_class_init (method->klass);
11267
11268                 result = mono_declsec_get_method_demands_params (method, cmethod, 
11269                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11270         }
11271
11272         /* Here we use (or create) the class declarative cache to look for demands */
11273         flags = mono_declsec_flags_from_class (method->klass);
11274         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11275                 mono_class_init (method->klass);
11276
11277                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
11278                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11279         }
11280
11281         return result;
11282 }
11283
11284 /*
11285  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11286  *
11287  * @klass       The inherited class - this is the class that provides the security check (attributes)
11288  * @demans      
11289  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11290  * 
11291  * Note: Don't use the content of actions if the function return FALSE.
11292  */
11293 MonoBoolean
11294 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11295 {
11296         MonoBoolean result = FALSE;
11297         guint32 flags;
11298
11299         /* quick exit if no declarative security is present in the metadata */
11300         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11301                 return FALSE;
11302
11303         /* Here we use (or create) the class declarative cache to look for demands */
11304         flags = mono_declsec_flags_from_class (klass);
11305         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11306                 mono_class_init (klass);
11307                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11308
11309                 result |= mono_declsec_get_class_demands_params (klass, demands, 
11310                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11311         }
11312
11313         return result;
11314 }
11315
11316 /*
11317  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11318  *
11319  * Note: Don't use the content of actions if the function return FALSE.
11320  */
11321 MonoBoolean
11322 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11323 {
11324         /* quick exit if no declarative security is present in the metadata */
11325         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11326                 return FALSE;
11327
11328         /* we want the original as the wrapper is "free" of the security informations */
11329         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11330                 method = mono_marshal_method_from_wrapper (method);
11331                 if (!method)
11332                         return FALSE;
11333         }
11334
11335         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11336                 mono_class_init (method->klass);
11337                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11338
11339                 return mono_declsec_get_method_demands_params (method, demands, 
11340                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11341         }
11342         return FALSE;
11343 }
11344
11345
11346 static MonoBoolean
11347 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11348 {
11349         guint32 cols [MONO_DECL_SECURITY_SIZE];
11350         MonoTableInfo *t;
11351         int i;
11352
11353         int index = mono_metadata_declsec_from_index (image, token);
11354         if (index == -1)
11355                 return FALSE;
11356
11357         t =  &image->tables [MONO_TABLE_DECLSECURITY];
11358         for (i = index; i < t->rows; i++) {
11359                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11360
11361                 /* shortcut - index are ordered */
11362                 if (token != cols [MONO_DECL_SECURITY_PARENT])
11363                         return FALSE;
11364
11365                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11366                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11367                         entry->blob = (char*) (metadata + 2);
11368                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11369                         return TRUE;
11370                 }
11371         }
11372
11373         return FALSE;
11374 }
11375
11376 MonoBoolean
11377 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11378 {
11379         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11380                 guint32 idx = mono_method_get_index (method);
11381                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11382                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11383                 return get_declsec_action (method->klass->image, idx, action, entry);
11384         }
11385         return FALSE;
11386 }
11387
11388 MonoBoolean
11389 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11390 {
11391         /* use cache */
11392         guint32 flags = mono_declsec_flags_from_class (klass);
11393         if (declsec_flags_map [action] & flags) {
11394                 guint32 idx = mono_metadata_token_index (klass->type_token);
11395                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11396                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11397                 return get_declsec_action (klass->image, idx, action, entry);
11398         }
11399         return FALSE;
11400 }
11401
11402 MonoBoolean
11403 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11404 {
11405         guint32 idx = 1; /* there is only one assembly */
11406         idx <<= MONO_HAS_DECL_SECURITY_BITS;
11407         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11408
11409         return get_declsec_action (assembly->image, idx, action, entry);
11410 }
11411
11412 gboolean
11413 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11414 {
11415         MonoObject *res, *exc;
11416         void *params [1];
11417         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11418         static MonoMethod *method = NULL;
11419
11420         if (!System_Reflection_Emit_TypeBuilder) {
11421                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11422                 g_assert (System_Reflection_Emit_TypeBuilder);
11423         }
11424         if (method == NULL) {
11425                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11426                 g_assert (method);
11427         }
11428
11429         /* 
11430          * The result of mono_type_get_object () might be a System.MonoType but we
11431          * need a TypeBuilder so use klass->reflection_info.
11432          */
11433         g_assert (klass->reflection_info);
11434         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11435
11436         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11437
11438         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11439         if (exc)
11440                 return FALSE;
11441         else
11442                 return *(MonoBoolean*)mono_object_unbox (res);
11443 }