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