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