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