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