2004-09-28 Zoltan Varga <vargaz@freemail.hu>
[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, GUINT32_FROM_LE (*int32val));
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++ = 0; /* 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         mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4224         image->imp_names_offset = 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
4240         return image;
4241 }
4242
4243 /*
4244  * mono_image_basic_init:
4245  * @assembly: an assembly builder object
4246  *
4247  * Create the MonoImage that represents the assembly builder and setup some
4248  * of the helper hash table and the basic metadata streams.
4249  */
4250 void
4251 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4252 {
4253         MonoDynamicAssembly *assembly;
4254         MonoDynamicImage *image;
4255         
4256         MONO_ARCH_SAVE_REGS;
4257
4258         if (assemblyb->dynamic_assembly)
4259                 return;
4260
4261 #if HAVE_BOEHM_GC
4262         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4263 #else
4264         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4265 #endif
4266
4267         assembly->assembly.dynamic = TRUE;
4268         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4269         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4270         if (assemblyb->culture)
4271                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4272         else
4273                 assembly->assembly.aname.culture = g_strdup ("");
4274
4275         assembly->run = assemblyb->access != 2;
4276         assembly->save = assemblyb->access != 1;
4277
4278         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4279         assembly->assembly.aname.name = image->image.name;
4280         assembly->assembly.image = &image->image;
4281
4282         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4283         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4284 }
4285
4286 static int
4287 calc_section_size (MonoDynamicImage *assembly)
4288 {
4289         int nsections = 0;
4290
4291         /* alignment constraints */
4292         assembly->code.index += 3;
4293         assembly->code.index &= ~3;
4294         assembly->meta_size += 3;
4295         assembly->meta_size &= ~3;
4296         assembly->resources.index += 3;
4297         assembly->resources.index &= ~3;
4298
4299         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4300         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4301         nsections++;
4302
4303         if (assembly->win32_res) {
4304                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4305
4306                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4307                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4308                 nsections++;
4309         }
4310
4311         assembly->sections [MONO_SECTION_RELOC].size = 12;
4312         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4313         nsections++;
4314
4315         return nsections;
4316 }
4317
4318 typedef struct {
4319         guint32 id;
4320         guint32 offset;
4321         GSList *children;
4322         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4323 } ResTreeNode;
4324
4325 static int
4326 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4327 {
4328         ResTreeNode *t1 = (ResTreeNode*)a;
4329         ResTreeNode *t2 = (ResTreeNode*)b;
4330
4331         return t1->id - t2->id;
4332 }
4333
4334 /*
4335  * resource_tree_create:
4336  *
4337  *  Organize the resources into a resource tree.
4338  */
4339 static ResTreeNode *
4340 resource_tree_create (MonoArray *win32_resources)
4341 {
4342         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4343         GSList *l;
4344         int i;
4345
4346         tree = g_new0 (ResTreeNode, 1);
4347         
4348         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4349                 MonoReflectionWin32Resource *win32_res =
4350                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4351
4352                 /* Create node */
4353
4354                 lang_node = g_new0 (ResTreeNode, 1);
4355                 lang_node->id = win32_res->lang_id;
4356                 lang_node->win32_res = win32_res;
4357
4358                 /* Create type node if neccesary */
4359                 type_node = NULL;
4360                 for (l = tree->children; l; l = l->next)
4361                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4362                                 type_node = (ResTreeNode*)l->data;
4363                                 break;
4364                         }
4365
4366                 if (!type_node) {
4367                         type_node = g_new0 (ResTreeNode, 1);
4368                         type_node->id = win32_res->res_type;
4369
4370                         /* 
4371                          * The resource types have to be sorted otherwise
4372                          * Windows Explorer can't display the version information.
4373                          */
4374                         tree->children = g_slist_insert_sorted (tree->children, 
4375                                 type_node, resource_tree_compare_by_id);
4376                 }
4377
4378                 /* Create res node if neccesary */
4379                 res_node = NULL;
4380                 for (l = type_node->children; l; l = l->next)
4381                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4382                                 res_node = (ResTreeNode*)l->data;
4383                                 break;
4384                         }
4385
4386                 if (!res_node) {
4387                         res_node = g_new0 (ResTreeNode, 1);
4388                         res_node->id = win32_res->res_id;
4389                         type_node->children = g_slist_append (type_node->children, res_node);
4390                 }
4391
4392                 res_node->children = g_slist_append (res_node->children, lang_node);
4393         }
4394
4395         return tree;
4396 }
4397
4398 /*
4399  * resource_tree_encode:
4400  * 
4401  *   Encode the resource tree into the format used in the PE file.
4402  */
4403 static void
4404 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4405 {
4406         char *entries;
4407         MonoPEResourceDir dir;
4408         MonoPEResourceDirEntry dir_entry;
4409         MonoPEResourceDataEntry data_entry;
4410         GSList *l;
4411
4412         /*
4413          * For the format of the resource directory, see the article
4414          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4415          * Matt Pietrek
4416          */
4417
4418         memset (&dir, 0, sizeof (dir));
4419         memset (&dir_entry, 0, sizeof (dir_entry));
4420         memset (&data_entry, 0, sizeof (data_entry));
4421
4422         g_assert (sizeof (dir) == 16);
4423         g_assert (sizeof (dir_entry) == 8);
4424         g_assert (sizeof (data_entry) == 16);
4425
4426         node->offset = p - begin;
4427
4428         /* IMAGE_RESOURCE_DIRECTORY */
4429         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4430
4431         memcpy (p, &dir, sizeof (dir));
4432         p += sizeof (dir);
4433
4434         /* Reserve space for entries */
4435         entries = p;
4436         p += sizeof (dir_entry) * dir.res_id_entries;
4437
4438         /* Write children */
4439         for (l = node->children; l; l = l->next) {
4440                 ResTreeNode *child = (ResTreeNode*)l->data;
4441
4442                 if (child->win32_res) {
4443
4444                         child->offset = p - begin;
4445
4446                         /* IMAGE_RESOURCE_DATA_ENTRY */
4447                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4448                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4449
4450                         memcpy (p, &data_entry, sizeof (data_entry));
4451                         p += sizeof (data_entry);
4452
4453                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4454                         p += data_entry.rde_size;
4455                 } else {
4456                         resource_tree_encode (child, begin, p, &p);
4457                 }
4458         }
4459
4460         /* IMAGE_RESOURCE_ENTRY */
4461         for (l = node->children; l; l = l->next) {
4462                 ResTreeNode *child = (ResTreeNode*)l->data;
4463                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4464
4465                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4466                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4467
4468                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4469                 entries += sizeof (dir_entry);
4470         }
4471
4472         *endbuf = p;
4473 }
4474
4475 static void
4476 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4477 {
4478         char *buf;
4479         char *p;
4480         guint32 size, i;
4481         MonoReflectionWin32Resource *win32_res;
4482         ResTreeNode *tree;
4483
4484         if (!assemblyb->win32_resources)
4485                 return;
4486
4487         /*
4488          * Resources are stored in a three level tree inside the PE file.
4489          * - level one contains a node for each type of resource
4490          * - level two contains a node for each resource
4491          * - level three contains a node for each instance of a resource for a
4492          *   specific language.
4493          */
4494
4495         tree = resource_tree_create (assemblyb->win32_resources);
4496
4497         /* Estimate the size of the encoded tree */
4498         size = 0;
4499         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4500                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4501                 size += mono_array_length (win32_res->res_data);
4502         }
4503         /* Directory structure */
4504         size += mono_array_length (assemblyb->win32_resources) * 256;
4505         p = buf = g_malloc (size);
4506
4507         resource_tree_encode (tree, p, p, &p);
4508
4509         g_assert (p - buf < size);
4510
4511         assembly->win32_res = g_malloc (p - buf);
4512         assembly->win32_res_size = p - buf;
4513         memcpy (assembly->win32_res, buf, p - buf);
4514
4515         g_free (buf);
4516 }
4517
4518 static void
4519 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4520 {
4521         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4522         int i;
4523
4524         p += sizeof (MonoPEResourceDir);
4525         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4526                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4527                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4528                 if (dir_entry->is_dir) {
4529                         fixup_resource_directory (res_section, child, rva);
4530                 } else {
4531                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4532                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4533                 }
4534
4535                 p += sizeof (MonoPEResourceDirEntry);
4536         }
4537 }
4538
4539 /*
4540  * mono_image_create_pefile:
4541  * @mb: a module builder object
4542  * 
4543  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4544  * assembly->pefile where it can be easily retrieved later in chunks.
4545  */
4546 void
4547 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4548         MonoMSDOSHeader *msdos;
4549         MonoDotNetHeader *header;
4550         MonoSectionTable *section;
4551         MonoCLIHeader *cli_header;
4552         guint32 size, image_size, virtual_base, text_offset;
4553         guint32 header_start, section_start, file_offset, virtual_offset;
4554         MonoDynamicImage *assembly;
4555         MonoReflectionAssemblyBuilder *assemblyb;
4556         MonoDynamicStream *pefile;
4557         int i, nsections;
4558         guint32 *rva, value;
4559         guint16 *data16;
4560         guchar *p;
4561         static const unsigned char msheader[] = {
4562                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4563                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4564                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4565                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4566                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4567                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4568                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4569                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4570         };
4571
4572         assemblyb = mb->assemblyb;
4573
4574         mono_image_basic_init (assemblyb);
4575         assembly = mb->dynamic_image;
4576
4577         /* already created */
4578         if (assembly->pefile.index)
4579                 return;
4580         
4581         mono_image_build_metadata (mb);
4582
4583         if (mb->is_main && assemblyb->resources) {
4584                 int len = mono_array_length (assemblyb->resources);
4585                 for (i = 0; i < len; ++i)
4586                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4587         }
4588
4589         if (mb->resources) {
4590                 int len = mono_array_length (mb->resources);
4591                 for (i = 0; i < len; ++i)
4592                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4593         }
4594
4595         build_compressed_metadata (assembly);
4596
4597         if (mb->is_main)
4598                 assembly_add_win32_resources (assembly, assemblyb);
4599
4600         nsections = calc_section_size (assembly);
4601
4602         pefile = &assembly->pefile;
4603
4604         /* The DOS header and stub */
4605         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4606         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4607
4608         /* the dotnet header */
4609         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4610
4611         /* the section tables */
4612         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4613
4614         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4615         virtual_offset = VIRT_ALIGN;
4616         image_size = 0;
4617
4618         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4619                 if (!assembly->sections [i].size)
4620                         continue;
4621                 /* align offsets */
4622                 file_offset += FILE_ALIGN - 1;
4623                 file_offset &= ~(FILE_ALIGN - 1);
4624                 virtual_offset += VIRT_ALIGN - 1;
4625                 virtual_offset &= ~(VIRT_ALIGN - 1);
4626
4627                 assembly->sections [i].offset = file_offset;
4628                 assembly->sections [i].rva = virtual_offset;
4629
4630                 file_offset += assembly->sections [i].size;
4631                 virtual_offset += assembly->sections [i].size;
4632                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4633         }
4634
4635         file_offset += FILE_ALIGN - 1;
4636         file_offset &= ~(FILE_ALIGN - 1);
4637         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4638
4639         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4640
4641         /* back-patch info */
4642         msdos = (MonoMSDOSHeader*)pefile->data;
4643         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4644         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4645         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4646
4647         header = (MonoDotNetHeader*)(pefile->data + header_start);
4648         header->pesig [0] = 'P';
4649         header->pesig [1] = 'E';
4650         
4651         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4652         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4653         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4654         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4655         if (assemblyb->pekind == 1) {
4656                 /* it's a dll */
4657                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4658         } else {
4659                 /* it's an exe */
4660                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4661         }
4662
4663         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4664
4665         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4666         header->pe.pe_major = 6;
4667         header->pe.pe_minor = 0;
4668         size = assembly->sections [MONO_SECTION_TEXT].size;
4669         size += FILE_ALIGN - 1;
4670         size &= ~(FILE_ALIGN - 1);
4671         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4672         size = assembly->sections [MONO_SECTION_RSRC].size;
4673         size += FILE_ALIGN - 1;
4674         size &= ~(FILE_ALIGN - 1);
4675         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4676         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4677         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4678         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4679         /* pe_rva_entry_point always at the beginning of the text section */
4680         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4681
4682         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4683         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4684         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4685         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4686         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4687         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4688         size = section_start;
4689         size += FILE_ALIGN - 1;
4690         size &= ~(FILE_ALIGN - 1);
4691         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4692         size = image_size;
4693         size += VIRT_ALIGN - 1;
4694         size &= ~(VIRT_ALIGN - 1);
4695         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4696
4697         /*
4698         // Translate the PEFileKind value to the value expected by the Windows loader
4699         */
4700         {
4701                 short kind;
4702
4703                 /*
4704                 // PEFileKinds.Dll == 1
4705                 // PEFileKinds.ConsoleApplication == 2
4706                 // PEFileKinds.WindowApplication == 3
4707                 //
4708                 // need to get:
4709                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4710                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4711                 */
4712                 if (assemblyb->pekind == 3)
4713                         kind = 2;
4714                 else
4715                         kind = 3;
4716                 
4717                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4718         }    
4719         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4720         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4721         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4722         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4723         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4724         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4725
4726         /* fill data directory entries */
4727
4728         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4729         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4730
4731         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4732         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4733
4734         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4735         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4736         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4737         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4738         /* patch imported function RVA name */
4739         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4740         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4741
4742         /* the import table */
4743         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4744         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4745         /* patch imported dll RVA name and other entries in the dir */
4746         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4747         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4748         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4749         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4750         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4751         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4752
4753         p = (assembly->code.data + assembly->ilt_offset);
4754         value = (assembly->text_rva + assembly->imp_names_offset - 2);
4755         *p++ = (value) & 0xff;
4756         *p++ = (value >> 8) & (0xff);
4757         *p++ = (value >> 16) & (0xff);
4758         *p++ = (value >> 24) & (0xff);
4759
4760         /* the CLI header info */
4761         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4762         cli_header->ch_size = GUINT32_FROM_LE (72);
4763         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4764         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4765         if (assemblyb->entry_point) {
4766                 guint32 table_idx = 0;
4767                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4768                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4769                         table_idx = methodb->table_idx;
4770                 } else {
4771                         table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4772                 }
4773                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4774         } else {
4775                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4776         }
4777         /* The embedded managed resources */
4778         text_offset = assembly->text_rva + assembly->code.index;
4779         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4780         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4781         text_offset += assembly->resources.index;
4782         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4783         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4784         text_offset += assembly->meta_size;
4785         if (assembly->strong_name_size) {
4786                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4787                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4788                 text_offset += assembly->strong_name_size;
4789         }
4790
4791         /* write the section tables and section content */
4792         section = (MonoSectionTable*)(pefile->data + section_start);
4793         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4794                 static const char *section_names [] = {
4795                         ".text", ".rsrc", ".reloc"
4796                 };
4797                 if (!assembly->sections [i].size)
4798                         continue;
4799                 strcpy (section->st_name, section_names [i]);
4800                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4801                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4802                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4803                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4804                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4805                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4806                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4807                 switch (i) {
4808                 case MONO_SECTION_TEXT:
4809                         /* patch entry point */
4810                         p = (assembly->code.data + 2);
4811                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4812                         *p++ = (value) & 0xff;
4813                         *p++ = (value >> 8) & 0xff;
4814                         *p++ = (value >> 16) & 0xff;
4815                         *p++ = (value >> 24) & 0xff;
4816
4817                         text_offset = assembly->sections [i].offset;
4818                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4819                         text_offset += assembly->code.index;
4820                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4821                         text_offset += assembly->resources.index;
4822                         memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4823                         text_offset += assembly->meta_size;
4824                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4825
4826                         g_free (assembly->image.raw_metadata);
4827                         break;
4828                 case MONO_SECTION_RELOC:
4829                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4830                         *rva = GUINT32_FROM_LE (assembly->text_rva);
4831                         ++rva;
4832                         *rva = GUINT32_FROM_LE (12);
4833                         ++rva;
4834                         data16 = (guint16*)rva;
4835                         /* 
4836                          * the entrypoint is always at the start of the text section 
4837                          * 3 is IMAGE_REL_BASED_HIGHLOW
4838                          * 2 is patch_size_rva - text_rva
4839                          */
4840                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4841                         data16++;
4842                         *data16 = 0; /* terminate */
4843                         break;
4844                 case MONO_SECTION_RSRC:
4845                         if (assembly->win32_res) {
4846                                 text_offset = assembly->sections [i].offset;
4847
4848                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4849                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4850
4851                                 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4852                         }
4853                         break;
4854                 default:
4855                         g_assert_not_reached ();
4856                 }
4857                 section++;
4858         }
4859         
4860         /* check that the file is properly padded */
4861 #if 0
4862         {
4863                 FILE *f = fopen ("mypetest.exe", "w");
4864                 fwrite (pefile->data, pefile->index, 1, f);
4865                 fclose (f);
4866         }
4867 #endif
4868 }
4869
4870 MonoReflectionModule *
4871 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4872 {
4873         char *name;
4874         MonoImage *image;
4875         MonoImageOpenStatus status;
4876         MonoDynamicAssembly *assembly;
4877         guint32 module_count;
4878         MonoImage **new_modules;
4879         
4880         name = mono_string_to_utf8 (fileName);
4881
4882         image = mono_image_open (name, &status);
4883         if (status) {
4884                 MonoException *exc;
4885                 if (status == MONO_IMAGE_ERROR_ERRNO)
4886                         exc = mono_get_exception_file_not_found (fileName);
4887                 else
4888                         exc = mono_get_exception_bad_image_format (name);
4889                 g_free (name);
4890                 mono_raise_exception (exc);
4891         }
4892
4893         g_free (name);
4894
4895         assembly = ab->dynamic_assembly;
4896         image->assembly = (MonoAssembly*)assembly;
4897
4898         module_count = image->assembly->image->module_count;
4899         new_modules = g_new0 (MonoImage *, module_count + 1);
4900
4901         if (image->assembly->image->modules)
4902                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4903         new_modules [module_count] = image;
4904
4905         g_free (image->assembly->image->modules);
4906         image->assembly->image->modules = new_modules;
4907         image->assembly->image->module_count ++;
4908
4909         mono_assembly_load_references (image, &status);
4910         if (status) {
4911                 mono_image_close (image);
4912                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4913         }
4914
4915         return mono_module_get_object (mono_domain_get (), image);
4916 }
4917
4918 /*
4919  * We need to return always the same object for MethodInfo, FieldInfo etc..
4920  * but we need to consider the reflected type.
4921  * type uses a different hash, since it uses custom hash/equal functions.
4922  */
4923
4924 typedef struct {
4925         gpointer item;
4926         MonoClass *refclass;
4927 } ReflectedEntry;
4928
4929 static gboolean
4930 reflected_equal (gconstpointer a, gconstpointer b) {
4931         const ReflectedEntry *ea = a;
4932         const ReflectedEntry *eb = b;
4933
4934         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4935 }
4936
4937 static guint
4938 reflected_hash (gconstpointer a) {
4939         const ReflectedEntry *ea = a;
4940         return GPOINTER_TO_UINT (ea->item);
4941 }
4942
4943 #define CHECK_OBJECT(t,p,k)     \
4944         do {    \
4945                 t _obj; \
4946                 ReflectedEntry e;       \
4947                 e.item = (p);   \
4948                 e.refclass = (k);       \
4949                 mono_domain_lock (domain);      \
4950                 if (!domain->refobject_hash)    \
4951                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
4952                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
4953                         mono_domain_unlock (domain);    \
4954                         return _obj;    \
4955                 }       \
4956         } while (0)
4957
4958 #if HAVE_BOEHM_GC
4959 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4960 #else
4961 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4962 #endif
4963
4964 #define CACHE_OBJECT(p,o,k)     \
4965         do {    \
4966                 ReflectedEntry *e = ALLOC_REFENTRY;     \
4967                 e->item = (p);  \
4968                 e->refclass = (k);      \
4969                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4970                 mono_domain_unlock (domain);    \
4971         } while (0)
4972
4973 static void 
4974 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4975 {
4976         /* this is done only once */
4977         mono_domain_lock (domain);
4978         CACHE_OBJECT (assembly, res, NULL);
4979 }
4980
4981 static void
4982 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4983 {
4984         /* this is done only once */
4985         mono_domain_lock (domain);
4986         CACHE_OBJECT (module, res, NULL);
4987 }
4988
4989 void
4990 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4991 {
4992         MonoDynamicImage *image = moduleb->dynamic_image;
4993         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4994         if (!image) {
4995                 /*
4996                  * FIXME: we already created an image in mono_image_basic_init (), but
4997                  * we don't know which module it belongs to, since that is only 
4998                  * determined at assembly save time.
4999                  */
5000                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5001                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5002
5003                 moduleb->module.image = &image->image;
5004                 moduleb->dynamic_image = image;
5005                 register_module (mono_object_domain (moduleb), moduleb, image);
5006         }
5007 }
5008
5009 /*
5010  * mono_assembly_get_object:
5011  * @domain: an app domain
5012  * @assembly: an assembly
5013  *
5014  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5015  */
5016 MonoReflectionAssembly*
5017 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5018 {
5019         static MonoClass *System_Reflection_Assembly;
5020         MonoReflectionAssembly *res;
5021         
5022         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5023         if (!System_Reflection_Assembly)
5024                 System_Reflection_Assembly = mono_class_from_name (
5025                         mono_defaults.corlib, "System.Reflection", "Assembly");
5026         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5027         res->assembly = assembly;
5028         CACHE_OBJECT (assembly, res, NULL);
5029         return res;
5030 }
5031
5032
5033
5034 MonoReflectionModule*   
5035 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5036 {
5037         static MonoClass *System_Reflection_Module;
5038         MonoReflectionModule *res;
5039         
5040         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5041         if (!System_Reflection_Module)
5042                 System_Reflection_Module = mono_class_from_name (
5043                         mono_defaults.corlib, "System.Reflection", "Module");
5044         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5045
5046         res->image = image;
5047         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5048
5049         res->fqname    = mono_string_new (domain, image->name);
5050         res->name      = mono_string_new (domain, g_path_get_basename (image->name));
5051         res->scopename = mono_string_new (domain, image->module_name);
5052
5053         if (image->assembly->image == image) {
5054                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5055         } else {
5056                 int i;
5057                 g_assert (image->assembly->image->modules);
5058                 res->token = 0;
5059                 for (i = 0; i < image->assembly->image->module_count; i++) {
5060                         if (image->assembly->image->modules [i] == image)
5061                                 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5062                 }
5063                 g_assert (res->token);
5064         }
5065
5066         mono_image_addref (image);
5067
5068         CACHE_OBJECT (image, res, NULL);
5069         return res;
5070 }
5071
5072 MonoReflectionModule*   
5073 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5074 {
5075         static MonoClass *System_Reflection_Module;
5076         MonoReflectionModule *res;
5077         MonoTableInfo *table;
5078         guint32 cols [MONO_FILE_SIZE];
5079         const char *name;
5080         guint32 i, name_idx;
5081         const char *val;
5082         
5083         if (!System_Reflection_Module)
5084                 System_Reflection_Module = mono_class_from_name (
5085                         mono_defaults.corlib, "System.Reflection", "Module");
5086         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5087
5088         table = &image->tables [MONO_TABLE_FILE];
5089         g_assert (table_index < table->rows);
5090         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5091
5092         res->image = 0;
5093         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5094         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5095
5096         /* Check whenever the row has a corresponding row in the moduleref table */
5097         table = &image->tables [MONO_TABLE_MODULEREF];
5098         for (i = 0; i < table->rows; ++i) {
5099                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5100                 val = mono_metadata_string_heap (image, name_idx);
5101                 if (strcmp (val, name) == 0)
5102                         res->image = image->modules [i];
5103         }
5104
5105         res->fqname    = mono_string_new (domain, name);
5106         res->name      = mono_string_new (domain, name);
5107         res->scopename = mono_string_new (domain, name);
5108         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5109         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5110
5111         return res;
5112 }
5113
5114 static gboolean
5115 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5116 {
5117         if ((t1->type != t2->type) ||
5118             (t1->byref != t2->byref))
5119                 return FALSE;
5120
5121         switch (t1->type) {
5122         case MONO_TYPE_VOID:
5123         case MONO_TYPE_BOOLEAN:
5124         case MONO_TYPE_CHAR:
5125         case MONO_TYPE_I1:
5126         case MONO_TYPE_U1:
5127         case MONO_TYPE_I2:
5128         case MONO_TYPE_U2:
5129         case MONO_TYPE_I4:
5130         case MONO_TYPE_U4:
5131         case MONO_TYPE_I8:
5132         case MONO_TYPE_U8:
5133         case MONO_TYPE_R4:
5134         case MONO_TYPE_R8:
5135         case MONO_TYPE_STRING:
5136         case MONO_TYPE_I:
5137         case MONO_TYPE_U:
5138         case MONO_TYPE_OBJECT:
5139         case MONO_TYPE_TYPEDBYREF:
5140                 return TRUE;
5141         case MONO_TYPE_VALUETYPE:
5142         case MONO_TYPE_CLASS:
5143         case MONO_TYPE_SZARRAY:
5144                 return t1->data.klass == t2->data.klass;
5145         case MONO_TYPE_PTR:
5146                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5147         case MONO_TYPE_ARRAY:
5148                 if (t1->data.array->rank != t2->data.array->rank)
5149                         return FALSE;
5150                 return t1->data.array->eklass == t2->data.array->eklass;
5151         case MONO_TYPE_GENERICINST: {
5152                 int i;
5153                 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5154                         return FALSE;
5155                 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5156                         return FALSE;
5157                 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5158                         if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5159                                 return FALSE;
5160                 }
5161                 return TRUE;
5162         }
5163         case MONO_TYPE_VAR:
5164         case MONO_TYPE_MVAR:
5165                 return t1->data.generic_param == t2->data.generic_param;
5166         default:
5167                 g_error ("implement type compare for %0x!", t1->type);
5168                 return FALSE;
5169         }
5170
5171         return FALSE;
5172 }
5173
5174 static guint
5175 mymono_metadata_type_hash (MonoType *t1)
5176 {
5177         guint hash;
5178
5179         hash = t1->type;
5180
5181         hash |= t1->byref << 6; /* do not collide with t1->type values */
5182         switch (t1->type) {
5183         case MONO_TYPE_VALUETYPE:
5184         case MONO_TYPE_CLASS:
5185         case MONO_TYPE_SZARRAY:
5186                 /* check if the distribution is good enough */
5187                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5188         case MONO_TYPE_PTR:
5189                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5190         }
5191         return hash;
5192 }
5193
5194 static MonoReflectionGenericInst*
5195 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5196 {
5197         static MonoClass *System_Reflection_MonoGenericInst;
5198         MonoReflectionGenericInst *res;
5199         MonoGenericInst *ginst;
5200         MonoClass *gklass;
5201
5202         if (!System_Reflection_MonoGenericInst) {
5203                 System_Reflection_MonoGenericInst = mono_class_from_name (
5204                         mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5205                 g_assert (System_Reflection_MonoGenericInst);
5206         }
5207
5208         ginst = geninst->data.generic_inst;
5209         gklass = mono_class_from_mono_type (ginst->generic_type);
5210
5211         mono_class_init (ginst->klass);
5212
5213         res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5214
5215         res->type.type = geninst;
5216         if (gklass->wastypebuilder && gklass->reflection_info)
5217                 res->generic_type = gklass->reflection_info;
5218         else
5219                 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5220
5221         return res;
5222 }
5223
5224 /*
5225  * mono_type_get_object:
5226  * @domain: an app domain
5227  * @type: a type
5228  *
5229  * Return an System.MonoType object representing the type @type.
5230  */
5231 MonoReflectionType*
5232 mono_type_get_object (MonoDomain *domain, MonoType *type)
5233 {
5234         MonoReflectionType *res;
5235         MonoClass *klass = mono_class_from_mono_type (type);
5236
5237         mono_domain_lock (domain);
5238         if (!domain->type_hash)
5239                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
5240                                 (GCompareFunc)mymono_metadata_type_equal);
5241         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5242                 mono_domain_unlock (domain);
5243                 return res;
5244         }
5245         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5246                 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5247                 mono_g_hash_table_insert (domain->type_hash, type, res);
5248                 mono_domain_unlock (domain);
5249                 return res;
5250         }
5251         if (klass->reflection_info && !klass->wastypebuilder) {
5252                 /* g_assert_not_reached (); */
5253                 /* should this be considered an error condition? */
5254                 if (!type->byref) {
5255                         mono_domain_unlock (domain);
5256                         return klass->reflection_info;
5257                 }
5258         }
5259         mono_class_init (klass);
5260         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5261         res->type = type;
5262         mono_g_hash_table_insert (domain->type_hash, type, res);
5263         mono_domain_unlock (domain);
5264         return res;
5265 }
5266
5267 /*
5268  * mono_method_get_object:
5269  * @domain: an app domain
5270  * @method: a method
5271  * @refclass: the reflected type (can be NULL)
5272  *
5273  * Return an System.Reflection.MonoMethod object representing the method @method.
5274  */
5275 MonoReflectionMethod*
5276 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5277 {
5278         /*
5279          * We use the same C representation for methods and constructors, but the type 
5280          * name in C# is different.
5281          */
5282         const char *cname;
5283         MonoClass *klass;
5284         MonoReflectionMethod *ret;
5285
5286         if (!refclass)
5287                 refclass = method->klass;
5288
5289         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5290         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5291                 cname = "MonoCMethod";
5292         else
5293                 cname = "MonoMethod";
5294         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5295
5296         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5297         ret->method = method;
5298         ret->name = mono_string_new (domain, method->name);
5299         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5300         CACHE_OBJECT (method, ret, refclass);
5301         return ret;
5302 }
5303
5304 /*
5305  * mono_field_get_object:
5306  * @domain: an app domain
5307  * @klass: a type
5308  * @field: a field
5309  *
5310  * Return an System.Reflection.MonoField object representing the field @field
5311  * in class @klass.
5312  */
5313 MonoReflectionField*
5314 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5315 {
5316         MonoReflectionField *res;
5317         MonoClass *oklass;
5318
5319         CHECK_OBJECT (MonoReflectionField *, field, klass);
5320         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5321         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5322         res->klass = klass;
5323         res->field = field;
5324         res->name = mono_string_new (domain, field->name);
5325         if (field->generic_info)
5326                 res->attrs = field->generic_info->generic_type->attrs;
5327         else
5328                 res->attrs = field->type->attrs;
5329         res->type = mono_type_get_object (domain, field->type);
5330         CACHE_OBJECT (field, res, klass);
5331         return res;
5332 }
5333
5334 /*
5335  * mono_property_get_object:
5336  * @domain: an app domain
5337  * @klass: a type
5338  * @property: a property
5339  *
5340  * Return an System.Reflection.MonoProperty object representing the property @property
5341  * in class @klass.
5342  */
5343 MonoReflectionProperty*
5344 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5345 {
5346         MonoReflectionProperty *res;
5347         MonoClass *oklass;
5348
5349         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5350         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5351         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5352         res->klass = klass;
5353         res->property = property;
5354         CACHE_OBJECT (property, res, klass);
5355         return res;
5356 }
5357
5358 /*
5359  * mono_event_get_object:
5360  * @domain: an app domain
5361  * @klass: a type
5362  * @event: a event
5363  *
5364  * Return an System.Reflection.MonoEvent object representing the event @event
5365  * in class @klass.
5366  */
5367 MonoReflectionEvent*
5368 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5369 {
5370         MonoReflectionEvent *res;
5371         MonoClass *oklass;
5372
5373         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5374         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5375         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5376         res->klass = klass;
5377         res->event = event;
5378         CACHE_OBJECT (event, res, klass);
5379         return res;
5380 }
5381
5382 /*
5383  * mono_param_get_objects:
5384  * @domain: an app domain
5385  * @method: a method
5386  *
5387  * Return an System.Reflection.ParameterInfo array object representing the parameters
5388  * in the method @method.
5389  */
5390 MonoArray*
5391 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5392 {
5393         static MonoClass *System_Reflection_ParameterInfo;
5394         MonoArray *res = NULL;
5395         MonoReflectionMethod *member = NULL;
5396         MonoReflectionParameter *param = NULL;
5397         char **names, **blobs = NULL;
5398         MonoObject *dbnull = mono_get_dbnull_object (domain);
5399         MonoMarshalSpec **mspecs;
5400         int i;
5401
5402         if (!System_Reflection_ParameterInfo)
5403                 System_Reflection_ParameterInfo = mono_class_from_name (
5404                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5405         
5406         if (!method->signature->param_count)
5407                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5408
5409         /* Note: the cache is based on the address of the signature into the method
5410          * since we already cache MethodInfos with the method as keys.
5411          */
5412         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5413
5414         member = mono_method_get_object (domain, method, NULL);
5415         names = g_new (char *, method->signature->param_count);
5416         mono_method_get_param_names (method, (const char **) names);
5417
5418         mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5419         mono_method_get_marshal_info (method, mspecs);
5420
5421         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5422         for (i = 0; i < method->signature->param_count; ++i) {
5423                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5424                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5425                 param->MemberImpl = (MonoObject*)member;
5426                 param->NameImpl = mono_string_new (domain, names [i]);
5427                 param->PositionImpl = i;
5428                 param->AttrsImpl = method->signature->params [i]->attrs;
5429
5430                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5431                         param->DefaultValueImpl = dbnull;
5432                 } else {
5433                         MonoType *type = param->ClassImpl->type;
5434                         
5435                         if (!blobs) {
5436                                 blobs = g_new0 (char *, method->signature->param_count);
5437                                 get_default_param_value_blobs (method, blobs); 
5438                         }
5439
5440                         param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5441
5442                         if (!param->DefaultValueImpl) {
5443                                 param->DefaultValueImpl = dbnull;
5444                         }
5445                 }
5446
5447                 if (mspecs [i + 1])
5448                         param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5449                 
5450                 mono_array_set (res, gpointer, i, param);
5451         }
5452         g_free (names);
5453         g_free (blobs);
5454
5455         for (i = method->signature->param_count; i >= 0; i--)
5456                 if (mspecs [i])
5457                         mono_metadata_free_marshal_spec (mspecs [i]);
5458         g_free (mspecs);
5459         
5460         CACHE_OBJECT (&(method->signature), res, NULL);
5461         return res;
5462 }
5463
5464 MonoObject *
5465 mono_get_dbnull_object (MonoDomain *domain)
5466 {
5467         MonoObject *obj;
5468         MonoClass *klass;
5469         static MonoClassField *dbnull_value_field = NULL;
5470         
5471         if (!dbnull_value_field) {
5472                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5473                 mono_class_init (klass);
5474                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5475                 g_assert (dbnull_value_field);
5476         }
5477         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5478         g_assert (obj);
5479         return obj;
5480 }
5481
5482
5483 static void
5484 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5485 {
5486         guint32 param_index, i, lastp, crow = 0;
5487         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5488         gint32 idx = -1;
5489
5490         MonoClass *klass = method->klass;
5491         MonoImage *image = klass->image;
5492         MonoMethodSignature *methodsig = method->signature;
5493
5494         MonoTableInfo *constt;
5495         MonoTableInfo *methodt;
5496         MonoTableInfo *paramt;
5497
5498         if (!methodsig->param_count)
5499                 return;
5500
5501         if (klass->generic_inst) {
5502                 return; /* FIXME - ??? */
5503         }
5504
5505         mono_class_init (klass);
5506
5507         if (klass->image->dynamic) {
5508                 return; /* FIXME */
5509         }
5510
5511         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5512         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5513         constt = &image->tables [MONO_TABLE_CONSTANT];
5514
5515         for (i = 0; i < klass->method.count; ++i) {
5516                 if (method == klass->methods [i]) {
5517                         idx = klass->method.first + i;
5518                         break;
5519                 }
5520         }
5521
5522         g_assert (idx != -1);
5523
5524         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5525         if (idx + 1 < methodt->rows)
5526                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5527         else
5528                 lastp = paramt->rows + 1;
5529
5530         for (i = param_index; i < lastp; ++i) {
5531                 guint32 paramseq;
5532
5533                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5534                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5535
5536                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5537                         continue;
5538
5539                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5540                 if (!crow) {
5541                         continue;
5542                 }
5543         
5544                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5545                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5546         }
5547
5548         return;
5549 }
5550
5551 static MonoObject *
5552 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5553 {
5554         void *retval;
5555         MonoClass *klass;
5556         MonoObject *object;
5557
5558         if (!blob)
5559                 return NULL;
5560         
5561         klass = mono_class_from_mono_type (type);
5562         if (klass->valuetype) {
5563                 object = mono_object_new (domain, klass);
5564                 retval = ((gchar *) object + sizeof (MonoObject));
5565         } else {
5566                 retval = &object;
5567         }
5568                         
5569         if (!mono_get_constant_value_from_blob (domain, type->type,  blob, retval))
5570                 return object;
5571         else
5572                 return NULL;
5573 }
5574
5575 static int
5576 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5577         int found_sep;
5578         char *s;
5579
5580         memset (assembly, 0, sizeof (MonoAssemblyName));
5581         assembly->name = p;
5582         assembly->culture = "";
5583         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5584
5585         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5586                 p++;
5587         found_sep = 0;
5588         while (*p == ' ' || *p == ',') {
5589                 *p++ = 0;
5590                 found_sep = 1;
5591                 continue;
5592         }
5593         /* failed */
5594         if (!found_sep)
5595                 return 1;
5596         while (*p) {
5597                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5598                         p += 8;
5599                         assembly->major = strtoul (p, &s, 10);
5600                         if (s == p || *s != '.')
5601                                 return 1;
5602                         p = ++s;
5603                         assembly->minor = strtoul (p, &s, 10);
5604                         if (s == p || *s != '.')
5605                                 return 1;
5606                         p = ++s;
5607                         assembly->build = strtoul (p, &s, 10);
5608                         if (s == p || *s != '.')
5609                                 return 1;
5610                         p = ++s;
5611                         assembly->revision = strtoul (p, &s, 10);
5612                         if (s == p)
5613                                 return 1;
5614                         p = s;
5615                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5616                         p += 8;
5617                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5618                                 assembly->culture = "";
5619                                 p += 7;
5620                         } else {
5621                                 assembly->culture = p;
5622                                 while (*p && *p != ',') {
5623                                         p++;
5624                                 }
5625                         }
5626                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5627                         p += 15;
5628                         if (strncmp (p, "null", 4) == 0) {
5629                                 p += 4;
5630                         } else {
5631                                 int len;
5632                                 gchar *start = p;
5633                                 while (*p && *p != ',') {
5634                                         p++;
5635                                 }
5636                                 len = (p - start + 1);
5637                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5638                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5639                                 g_strlcpy (assembly->public_key_token, start, len);
5640                         }
5641                 } else {
5642                         while (*p && *p != ',')
5643                                 p++;
5644                 }
5645                 found_sep = 0;
5646                 while (*p == ' ' || *p == ',') {
5647                         *p++ = 0;
5648                         found_sep = 1;
5649                         continue;
5650                 }
5651                 /* failed */
5652                 if (!found_sep)
5653                         return 1;
5654         }
5655
5656         return 0;
5657 }
5658
5659 /*
5660  * mono_reflection_parse_type:
5661  * @name: type name
5662  *
5663  * Parse a type name as accepted by the GetType () method and output the info
5664  * extracted in the info structure.
5665  * the name param will be mangled, so, make a copy before passing it to this function.
5666  * The fields in info will be valid until the memory pointed to by name is valid.
5667  * Returns 0 on parse error.
5668  * See also mono_type_get_name () below.
5669  */
5670 int
5671 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5672
5673         char *start, *p, *w, *last_point, *startn;
5674         int in_modifiers = 0;
5675         int isbyref = 0, rank;
5676
5677         start = p = w = name;
5678
5679         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5680         info->name = info->name_space = NULL;
5681         info->nested = NULL;
5682         info->modifiers = NULL;
5683
5684         /* last_point separates the namespace from the name */
5685         last_point = NULL;
5686
5687         while (*p) {
5688                 switch (*p) {
5689                 case '+':
5690                         *p = 0; /* NULL terminate the name */
5691                         startn = p + 1;
5692                         info->nested = g_list_append (info->nested, startn);
5693                         /* we have parsed the nesting namespace + name */
5694                         if (info->name)
5695                                 break;
5696                         if (last_point) {
5697                                 info->name_space = start;
5698                                 *last_point = 0;
5699                                 info->name = last_point + 1;
5700                         } else {
5701                                 info->name_space = (char *)"";
5702                                 info->name = start;
5703                         }
5704                         break;
5705                 case '.':
5706                         last_point = w;
5707                         break;
5708                 case '\\':
5709                         ++p;
5710                         break;
5711                 case '&':
5712                 case '*':
5713                 case '[':
5714                 case ',':
5715                         in_modifiers = 1;
5716                         break;
5717                 default:
5718                         break;
5719                 }
5720                 if (in_modifiers)
5721                         break;
5722                 *w++ = *p++;
5723         }
5724         
5725         if (!info->name) {
5726                 if (last_point) {
5727                         info->name_space = start;
5728                         *last_point = 0;
5729                         info->name = last_point + 1;
5730                 } else {
5731                         info->name_space = (char *)"";
5732                         info->name = start;
5733                 }
5734         }
5735         while (*p) {
5736                 switch (*p) {
5737                 case '&':
5738                         if (isbyref) /* only one level allowed by the spec */
5739                                 return 0;
5740                         isbyref = 1;
5741                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5742                         *p++ = 0;
5743                         break;
5744                 case '*':
5745                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5746                         *p++ = 0;
5747                         break;
5748                 case '[':
5749                         rank = 1;
5750                         *p++ = 0;
5751                         while (*p) {
5752                                 if (*p == ']')
5753                                         break;
5754                                 if (*p == ',')
5755                                         rank++;
5756                                 else if (*p != '*') /* '*' means unknown lower bound */
5757                                         return 0;
5758                                 ++p;
5759                         }
5760                         if (*p++ != ']')
5761                                 return 0;
5762                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5763                         break;
5764                 case ',':
5765                         *p++ = 0;
5766                         while (*p) {
5767                                 if (*p == ' ') {
5768                                         ++p;
5769                                         continue;
5770                                 }
5771                                 break;
5772                         }
5773                         if (!*p)
5774                                 return 0; /* missing assembly name */
5775                         if (!assembly_name_to_aname (&info->assembly, p))
5776                                 return 0;
5777                         break;
5778                 default:
5779                         return 0;
5780                         break;
5781                 }
5782                 if (info->assembly.name)
5783                         break;
5784         }
5785         *w = 0; /* terminate class name */
5786         if (!info->name || !*info->name)
5787                 return 0;
5788         /* add other consistency checks */
5789         return 1;
5790 }
5791
5792 static MonoType*
5793 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5794 {
5795         MonoClass *klass;
5796         GList *mod;
5797         int modval;
5798         
5799         if (!image)
5800                 image = mono_defaults.corlib;
5801
5802         if (ignorecase)
5803                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5804         else
5805                 klass = mono_class_from_name (image, info->name_space, info->name);
5806         if (!klass)
5807                 return NULL;
5808         for (mod = info->nested; mod; mod = mod->next) {
5809                 GList *nested;
5810
5811                 mono_class_init (klass);
5812                 nested = klass->nested_classes;
5813                 klass = NULL;
5814                 while (nested) {
5815                         klass = nested->data;
5816                         if (ignorecase) {
5817                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5818                                         break;
5819                         } else {
5820                                 if (strcmp (klass->name, mod->data) == 0)
5821                                         break;
5822                         }
5823                         klass = NULL;
5824                         nested = nested->next;
5825                 }
5826                 if (!klass)
5827                         break;
5828         }
5829         if (!klass)
5830                 return NULL;
5831         mono_class_init (klass);
5832         for (mod = info->modifiers; mod; mod = mod->next) {
5833                 modval = GPOINTER_TO_UINT (mod->data);
5834                 if (!modval) { /* byref: must be last modifier */
5835                         return &klass->this_arg;
5836                 } else if (modval == -1) {
5837                         klass = mono_ptr_class_get (&klass->byval_arg);
5838                 } else { /* array rank */
5839                         klass = mono_array_class_get (klass, modval);
5840                 }
5841                 mono_class_init (klass);
5842         }
5843
5844         return &klass->byval_arg;
5845 }
5846
5847 /*
5848  * mono_reflection_get_type:
5849  * @image: a metadata context
5850  * @info: type description structure
5851  * @ignorecase: flag for case-insensitive string compares
5852  * @type_resolve: whenever type resolve was already tried
5853  *
5854  * Build a MonoType from the type description in @info.
5855  * 
5856  */
5857
5858 MonoType*
5859 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5860 {
5861         MonoType *type;
5862         MonoReflectionAssembly *assembly;
5863         GString *fullName;
5864         GList *mod;
5865
5866         type = mono_reflection_get_type_internal (image, info, ignorecase);
5867         if (type)
5868                 return type;
5869         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5870                 return NULL;
5871
5872         /* FIXME: Enabling this causes regressions (#65577) */
5873         /*
5874         if (type_resolve) {
5875                 if (*type_resolve) 
5876                         return NULL;
5877                 else
5878                         *type_resolve = TRUE;
5879         }
5880         */
5881         
5882         /* Reconstruct the type name */
5883         fullName = g_string_new ("");
5884         if (info->name_space && (info->name_space [0] != '\0'))
5885                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5886         else
5887                 g_string_printf (fullName, info->name);
5888         for (mod = info->nested; mod; mod = mod->next)
5889                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5890
5891         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5892         if (assembly && (!image || (assembly->assembly->image == image))) {
5893
5894                 if (assembly->assembly->dynamic) {
5895                         /* Enumerate all modules */
5896                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5897                         int i;
5898
5899                         type = NULL;
5900                         if (abuilder->modules) {
5901                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5902                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5903                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5904                                         if (type)
5905                                                 break;
5906                                 }
5907                         }
5908
5909                         if (!type && abuilder->loaded_modules) {
5910                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5911                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5912                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5913                                         if (type)
5914                                                 break;
5915                                 }
5916                         }
5917                 }
5918                 else
5919                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
5920                                                                                                           info, ignorecase);
5921         }
5922         g_string_free (fullName, TRUE);
5923         return type;
5924 }
5925
5926 /*
5927  * mono_reflection_type_from_name:
5928  * @name: type name.
5929  * @image: a metadata context (can be NULL).
5930  *
5931  * Retrieves a MonoType from its @name. If the name is not fully qualified,
5932  * it defaults to get the type from @image or, if @image is NULL or loading
5933  * from it fails, uses corlib.
5934  * 
5935  */
5936 MonoType*
5937 mono_reflection_type_from_name (char *name, MonoImage *image)
5938 {
5939         MonoType *type;
5940         MonoTypeNameParse info;
5941         MonoAssembly *assembly;
5942         char *tmp;
5943         gboolean type_resolve = FALSE;
5944
5945         /* Make a copy since parse_type modifies its argument */
5946         tmp = g_strdup (name);
5947         
5948         /*g_print ("requested type %s\n", str);*/
5949         if (!mono_reflection_parse_type (tmp, &info)) {
5950                 g_free (tmp);
5951                 g_list_free (info.modifiers);
5952                 g_list_free (info.nested);
5953                 return NULL;
5954         }
5955
5956         if (info.assembly.name) {
5957                 assembly = mono_assembly_loaded (&info.assembly);
5958                 if (!assembly) {
5959                         /* then we must load the assembly ourselve - see #60439 */
5960                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5961                         if (!assembly) {
5962                                 g_free (tmp);
5963                                 g_list_free (info.modifiers);
5964                                 g_list_free (info.nested);
5965                                 return NULL;
5966                         }
5967                 }
5968                 image = assembly->image;
5969         } else if (image == NULL) {
5970                 image = mono_defaults.corlib;
5971         }
5972
5973         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5974         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5975                 image = mono_defaults.corlib;
5976                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5977         }
5978
5979         g_free (tmp);
5980         g_list_free (info.modifiers);
5981         g_list_free (info.nested);
5982         return type;
5983 }
5984
5985 /*
5986  * mono_reflection_get_token:
5987  *
5988  *   Return the metadata token of OBJ which should be an object
5989  * representing a metadata element.
5990  */
5991 guint32
5992 mono_reflection_get_token (MonoObject *obj)
5993 {
5994         MonoClass *klass;
5995         guint32 token = 0;
5996
5997         klass = obj->vtable->klass;
5998
5999         if (strcmp (klass->name, "MethodBuilder") == 0) {
6000                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6001
6002                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6003         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6004                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6005
6006                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6007         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6008                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6009                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6010                 if (tb->generic_params) {
6011                         g_assert_not_reached ();
6012                 } else {
6013                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6014                 }
6015         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6016                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6017                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6018         } else if (strcmp (klass->name, "MonoType") == 0) {
6019                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6020                 token = mono_class_from_mono_type (tb->type)->type_token;
6021         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6022                         strcmp (klass->name, "MonoMethod") == 0) {
6023                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6024                 if (m->method->signature->is_inflated) {
6025                         g_assert_not_reached ();
6026                 } else if (m->method->signature->generic_param_count) {
6027                         g_assert_not_reached ();
6028                 } else if (m->method->klass->generic_inst) {
6029                         g_assert_not_reached ();
6030                 } else {
6031                         token = m->method->token;
6032                 }
6033         } else if (strcmp (klass->name, "MonoField") == 0) {
6034                 MonoReflectionField *f = (MonoReflectionField*)obj;
6035
6036                 token = mono_class_get_field_token (f->field);
6037         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6038                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6039
6040                 token = mono_class_get_property_token (p->property);
6041         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6042                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6043
6044                 token = mono_class_get_event_token (p->event);
6045         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6046                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6047
6048                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6049         } else if (strcmp (klass->name, "Module") == 0) {
6050                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6051
6052                 token = m->token;
6053         } else if (strcmp (klass->name, "Assembly") == 0) {
6054                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6055         } else {
6056                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6057                 MonoException *ex = mono_get_exception_not_implemented (msg);
6058                 g_free (msg);
6059                 mono_raise_exception (ex);
6060         }
6061
6062         return token;
6063 }
6064
6065 static void*
6066 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6067 {
6068         int slen, type = t->type;
6069 handle_enum:
6070         switch (type) {
6071         case MONO_TYPE_U1:
6072         case MONO_TYPE_I1:
6073         case MONO_TYPE_BOOLEAN: {
6074                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6075                 *bval = *p;
6076                 *end = p + 1;
6077                 return bval;
6078         }
6079         case MONO_TYPE_CHAR:
6080         case MONO_TYPE_U2:
6081         case MONO_TYPE_I2: {
6082                 guint16 *val = g_malloc (sizeof (guint16));
6083                 *val = read16 (p);
6084                 *end = p + 2;
6085                 return val;
6086         }
6087 #if SIZEOF_VOID_P == 4
6088         case MONO_TYPE_U:
6089         case MONO_TYPE_I:
6090 #endif
6091         case MONO_TYPE_R4:
6092         case MONO_TYPE_U4:
6093         case MONO_TYPE_I4: {
6094                 guint32 *val = g_malloc (sizeof (guint32));
6095                 *val = read32 (p);
6096                 *end = p + 4;
6097                 return val;
6098         }
6099 #if SIZEOF_VOID_P == 8
6100         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6101         case MONO_TYPE_I:
6102 #endif
6103         case MONO_TYPE_R8:
6104         case MONO_TYPE_U8:
6105         case MONO_TYPE_I8: {
6106                 guint64 *val = g_malloc (sizeof (guint64));
6107                 *val = read64 (p);
6108                 *end = p + 8;
6109                 return val;
6110         }
6111         case MONO_TYPE_VALUETYPE:
6112                 if (t->data.klass->enumtype) {
6113                         type = t->data.klass->enum_basetype->type;
6114                         goto handle_enum;
6115                 } else {
6116                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6117                 }
6118                 break;
6119         case MONO_TYPE_STRING:
6120                 if (*p == (char)0xFF) {
6121                         *end = p + 1;
6122                         return NULL;
6123                 }
6124                 slen = mono_metadata_decode_value (p, &p);
6125                 *end = p + slen;
6126                 return mono_string_new_len (mono_domain_get (), p, slen);
6127         case MONO_TYPE_CLASS: {
6128                 char *n;
6129                 MonoType *t;
6130                 if (*p == (char)0xFF) {
6131                         *end = p + 1;
6132                         return NULL;
6133                 }
6134 handle_type:
6135                 slen = mono_metadata_decode_value (p, &p);
6136                 n = g_memdup (p, slen + 1);
6137                 n [slen] = 0;
6138                 t = mono_reflection_type_from_name (n, image);
6139                 if (!t)
6140                         g_warning ("Cannot load type '%s'", n);
6141                 g_free (n);
6142                 *end = p + slen;
6143                 if (t)
6144                         return mono_type_get_object (mono_domain_get (), t);
6145                 else
6146                         return NULL;
6147         }
6148         case MONO_TYPE_OBJECT: {
6149                 char subt = *p++;
6150                 MonoObject *obj;
6151                 MonoClass *subc = NULL;
6152                 void *val;
6153
6154                 if (subt == 0x50) {
6155                         goto handle_type;
6156                 } else if (subt == 0x0E) {
6157                         type = MONO_TYPE_STRING;
6158                         goto handle_enum;
6159                 } else if (subt == 0x55) {
6160                         char *n;
6161                         MonoType *t;
6162                         slen = mono_metadata_decode_value (p, &p);
6163                         n = g_memdup (p, slen + 1);
6164                         n [slen] = 0;
6165                         t = mono_reflection_type_from_name (n, image);
6166                         if (!t)
6167                                 g_warning ("Cannot load type '%s'", n);
6168                         g_free (n);
6169                         p += slen;
6170                         subc = mono_class_from_mono_type (t);
6171                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6172                         MonoType simple_type = {{0}};
6173                         simple_type.type = subt;
6174                         subc = mono_class_from_mono_type (&simple_type);
6175                 } else {
6176                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6177                 }
6178                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6179                 obj = mono_object_new (mono_domain_get (), subc);
6180                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6181                 g_free (val);
6182                 return obj;
6183         }
6184         case MONO_TYPE_SZARRAY: {
6185                 MonoArray *arr;
6186                 guint32 i, alen, basetype;
6187                 alen = read32 (p);
6188                 p += 4;
6189                 if (alen == 0xffffffff) {
6190                         *end = p;
6191                         return NULL;
6192                 }
6193                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6194                 basetype = t->data.klass->byval_arg.type;
6195                 switch (basetype)
6196                 {
6197                         case MONO_TYPE_U1:
6198                         case MONO_TYPE_I1:
6199                         case MONO_TYPE_BOOLEAN:
6200                                 for (i = 0; i < alen; i++) {
6201                                         MonoBoolean val = *p++;
6202                                         mono_array_set (arr, MonoBoolean, i, val);
6203                                 }
6204                                 break;
6205                         case MONO_TYPE_CHAR:
6206                         case MONO_TYPE_U2:
6207                         case MONO_TYPE_I2:
6208                                 for (i = 0; i < alen; i++) {
6209                                         guint16 val = read16 (p);
6210                                         mono_array_set (arr, guint16, i, val);
6211                                         p += 2;
6212                                 }
6213                                 break;
6214                         case MONO_TYPE_R4:
6215                         case MONO_TYPE_U4:
6216                         case MONO_TYPE_I4:
6217                                 for (i = 0; i < alen; i++) {
6218                                         guint32 val = read32 (p);
6219                                         mono_array_set (arr, guint32, i, val);
6220                                         p += 4;
6221                                 }
6222                                 break;
6223                         case MONO_TYPE_R8:
6224                         case MONO_TYPE_U8:
6225                         case MONO_TYPE_I8:
6226                                 for (i = 0; i < alen; i++) {
6227                                         guint64 val = read64 (p);
6228                                         mono_array_set (arr, guint64, i, val);
6229                                         p += 8;
6230                                 }
6231                                 break;
6232                         case MONO_TYPE_CLASS:
6233                         case MONO_TYPE_OBJECT:
6234                         case MONO_TYPE_STRING:
6235                                 for (i = 0; i < alen; i++) {
6236                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6237                                         mono_array_set (arr, gpointer, i, item);
6238                                 }
6239                                 break;
6240                         default:
6241                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6242                 }
6243                 *end=p;
6244                 return arr;
6245         }
6246         default:
6247                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6248         }
6249         return NULL;
6250 }
6251
6252 static gboolean
6253 type_is_reference (MonoType *type)
6254 {
6255         switch (type->type) {
6256         case MONO_TYPE_BOOLEAN:
6257         case MONO_TYPE_CHAR:
6258         case MONO_TYPE_U:
6259         case MONO_TYPE_I:
6260         case MONO_TYPE_U1:
6261         case MONO_TYPE_I1:
6262         case MONO_TYPE_U2:
6263         case MONO_TYPE_I2:
6264         case MONO_TYPE_U4:
6265         case MONO_TYPE_I4:
6266         case MONO_TYPE_U8:
6267         case MONO_TYPE_I8:
6268         case MONO_TYPE_R8:
6269         case MONO_TYPE_R4:
6270         case MONO_TYPE_VALUETYPE:
6271                 return FALSE;
6272         default:
6273                 return TRUE;
6274         }
6275 }
6276
6277 static void
6278 free_param_data (MonoMethodSignature *sig, void **params) {
6279         int i;
6280         for (i = 0; i < sig->param_count; ++i) {
6281                 if (!type_is_reference (sig->params [i]))
6282                         g_free (params [i]);
6283         }
6284 }
6285
6286 /*
6287  * Find the method index in the metadata methodDef table.
6288  * Later put these three helper methods in metadata and export them.
6289  */
6290 static guint32
6291 find_method_index (MonoMethod *method) {
6292         MonoClass *klass = method->klass;
6293         int i;
6294
6295         for (i = 0; i < klass->method.count; ++i) {
6296                 if (method == klass->methods [i])
6297                         return klass->method.first + 1 + i;
6298         }
6299         return 0;
6300 }
6301
6302 /*
6303  * Find the field index in the metadata FieldDef table.
6304  */
6305 static guint32
6306 find_field_index (MonoClass *klass, MonoClassField *field) {
6307         int i;
6308
6309         for (i = 0; i < klass->field.count; ++i) {
6310                 if (field == &klass->fields [i])
6311                         return klass->field.first + 1 + i;
6312         }
6313         return 0;
6314 }
6315
6316 /*
6317  * Find the property index in the metadata Property table.
6318  */
6319 static guint32
6320 find_property_index (MonoClass *klass, MonoProperty *property) {
6321         int i;
6322
6323         for (i = 0; i < klass->property.count; ++i) {
6324                 if (property == &klass->properties [i])
6325                         return klass->property.first + 1 + i;
6326         }
6327         return 0;
6328 }
6329
6330 /*
6331  * Find the event index in the metadata Event table.
6332  */
6333 static guint32
6334 find_event_index (MonoClass *klass, MonoEvent *event) {
6335         int i;
6336
6337         for (i = 0; i < klass->event.count; ++i) {
6338                 if (event == &klass->events [i])
6339                         return klass->event.first + 1 + i;
6340         }
6341         return 0;
6342 }
6343
6344 static MonoObject*
6345 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6346 {
6347         const char *p = data;
6348         const char *named;
6349         guint32 i, j, num_named;
6350         MonoObject *attr;
6351         void **params;
6352
6353         mono_class_init (method->klass);
6354
6355         if (len == 0) {
6356                 attr = mono_object_new (mono_domain_get (), method->klass);
6357                 mono_runtime_invoke (method, attr, NULL, NULL);
6358                 return attr;
6359         }
6360
6361         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6362                 return NULL;
6363
6364         /*g_print ("got attr %s\n", method->klass->name);*/
6365         
6366         params = g_new (void*, method->signature->param_count);
6367
6368         /* skip prolog */
6369         p += 2;
6370         for (i = 0; i < method->signature->param_count; ++i) {
6371                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6372         }
6373
6374         named = p;
6375         attr = mono_object_new (mono_domain_get (), method->klass);
6376         mono_runtime_invoke (method, attr, params, NULL);
6377         free_param_data (method->signature, params);
6378         g_free (params);
6379         num_named = read16 (named);
6380         named += 2;
6381         for (j = 0; j < num_named; j++) {
6382                 gint name_len;
6383                 char *name, named_type, data_type;
6384                 named_type = *named++;
6385                 data_type = *named++; /* type of data */
6386                 if (data_type == 0x55) {
6387                         gint type_len;
6388                         char *type_name;
6389                         type_len = mono_metadata_decode_blob_size (named, &named);
6390                         type_name = g_malloc (type_len + 1);
6391                         memcpy (type_name, named, type_len);
6392                         type_name [type_len] = 0;
6393                         named += type_len;
6394                         /* FIXME: lookup the type and check type consistency */
6395                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6396                         /* this seems to be the type of the element of the array */
6397                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6398                         named++;
6399                 }
6400                 name_len = mono_metadata_decode_blob_size (named, &named);
6401                 name = g_malloc (name_len + 1);
6402                 memcpy (name, named, name_len);
6403                 name [name_len] = 0;
6404                 named += name_len;
6405                 if (named_type == 0x53) {
6406                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6407                         void *val = load_cattr_value (image, field->type, named, &named);
6408                         mono_field_set_value (attr, field, val);
6409                         if (!type_is_reference (field->type))
6410                                 g_free (val);
6411                 } else if (named_type == 0x54) {
6412                         MonoProperty *prop;
6413                         void *pparams [1];
6414                         MonoType *prop_type;
6415
6416                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6417                         /* can we have more that 1 arg in a custom attr named property? */
6418                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6419                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6420                         mono_property_set_value (prop, attr, pparams, NULL);
6421                         if (!type_is_reference (prop_type))
6422                                 g_free (pparams [0]);
6423                 }
6424                 g_free (name);
6425         }
6426
6427         return attr;
6428 }
6429
6430 MonoArray*
6431 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6432 {
6433         MonoArray *result;
6434         MonoClass *klass;
6435         MonoObject *attr;
6436         int i;
6437
6438         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6439         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6440         for (i = 0; i < cinfo->num_attrs; ++i) {
6441                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6442                 mono_array_set (result, gpointer, i, attr);
6443         }
6444         return result;
6445 }
6446
6447 MonoCustomAttrInfo*
6448 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6449 {
6450         guint32 mtoken, i, len;
6451         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6452         MonoTableInfo *ca;
6453         MonoCustomAttrInfo *ainfo;
6454         GList *tmp, *list = NULL;
6455         const char *data;
6456
6457         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6458
6459         i = mono_metadata_custom_attrs_from_index (image, idx);
6460         if (!i)
6461                 return NULL;
6462         i --;
6463         while (i < ca->rows) {
6464                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6465                         break;
6466                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6467                 ++i;
6468         }
6469         len = g_list_length (list);
6470         if (!len)
6471                 return NULL;
6472         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6473         ainfo->num_attrs = len;
6474         ainfo->image = image;
6475         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6476                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6477                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6478                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6479                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6480                         mtoken |= MONO_TOKEN_METHOD_DEF;
6481                         break;
6482                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6483                         mtoken |= MONO_TOKEN_MEMBER_REF;
6484                         break;
6485                 default:
6486                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6487                         break;
6488                 }
6489                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6490                 if (!ainfo->attrs [i].ctor)
6491                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6492                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6493                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6494                 ainfo->attrs [i].data = data;
6495         }
6496         g_list_free (list);
6497
6498         return ainfo;
6499 }
6500
6501 MonoCustomAttrInfo*
6502 mono_custom_attrs_from_method (MonoMethod *method)
6503 {
6504         MonoCustomAttrInfo *cinfo;
6505         guint32 idx;
6506         
6507         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6508                 return cinfo;
6509         idx = find_method_index (method);
6510         idx <<= MONO_CUSTOM_ATTR_BITS;
6511         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6512         return mono_custom_attrs_from_index (method->klass->image, idx);
6513 }
6514
6515 MonoCustomAttrInfo*
6516 mono_custom_attrs_from_class (MonoClass *klass)
6517 {
6518         MonoCustomAttrInfo *cinfo;
6519         guint32 idx;
6520         
6521         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6522                 return cinfo;
6523         idx = mono_metadata_token_index (klass->type_token);
6524         idx <<= MONO_CUSTOM_ATTR_BITS;
6525         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6526         return mono_custom_attrs_from_index (klass->image, idx);
6527 }
6528
6529 MonoCustomAttrInfo*
6530 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6531 {
6532         MonoCustomAttrInfo *cinfo;
6533         guint32 idx;
6534         
6535         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6536                 return cinfo;
6537         idx = 1; /* there is only one assembly */
6538         idx <<= MONO_CUSTOM_ATTR_BITS;
6539         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6540         return mono_custom_attrs_from_index (assembly->image, idx);
6541 }
6542
6543 static MonoCustomAttrInfo*
6544 mono_custom_attrs_from_module (MonoImage *image)
6545 {
6546         MonoCustomAttrInfo *cinfo;
6547         guint32 idx;
6548         
6549         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6550                 return cinfo;
6551         idx = 1; /* there is only one module */
6552         idx <<= MONO_CUSTOM_ATTR_BITS;
6553         idx |= MONO_CUSTOM_ATTR_MODULE;
6554         return mono_custom_attrs_from_index (image, idx);
6555 }
6556
6557 MonoCustomAttrInfo*
6558 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6559 {
6560         MonoCustomAttrInfo *cinfo;
6561         guint32 idx;
6562         
6563         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6564                 return cinfo;
6565         idx = find_property_index (klass, property);
6566         idx <<= MONO_CUSTOM_ATTR_BITS;
6567         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6568         return mono_custom_attrs_from_index (klass->image, idx);
6569 }
6570
6571 MonoCustomAttrInfo*
6572 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6573 {
6574         MonoCustomAttrInfo *cinfo;
6575         guint32 idx;
6576         
6577         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6578                 return cinfo;
6579         idx = find_event_index (klass, event);
6580         idx <<= MONO_CUSTOM_ATTR_BITS;
6581         idx |= MONO_CUSTOM_ATTR_EVENT;
6582         return mono_custom_attrs_from_index (klass->image, idx);
6583 }
6584
6585 MonoCustomAttrInfo*
6586 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6587 {
6588         MonoCustomAttrInfo *cinfo;
6589         guint32 idx;
6590         
6591         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6592                 return cinfo;
6593         idx = find_field_index (klass, field);
6594         idx <<= MONO_CUSTOM_ATTR_BITS;
6595         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6596         return mono_custom_attrs_from_index (klass->image, idx);
6597 }
6598
6599 MonoCustomAttrInfo*
6600 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6601 {
6602         MonoTableInfo *ca;
6603         guint32 i, idx, method_index;
6604         guint32 param_list, param_last, param_pos, found;
6605         MonoImage *image;
6606         MonoReflectionMethodAux *aux;
6607
6608         if (method->klass->image->dynamic) {
6609                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6610                 if (!aux || !aux->param_cattr)
6611                         return NULL;
6612                 return aux->param_cattr [param];
6613         }
6614
6615         image = method->klass->image;
6616         method_index = find_method_index (method);
6617         ca = &image->tables [MONO_TABLE_METHOD];
6618
6619         if (method->klass->generic_inst || method->klass->gen_params ||
6620                         method->signature->generic_param_count) {
6621                 /* FIXME FIXME FIXME */
6622                 return NULL;
6623         }
6624
6625         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6626         if (method_index == ca->rows) {
6627                 ca = &image->tables [MONO_TABLE_PARAM];
6628                 param_last = ca->rows + 1;
6629         } else {
6630                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6631                 ca = &image->tables [MONO_TABLE_PARAM];
6632         }
6633         found = FALSE;
6634         for (i = param_list; i < param_last; ++i) {
6635                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6636                 if (param_pos == param) {
6637                         found = TRUE;
6638                         break;
6639                 }
6640         }
6641         if (!found)
6642                 return NULL;
6643         idx = i;
6644         idx <<= MONO_CUSTOM_ATTR_BITS;
6645         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6646         return mono_custom_attrs_from_index (image, idx);
6647 }
6648
6649 /*
6650  * mono_reflection_get_custom_attrs:
6651  * @obj: a reflection object handle
6652  *
6653  * Return an array with all the custom attributes defined of the
6654  * reflection handle @obj. The objects are fully build.
6655  */
6656 MonoArray*
6657 mono_reflection_get_custom_attrs (MonoObject *obj)
6658 {
6659         MonoClass *klass;
6660         MonoArray *result;
6661         MonoCustomAttrInfo *cinfo = NULL;
6662         
6663         MONO_ARCH_SAVE_REGS;
6664
6665         klass = obj->vtable->klass;
6666         if (klass == mono_defaults.monotype_class) {
6667                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6668                 klass = mono_class_from_mono_type (rtype->type);
6669                 cinfo = mono_custom_attrs_from_class (klass);
6670         } else if (strcmp ("Assembly", klass->name) == 0) {
6671                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6672                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6673         } else if (strcmp ("Module", klass->name) == 0) {
6674                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6675                 cinfo = mono_custom_attrs_from_module (module->image);
6676         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6677                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6678                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6679         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6680                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6681                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6682         } else if (strcmp ("MonoField", klass->name) == 0) {
6683                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6684                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6685         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6686                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6687                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6688         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6689                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6690                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6691                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6692         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6693                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6694                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6695         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6696                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6697                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6698         } else { /* handle other types here... */
6699                 g_error ("get custom attrs not yet supported for %s", klass->name);
6700         }
6701
6702         if (cinfo) {
6703                 result = mono_custom_attrs_construct (cinfo);
6704                 if (!cinfo->cached)
6705                         mono_custom_attrs_free (cinfo);
6706         } else {
6707                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6708                 result = mono_array_new (mono_domain_get (), klass, 0);
6709         }
6710
6711         return result;
6712 }
6713
6714 static MonoMethodSignature*
6715 parameters_to_signature (MonoArray *parameters) {
6716         MonoMethodSignature *sig;
6717         int count, i;
6718
6719         count = parameters? mono_array_length (parameters): 0;
6720
6721         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6722         sig->param_count = count;
6723         sig->sentinelpos = -1; /* FIXME */
6724         for (i = 0; i < count; ++i) {
6725                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6726                 sig->params [i] = pt->type;
6727         }
6728         return sig;
6729 }
6730
6731 static MonoMethodSignature*
6732 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6733         MonoMethodSignature *sig;
6734
6735         sig = parameters_to_signature (ctor->parameters);
6736         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6737         sig->ret = &mono_defaults.void_class->byval_arg;
6738         return sig;
6739 }
6740
6741 static MonoMethodSignature*
6742 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6743         MonoMethodSignature *sig;
6744
6745         sig = parameters_to_signature (method->parameters);
6746         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6747         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6748         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6749         return sig;
6750 }
6751
6752 static MonoMethodSignature*
6753 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6754         MonoMethodSignature *sig;
6755
6756         sig = parameters_to_signature (method->parameters);
6757         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6758         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6759         sig->generic_param_count = 0;
6760         return sig;
6761 }
6762
6763 static void
6764 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6765 {
6766         MonoClass *klass = mono_object_class (prop);
6767         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6768                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6769                 *name = mono_string_to_utf8 (pb->name);
6770                 *type = pb->type->type;
6771         } else {
6772                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6773                 *name = g_strdup (p->property->name);
6774                 if (p->property->get)
6775                         *type = p->property->get->signature->ret;
6776                 else
6777                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6778         }
6779 }
6780
6781 static void
6782 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6783 {
6784         MonoClass *klass = mono_object_class (field);
6785         if (strcmp (klass->name, "FieldBuilder") == 0) {
6786                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6787                 *name = mono_string_to_utf8 (fb->name);
6788                 *type = fb->type->type;
6789         } else {
6790                 MonoReflectionField *f = (MonoReflectionField *)field;
6791                 *name = g_strdup (f->field->name);
6792                 *type = f->field->type;
6793         }
6794 }
6795
6796 /*
6797  * Encode a value in a custom attribute stream of bytes.
6798  * The value to encode is either supplied as an object in argument val
6799  * (valuetypes are boxed), or as a pointer to the data in the
6800  * argument argval.
6801  * @type represents the type of the value
6802  * @buffer is the start of the buffer
6803  * @p the current position in the buffer
6804  * @buflen contains the size of the buffer and is used to return the new buffer size
6805  * if this needs to be realloced.
6806  * @retbuffer and @retp return the start and the position of the buffer
6807  */
6808 static void
6809 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6810 {
6811         MonoTypeEnum simple_type;
6812         
6813         if ((p-buffer) + 10 >= *buflen) {
6814                 char *newbuf;
6815                 *buflen *= 2;
6816                 newbuf = g_realloc (buffer, *buflen);
6817                 p = newbuf + (p-buffer);
6818                 buffer = newbuf;
6819         }
6820         if (!argval)
6821                 argval = ((char*)arg + sizeof (MonoObject));
6822         simple_type = type->type;
6823 handle_enum:
6824         switch (simple_type) {
6825         case MONO_TYPE_BOOLEAN:
6826         case MONO_TYPE_U1:
6827         case MONO_TYPE_I1:
6828                 *p++ = *argval;
6829                 break;
6830         case MONO_TYPE_CHAR:
6831         case MONO_TYPE_U2:
6832         case MONO_TYPE_I2:
6833                 swap_with_size (p, argval, 2, 1);
6834                 p += 2;
6835                 break;
6836         case MONO_TYPE_U4:
6837         case MONO_TYPE_I4:
6838         case MONO_TYPE_R4:
6839                 swap_with_size (p, argval, 4, 1);
6840                 p += 4;
6841                 break;
6842         case MONO_TYPE_U8:
6843         case MONO_TYPE_I8:
6844         case MONO_TYPE_R8:
6845                 swap_with_size (p, argval, 8, 1);
6846                 p += 8;
6847                 break;
6848         case MONO_TYPE_VALUETYPE:
6849                 if (type->data.klass->enumtype) {
6850                         simple_type = type->data.klass->enum_basetype->type;
6851                         goto handle_enum;
6852                 } else {
6853                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6854                 }
6855                 break;
6856         case MONO_TYPE_STRING: {
6857                 char *str;
6858                 guint32 slen;
6859                 if (!arg) {
6860                         *p++ = 0xFF;
6861                         break;
6862                 }
6863                 str = mono_string_to_utf8 ((MonoString*)arg);
6864                 slen = strlen (str);
6865                 if ((p-buffer) + 10 + slen >= *buflen) {
6866                         char *newbuf;
6867                         *buflen *= 2;
6868                         *buflen += slen;
6869                         newbuf = g_realloc (buffer, *buflen);
6870                         p = newbuf + (p-buffer);
6871                         buffer = newbuf;
6872                 }
6873                 mono_metadata_encode_value (slen, p, &p);
6874                 memcpy (p, str, slen);
6875                 p += slen;
6876                 g_free (str);
6877                 break;
6878         }
6879         case MONO_TYPE_CLASS: {
6880                 char *str;
6881                 guint32 slen;
6882                 MonoClass *k;
6883                 if (!arg) {
6884                         *p++ = 0xFF;
6885                         break;
6886                 }
6887                 k = mono_object_class (arg);
6888                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6889                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6890                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6891 handle_type:
6892                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6893                 slen = strlen (str);
6894                 if ((p-buffer) + 10 + slen >= *buflen) {
6895                         char *newbuf;
6896                         *buflen *= 2;
6897                         *buflen += slen;
6898                         newbuf = g_realloc (buffer, *buflen);
6899                         p = newbuf + (p-buffer);
6900                         buffer = newbuf;
6901                 }
6902                 mono_metadata_encode_value (slen, p, &p);
6903                 memcpy (p, str, slen);
6904                 p += slen;
6905                 g_free (str);
6906                 break;
6907         }
6908         case MONO_TYPE_SZARRAY: {
6909                 int len, i;
6910                 MonoClass *eclass, *arg_eclass;
6911
6912                 if (!arg) {
6913                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6914                         break;
6915                 }
6916                 len = mono_array_length ((MonoArray*)arg);
6917                 *p++ = len & 0xff;
6918                 *p++ = (len >> 8) & 0xff;
6919                 *p++ = (len >> 16) & 0xff;
6920                 *p++ = (len >> 24) & 0xff;
6921                 *retp = p;
6922                 *retbuffer = buffer;
6923                 eclass = type->data.klass;
6924                 arg_eclass = mono_object_class (arg)->element_class;
6925                 if (eclass->valuetype && arg_eclass->valuetype) {
6926                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6927                         int elsize = mono_class_array_element_size (eclass);
6928                         for (i = 0; i < len; ++i) {
6929                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6930                                 elptr += elsize;
6931                         }
6932                 } else {
6933                         for (i = 0; i < len; ++i) {
6934                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6935                         }
6936                 }
6937                 break;
6938         }
6939         /* it may be a boxed value or a Type */
6940         case MONO_TYPE_OBJECT: {
6941                 MonoClass *klass = mono_object_class (arg);
6942                 char *str;
6943                 guint32 slen;
6944                 
6945                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6946                         *p++ = 0x50;
6947                         goto handle_type;
6948                 } else if (klass->enumtype) {
6949                         *p++ = 0x55;
6950                 } else if (klass == mono_defaults.string_class) {
6951                         simple_type = MONO_TYPE_STRING;
6952                         *p++ = 0x0E;
6953                         goto handle_enum;
6954                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6955                         *p++ = simple_type = klass->byval_arg.type;
6956                         goto handle_enum;
6957                 } else {
6958                         g_error ("unhandled type in custom attr");
6959                 }
6960                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6961                 slen = strlen (str);
6962                 if ((p-buffer) + 10 + slen >= *buflen) {
6963                         char *newbuf;
6964                         *buflen *= 2;
6965                         *buflen += slen;
6966                         newbuf = g_realloc (buffer, *buflen);
6967                         p = newbuf + (p-buffer);
6968                         buffer = newbuf;
6969                 }
6970                 mono_metadata_encode_value (slen, p, &p);
6971                 memcpy (p, str, slen);
6972                 p += slen;
6973                 g_free (str);
6974                 simple_type = klass->enum_basetype->type;
6975                 goto handle_enum;
6976         }
6977         default:
6978                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6979         }
6980         *retp = p;
6981         *retbuffer = buffer;
6982 }
6983
6984 /*
6985  * mono_reflection_get_custom_attrs_blob:
6986  * @ctor: custom attribute constructor
6987  * @ctorArgs: arguments o the constructor
6988  * @properties:
6989  * @propValues:
6990  * @fields:
6991  * @fieldValues:
6992  * 
6993  * Creates the blob of data that needs to be saved in the metadata and that represents
6994  * the custom attributed described by @ctor, @ctorArgs etc.
6995  * Returns: a Byte array representing the blob of data.
6996  */
6997 MonoArray*
6998 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6999 {
7000         MonoArray *result;
7001         MonoMethodSignature *sig;
7002         MonoObject *arg;
7003         char *buffer, *p;
7004         guint32 buflen, i;
7005
7006         MONO_ARCH_SAVE_REGS;
7007
7008         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7009                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7010         } else {
7011                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7012         }
7013         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7014         buflen = 256;
7015         p = buffer = g_malloc (buflen);
7016         /* write the prolog */
7017         *p++ = 1;
7018         *p++ = 0;
7019         for (i = 0; i < sig->param_count; ++i) {
7020                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7021                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7022         }
7023         i = 0;
7024         if (properties)
7025                 i += mono_array_length (properties);
7026         if (fields)
7027                 i += mono_array_length (fields);
7028         *p++ = i & 0xff;
7029         *p++ = (i >> 8) & 0xff;
7030         if (properties) {
7031                 MonoObject *prop;
7032                 for (i = 0; i < mono_array_length (properties); ++i) {
7033                         MonoType *ptype;
7034                         char *pname;
7035                         int len;
7036                         
7037                         prop = mono_array_get (properties, gpointer, i);
7038                         get_prop_name_and_type (prop, &pname, &ptype);
7039                         *p++ = 0x54; /* PROPERTY signature */
7040
7041                         /* Preallocate a large enough buffer */
7042                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7043                                 char *str = type_get_qualified_name (ptype, NULL);
7044                                 len = strlen (str);
7045                                 g_free (str);
7046                         }
7047                         else
7048                                 len = 0;
7049                         len += strlen (pname);
7050
7051                         if ((p-buffer) + 20 + len >= buflen) {
7052                                 char *newbuf;
7053                                 buflen *= 2;
7054                                 buflen += len;
7055                                 newbuf = g_realloc (buffer, buflen);
7056                                 p = newbuf + (p-buffer);
7057                                 buffer = newbuf;
7058                         }
7059
7060                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7061                                 char *str = type_get_qualified_name (ptype, NULL);
7062                                 int slen = strlen (str);
7063
7064                                 *p++ = 0x55;
7065                                 /*
7066                                  * This seems to be optional...
7067                                  * *p++ = 0x80;
7068                                  */
7069                                 mono_metadata_encode_value (slen, p, &p);
7070                                 memcpy (p, str, slen);
7071                                 p += slen;
7072                                 g_free (str);
7073                         } else {
7074                                 mono_metadata_encode_value (ptype->type, p, &p);
7075                                 if (ptype->type == MONO_TYPE_SZARRAY)
7076                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7077                         }
7078                         len = strlen (pname);
7079                         mono_metadata_encode_value (len, p, &p);
7080                         memcpy (p, pname, len);
7081                         p += len;
7082                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7083                         g_free (pname);
7084                 }
7085         }
7086
7087         if (fields) {
7088                 MonoObject *field;
7089                 for (i = 0; i < mono_array_length (fields); ++i) {
7090                         MonoType *ftype;
7091                         char *fname;
7092                         int len;
7093                         
7094                         field = mono_array_get (fields, gpointer, i);
7095                         get_field_name_and_type (field, &fname, &ftype);
7096                         *p++ = 0x53; /* FIELD signature */
7097                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7098                                 char *str = type_get_qualified_name (ftype, NULL);
7099                                 int slen = strlen (str);
7100                                 if ((p-buffer) + 10 + slen >= buflen) {
7101                                         char *newbuf;
7102                                         buflen *= 2;
7103                                         buflen += slen;
7104                                         newbuf = g_realloc (buffer, buflen);
7105                                         p = newbuf + (p-buffer);
7106                                         buffer = newbuf;
7107                                 }
7108                                 *p++ = 0x55;
7109                                 /*
7110                                  * This seems to be optional...
7111                                  * *p++ = 0x80;
7112                                  */
7113                                 mono_metadata_encode_value (slen, p, &p);
7114                                 memcpy (p, str, slen);
7115                                 p += slen;
7116                                 g_free (str);
7117                         } else {
7118                                 mono_metadata_encode_value (ftype->type, p, &p);
7119                                 if (ftype->type == MONO_TYPE_SZARRAY)
7120                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7121                         }
7122                         len = strlen (fname);
7123                         mono_metadata_encode_value (len, p, &p);
7124                         memcpy (p, fname, len);
7125                         p += len;
7126                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7127                         g_free (fname);
7128                 }
7129         }
7130
7131         g_assert (p - buffer <= buflen);
7132         buflen = p - buffer;
7133         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7134         p = mono_array_addr (result, char, 0);
7135         memcpy (p, buffer, buflen);
7136         g_free (buffer);
7137         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7138                 g_free (sig);
7139         return result;
7140 }
7141
7142 /*
7143  * mono_reflection_setup_internal_class:
7144  * @tb: a TypeBuilder object
7145  *
7146  * Creates a MonoClass that represents the TypeBuilder.
7147  * This is a trick that lets us simplify a lot of reflection code
7148  * (and will allow us to support Build and Run assemblies easier).
7149  */
7150 void
7151 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7152 {
7153         MonoClass *klass, *parent;
7154
7155         MONO_ARCH_SAVE_REGS;
7156
7157         if (tb->parent) {
7158                 /* check so we can compile corlib correctly */
7159                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7160                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7161                         parent = tb->parent->type->data.klass;
7162                 } else {
7163                         parent = my_mono_class_from_mono_type (tb->parent->type);
7164                 }
7165         } else {
7166                 parent = NULL;
7167         }
7168         
7169         /* the type has already being created: it means we just have to change the parent */
7170         if (tb->type.type) {
7171                 klass = mono_class_from_mono_type (tb->type.type);
7172                 klass->parent = NULL;
7173                 /* fool mono_class_setup_parent */
7174                 g_free (klass->supertypes);
7175                 klass->supertypes = NULL;
7176                 mono_class_setup_parent (klass, parent);
7177                 mono_class_setup_mono_type (klass);
7178                 return;
7179         }
7180         
7181         klass = g_new0 (MonoClass, 1);
7182
7183         klass->image = &tb->module->dynamic_image->image;
7184
7185         klass->inited = 1; /* we lie to the runtime */
7186         klass->name = mono_string_to_utf8 (tb->name);
7187         klass->name_space = mono_string_to_utf8 (tb->nspace);
7188         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7189         klass->flags = tb->attrs;
7190
7191         klass->element_class = klass;
7192         klass->reflection_info = tb; /* need to pin. */
7193
7194         /* Put into cache so mono_class_get () will find it */
7195         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7196
7197         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7198                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7199
7200         if (parent != NULL) {
7201                 mono_class_setup_parent (klass, parent);
7202         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7203                 const char *old_n = klass->name;
7204                 /* trick to get relative numbering right when compiling corlib */
7205                 klass->name = "BuildingObject";
7206                 mono_class_setup_parent (klass, mono_defaults.object_class);
7207                 klass->name = old_n;
7208         }
7209
7210         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7211                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7212                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7213                 klass->instance_size = sizeof (MonoObject);
7214                 klass->size_inited = 1;
7215                 mono_class_setup_vtable (klass, NULL, 0);
7216         }
7217
7218         mono_class_setup_mono_type (klass);
7219
7220         mono_class_setup_supertypes (klass);
7221
7222         /*
7223          * FIXME: handle interfaces.
7224          */
7225
7226         tb->type.type = &klass->byval_arg;
7227
7228         if (tb->nesting_type) {
7229                 g_assert (tb->nesting_type->type);
7230                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7231         }
7232
7233         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7234 }
7235
7236 /*
7237  * mono_reflection_setup_generic_class:
7238  * @tb: a TypeBuilder object
7239  *
7240  * Setup the generic class after all generic parameters have been added.
7241  */
7242 void
7243 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7244 {
7245         MonoClass *klass;
7246         int count, i;
7247
7248         MONO_ARCH_SAVE_REGS;
7249
7250         klass = my_mono_class_from_mono_type (tb->type.type);
7251
7252         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7253
7254         if (klass->gen_params || (count == 0))
7255                 return;
7256
7257         klass->num_gen_params = count;
7258         klass->gen_params = g_new0 (MonoGenericParam, count);
7259
7260         for (i = 0; i < count; i++) {
7261                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7262                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7263         }
7264 }
7265
7266 /*
7267  * mono_reflection_create_internal_class:
7268  * @tb: a TypeBuilder object
7269  *
7270  * Actually create the MonoClass that is associated with the TypeBuilder.
7271  */
7272 void
7273 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7274 {
7275         MonoClass *klass;
7276
7277         MONO_ARCH_SAVE_REGS;
7278
7279         klass = my_mono_class_from_mono_type (tb->type.type);
7280
7281         if (klass->enumtype && klass->enum_basetype == NULL) {
7282                 MonoReflectionFieldBuilder *fb;
7283                 MonoClass *ec;
7284
7285                 g_assert (tb->fields != NULL);
7286                 g_assert (mono_array_length (tb->fields) >= 1);
7287
7288                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7289
7290                 klass->enum_basetype = fb->type->type;
7291                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7292                 if (!klass->element_class)
7293                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7294
7295                 /*
7296                  * get the element_class from the current corlib.
7297                  */
7298                 ec = default_class_from_mono_type (klass->enum_basetype);
7299                 klass->instance_size = ec->instance_size;
7300                 klass->size_inited = 1;
7301                 /* 
7302                  * this is almost safe to do with enums and it's needed to be able
7303                  * to create objects of the enum type (for use in SetConstant).
7304                  */
7305                 /* FIXME: Does this mean enums can't have method overrides ? */
7306                 mono_class_setup_vtable (klass, NULL, 0);
7307         }
7308 }
7309
7310 static MonoMarshalSpec*
7311 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7312                                                                 MonoReflectionMarshal *minfo)
7313 {
7314         MonoMarshalSpec *res;
7315
7316         res = g_new0 (MonoMarshalSpec, 1);
7317         res->native = minfo->type;
7318
7319         switch (minfo->type) {
7320         case MONO_NATIVE_LPARRAY:
7321                 res->data.array_data.elem_type = minfo->eltype;
7322                 res->data.array_data.param_num = 0; /* Not yet */
7323                 res->data.array_data.num_elem = minfo->count;
7324                 break;
7325
7326         case MONO_NATIVE_BYVALTSTR:
7327         case MONO_NATIVE_BYVALARRAY:
7328                 res->data.array_data.num_elem = minfo->count;
7329                 break;
7330
7331         case MONO_NATIVE_CUSTOM:
7332                 if (minfo->marshaltyperef)
7333                         res->data.custom_data.custom_name =
7334                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7335                 if (minfo->mcookie)
7336                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7337                 break;
7338
7339         default:
7340                 break;
7341         }
7342
7343         return res;
7344 }
7345
7346 MonoReflectionMarshal*
7347 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7348                                                                                    MonoMarshalSpec *spec)
7349 {
7350         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7351         MonoReflectionMarshal *minfo;
7352         MonoType *mtype;
7353
7354         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7355                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7356                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7357                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7358         }
7359
7360         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7361         minfo->type = spec->native;
7362
7363         switch (minfo->type) {
7364         case MONO_NATIVE_LPARRAY:
7365                 minfo->eltype = spec->data.array_data.elem_type;
7366                 minfo->count = spec->data.array_data.num_elem;
7367                 break;
7368
7369         case MONO_NATIVE_BYVALTSTR:
7370         case MONO_NATIVE_BYVALARRAY:
7371                 minfo->count = spec->data.array_data.num_elem;
7372                 break;
7373
7374         case MONO_NATIVE_CUSTOM:
7375                 if (spec->data.custom_data.custom_name) {
7376                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7377                         if (mtype)
7378                                 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7379
7380                         minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7381                 }
7382                 if (spec->data.custom_data.cookie)
7383                         minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7384                 break;
7385
7386         default:
7387                 break;
7388         }
7389
7390         return minfo;
7391 }
7392
7393 static MonoMethod*
7394 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7395                                          ReflectionMethodBuilder *rmb,
7396                                          MonoMethodSignature *sig)
7397 {
7398         MonoMethod *m;
7399         MonoMethodNormal *pm;
7400         MonoMarshalSpec **specs;
7401         MonoReflectionMethodAux *method_aux;
7402         int i;
7403
7404         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7405                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7406                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7407         else if (rmb->refs)
7408                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7409         else
7410                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7411
7412         pm = (MonoMethodNormal*)m;
7413
7414         m->slot = -1;
7415         m->flags = rmb->attrs;
7416         m->iflags = rmb->iattrs;
7417         m->name = mono_string_to_utf8 (rmb->name);
7418         m->klass = klass;
7419         m->signature = sig;
7420         if (rmb->table_idx)
7421                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7422
7423         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7424                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7425                         m->string_ctor = 1;
7426
7427                 m->signature->pinvoke = 1;
7428         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7429                 m->signature->pinvoke = 1;
7430
7431                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7432
7433                 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7434                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7435                 
7436                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7437
7438                 if (klass->image->dynamic)
7439                         mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7440
7441                 return m;
7442         } else if (!m->klass->dummy && 
7443                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7444                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7445                 MonoMethodHeader *header;
7446                 guint32 code_size;
7447                 gint32 max_stack, i;
7448                 gint32 num_locals = 0;
7449                 gint32 num_clauses = 0;
7450                 guint8 *code;
7451
7452                 if (rmb->ilgen) {
7453                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7454                         code_size = rmb->ilgen->code_len;
7455                         max_stack = rmb->ilgen->max_stack;
7456                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7457                         if (rmb->ilgen->ex_handlers)
7458                                 num_clauses = method_count_clauses (rmb->ilgen);
7459                 } else {
7460                         if (rmb->code) {
7461                                 code = mono_array_addr (rmb->code, guint8, 0);
7462                                 code_size = mono_array_length (rmb->code);
7463                                 /* we probably need to run a verifier on the code... */
7464                                 max_stack = 8; 
7465                         }
7466                         else {
7467                                 code = NULL;
7468                                 code_size = 0;
7469                                 max_stack = 8;
7470                         }
7471                 }
7472
7473                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7474                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7475                 header->code_size = code_size;
7476                 header->code = g_malloc (code_size);
7477                 memcpy ((char*)header->code, code, code_size);
7478                 header->max_stack = max_stack;
7479                 header->init_locals = rmb->init_locals;
7480                 header->num_locals = num_locals;
7481
7482                 for (i = 0; i < num_locals; ++i) {
7483                         MonoReflectionLocalBuilder *lb = 
7484                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7485
7486                         header->locals [i] = g_new0 (MonoType, 1);
7487                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7488                 }
7489
7490                 header->num_clauses = num_clauses;
7491                 if (num_clauses) {
7492                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7493                                  rmb->ilgen, num_clauses);
7494                 }
7495
7496                 pm->header = header;
7497         }
7498
7499         if (rmb->generic_params) {
7500                 int count = mono_array_length (rmb->generic_params);
7501                 pm->gen_params = g_new0 (MonoGenericParam, count);
7502                 for (i = 0; i < count; i++) {
7503                         MonoReflectionGenericParam *gp =
7504                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7505
7506                         pm->gen_params [i] = *gp->type.type->data.generic_param;
7507                 }
7508         }
7509
7510         if (rmb->refs) {
7511                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7512                 int i;
7513
7514                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7515
7516                 for (i = 0; i < rmb->nrefs; ++i)
7517                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7518         }
7519
7520         method_aux = NULL;
7521
7522         /* Parameter names */
7523         if (rmb->pinfo) {
7524                 if (!method_aux)
7525                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7526                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7527                 for (i = 0; i <= m->signature->param_count; ++i) {
7528                         MonoReflectionParamBuilder *pb;
7529                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7530                                 if (pb->name)
7531                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7532                                 if (pb->cattrs) {
7533                                         if (!method_aux->param_cattr)
7534                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7535                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7536                                 }
7537                         }
7538                 }
7539         }
7540
7541         /* Parameter marshalling */
7542         specs = NULL;
7543         if (rmb->pinfo)         
7544                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7545                         MonoReflectionParamBuilder *pb;
7546                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7547                                 if (pb->marshal_info) {
7548                                         if (specs == NULL)
7549                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7550                                         specs [pb->position] = 
7551                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7552                                 }
7553                         }
7554                 }
7555         if (specs != NULL) {
7556                 if (!method_aux)
7557                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7558                 method_aux->param_marshall = specs;
7559         }
7560
7561         if (klass->image->dynamic && method_aux)
7562                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7563
7564         return m;
7565 }       
7566
7567 static MonoMethod*
7568 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7569 {
7570         ReflectionMethodBuilder rmb;
7571         MonoMethodSignature *sig;
7572
7573         sig = ctor_builder_to_signature (mb);
7574
7575         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7576
7577         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7578         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7579
7580         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7581                 /* ilgen is no longer needed */
7582                 mb->ilgen = NULL;
7583         }
7584
7585         return mb->mhandle;
7586 }
7587
7588 static MonoMethod*
7589 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7590 {
7591         ReflectionMethodBuilder rmb;
7592         MonoMethodSignature *sig;
7593
7594         sig = method_builder_to_signature (mb);
7595
7596         reflection_methodbuilder_from_method_builder (&rmb, mb);
7597
7598         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7599         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7600
7601         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7602                 /* ilgen is no longer needed */
7603                 mb->ilgen = NULL;
7604         }
7605         return mb->mhandle;
7606 }
7607
7608 static MonoClassField*
7609 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7610 {
7611         MonoClassField *field;
7612         const char *p, *p2;
7613         guint32 len, idx;
7614
7615         if (fb->handle)
7616                 return fb->handle;
7617
7618         field = g_new0 (MonoClassField, 1);
7619
7620         field->name = mono_string_to_utf8 (fb->name);
7621         if (fb->attrs) {
7622                 /* FIXME: handle type modifiers */
7623                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7624                 field->type->attrs = fb->attrs;
7625         } else {
7626                 field->type = fb->type->type;
7627         }
7628         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7629                 field->data = mono_array_addr (fb->rva_data, char, 0);
7630         if (fb->offset != -1)
7631                 field->offset = fb->offset;
7632         field->parent = klass;
7633         fb->handle = field;
7634         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7635
7636         if (fb->def_value) {
7637                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7638                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7639                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7640                 /* Copy the data from the blob since it might get realloc-ed */
7641                 p = assembly->blob.data + idx;
7642                 len = mono_metadata_decode_blob_size (p, &p2);
7643                 len += p2 - p;
7644                 field->data = g_malloc (len);
7645                 memcpy ((gpointer)field->data, p, len);
7646         }
7647
7648         return field;
7649 }
7650
7651 static MonoType*
7652 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7653 {
7654         MonoClass *klass;
7655         MonoReflectionTypeBuilder *tb = NULL;
7656         MonoGenericInst *ginst, *cached;
7657         MonoDomain *domain;
7658         MonoType *geninst;
7659         int icount, i;
7660
7661         klass = mono_class_from_mono_type (type->type);
7662         if (!klass->gen_params && !klass->generic_inst &&
7663                         !(klass->nested_in && klass->nested_in->gen_params))
7664                 return NULL;
7665
7666         mono_loader_lock ();
7667
7668         domain = mono_object_domain (type);
7669
7670         ginst = g_new0 (MonoGenericInst, 1);
7671
7672         if (!klass->generic_inst) {
7673                 ginst->type_argc = type_argc;
7674                 ginst->type_argv = types;
7675
7676                 for (i = 0; i < ginst->type_argc; ++i) {
7677                         if (!ginst->is_open)
7678                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7679                 }
7680
7681                 ginst->generic_type = &klass->byval_arg;
7682         } else {
7683                 MonoGenericInst *kginst = klass->generic_inst;
7684
7685                 ginst->type_argc = kginst->type_argc;
7686                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7687
7688                 for (i = 0; i < ginst->type_argc; i++) {
7689                         MonoType *t = kginst->type_argv [i];
7690
7691                         if (t->type == MONO_TYPE_VAR)
7692                                 t = types [t->data.generic_param->num];
7693
7694                         if (!ginst->is_open)
7695                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7696
7697                         ginst->type_argv [i] = t;
7698                 }
7699
7700                 ginst->generic_type = kginst->generic_type;
7701         }
7702
7703         geninst = g_new0 (MonoType, 1);
7704         geninst->type = MONO_TYPE_GENERICINST;
7705
7706         cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7707         if (cached) {
7708                 g_free (ginst);
7709                 mono_loader_unlock ();
7710                 geninst->data.generic_inst = cached;
7711                 return geninst;
7712         }
7713
7714         geninst->data.generic_inst = ginst;
7715
7716         ginst->context = g_new0 (MonoGenericContext, 1);
7717         ginst->context->ginst = ginst;
7718
7719         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7720                 tb = (MonoReflectionTypeBuilder *) type;
7721
7722                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7723                 ginst->is_dynamic = TRUE;
7724         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7725                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7726                 MonoReflectionType *rgt = rgi->generic_type;
7727
7728                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7729                 tb = (MonoReflectionTypeBuilder *) rgt;
7730
7731                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7732                 ginst->is_dynamic = TRUE;
7733         } else {
7734                 icount = klass->interface_count;
7735         }
7736
7737         ginst->ifaces = g_new0 (MonoType *, icount);
7738         ginst->count_ifaces = icount;
7739
7740         for (i = 0; i < icount; i++) {
7741                 MonoReflectionType *itype;
7742
7743                 if (tb)
7744                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7745                 else
7746                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7747                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7748                 if (!ginst->ifaces [i])
7749                         ginst->ifaces [i] = itype->type;
7750         }
7751
7752         mono_class_create_generic (ginst);
7753
7754         g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7755
7756         mono_loader_unlock ();
7757
7758         return geninst;
7759 }
7760
7761 MonoType*
7762 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7763 {
7764         MonoClass *klass, *pklass = NULL;
7765         MonoReflectionType *parent = NULL;
7766         MonoType *geninst;
7767         MonoReflectionTypeBuilder *tb = NULL;
7768         MonoGenericInst *ginst;
7769         MonoDomain *domain;
7770
7771         domain = mono_object_domain (type);
7772         klass = mono_class_from_mono_type (type->type);
7773
7774         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7775                 tb = (MonoReflectionTypeBuilder *) type;
7776
7777                 if (tb->parent) {
7778                         parent = tb->parent;
7779                         pklass = mono_class_from_mono_type (parent->type);
7780                 }
7781         } else {
7782                 pklass = klass->parent;
7783                 if (pklass)
7784                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7785         }
7786
7787         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7788         if (!geninst)
7789                 return NULL;
7790
7791         ginst = geninst->data.generic_inst;
7792
7793         if (pklass && pklass->generic_inst)
7794                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7795
7796         return geninst;
7797 }
7798
7799 MonoReflectionMethod*
7800 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7801 {
7802         MonoMethod *method, *inflated;
7803         MonoReflectionMethodBuilder *mb = NULL;
7804         MonoGenericMethod *gmethod;
7805         MonoGenericContext *context;
7806         int count, i;
7807
7808         MONO_ARCH_SAVE_REGS;
7809         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7810                 MonoReflectionTypeBuilder *tb;
7811                 MonoClass *klass;
7812
7813                 mb = (MonoReflectionMethodBuilder *) rmethod;
7814                 tb = (MonoReflectionTypeBuilder *) mb->type;
7815                 klass = mono_class_from_mono_type (tb->type.type);
7816
7817                 method = methodbuilder_to_mono_method (klass, mb);
7818         } else {
7819                 method = rmethod->method;
7820         }
7821
7822         count = method->signature->generic_param_count;
7823         if (count != mono_array_length (types))
7824                 return NULL;
7825
7826         gmethod = g_new0 (MonoGenericMethod, 1);
7827         gmethod->mtype_argc = count;
7828         gmethod->mtype_argv = g_new0 (MonoType *, count);
7829         for (i = 0; i < count; i++) {
7830                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7831                 gmethod->mtype_argv [i] = garg->type;
7832         }
7833
7834         gmethod->reflection_info = rmethod;
7835
7836         context = g_new0 (MonoGenericContext, 1);
7837         context->ginst = method->klass->generic_inst;
7838         context->gmethod = gmethod;
7839
7840         inflated = mono_class_inflate_generic_method (method, context, NULL);
7841
7842         return mono_method_get_object (
7843                 mono_object_domain (rmethod), inflated, NULL);
7844 }
7845
7846 static MonoMethod *
7847 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7848 {
7849         MonoGenericMethod *gmethod;
7850         MonoGenericInst *ginst;
7851         MonoGenericContext *context;
7852         int i;
7853
7854         ginst = type->type.type->data.generic_inst;
7855
7856         gmethod = g_new0 (MonoGenericMethod, 1);
7857         gmethod->reflection_info = obj;
7858
7859         gmethod->mtype_argc = method->signature->generic_param_count;
7860         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7861
7862         for (i = 0; i < gmethod->mtype_argc; i++) {
7863                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7864                 MonoGenericParam *gparam = &mn->gen_params [i];
7865
7866                 g_assert (gparam->pklass);
7867                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7868         }
7869
7870         context = g_new0 (MonoGenericContext, 1);
7871         context->ginst = ginst;
7872         context->gmethod = gmethod;
7873
7874         return mono_class_inflate_generic_method (method, context, ginst->klass);
7875 }
7876
7877 static MonoMethod *
7878 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7879 {
7880         MonoMethod *method;
7881         MonoClass *klass;
7882
7883         klass = mono_class_from_mono_type (type->type.type);
7884
7885         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7886                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7887         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7888                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7889         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7890                 method = ((MonoReflectionMethod *) obj)->method;
7891         else {
7892                 method = NULL; /* prevent compiler warning */
7893                 g_assert_not_reached ();
7894         }
7895
7896         return inflate_mono_method (type, method, obj);
7897 }
7898
7899 void
7900 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods, 
7901         MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
7902 {
7903         MonoGenericInst *ginst;
7904         MonoDynamicGenericInst *dginst;
7905         MonoClass *klass, *gklass, *pklass;
7906         int i;
7907
7908         MONO_ARCH_SAVE_REGS;
7909
7910         klass = mono_class_from_mono_type (type->type.type);
7911         ginst = type->type.type->data.generic_inst;
7912
7913         if (ginst->initialized)
7914                 return;
7915
7916         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7917
7918         gklass = mono_class_from_mono_type (ginst->generic_type);
7919         mono_class_init (gklass);
7920
7921         if (ginst->parent)
7922                 pklass = mono_class_from_mono_type (ginst->parent);
7923         else
7924                 pklass = gklass->parent;
7925
7926         mono_class_setup_parent (klass, pklass);
7927
7928         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7929         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7930         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7931         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7932         dginst->count_events = events ? mono_array_length (events) : 0;
7933
7934         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7935         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7936         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7937         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7938         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7939
7940         for (i = 0; i < dginst->count_methods; i++) {
7941                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7942
7943                 dginst->methods [i] = inflate_method (type, obj);
7944         }
7945
7946         for (i = 0; i < dginst->count_ctors; i++) {
7947                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7948
7949                 dginst->ctors [i] = inflate_method (type, obj);
7950         }
7951
7952         for (i = 0; i < dginst->count_fields; i++) {
7953                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7954                 MonoClassField *field;
7955                 MonoInflatedField *ifield;
7956
7957                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7958                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7959                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7960                         field = ((MonoReflectionField *) obj)->field;
7961                 else {
7962                         field = NULL; /* prevent compiler warning */
7963                         g_assert_not_reached ();
7964                 }
7965
7966                 ifield = g_new0 (MonoInflatedField, 1);
7967                 ifield->generic_type = field->type;
7968                 ifield->reflection_info = obj;
7969
7970                 dginst->fields [i] = *field;
7971                 dginst->fields [i].generic_info = ifield;
7972                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7973         }
7974
7975         for (i = 0; i < dginst->count_properties; i++) {
7976                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7977                 MonoProperty *property = &dginst->properties [i];
7978
7979                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7980                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7981
7982                         property->parent = klass;
7983                         property->attrs = pb->attrs;
7984                         property->name = mono_string_to_utf8 (pb->name);
7985                         if (pb->get_method)
7986                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7987                         if (pb->set_method)
7988                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7989                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7990                         *property = *((MonoReflectionProperty *) obj)->property;
7991
7992                         if (property->get)
7993                                 property->get = inflate_mono_method (type, property->get, NULL);
7994                         if (property->set)
7995                                 property->set = inflate_mono_method (type, property->set, NULL);
7996                 } else
7997                         g_assert_not_reached ();
7998         }
7999
8000         for (i = 0; i < dginst->count_events; i++) {
8001                 MonoObject *obj = mono_array_get (events, gpointer, i);
8002                 MonoEvent *event = &dginst->events [i];
8003
8004                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8005                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8006
8007                         event->parent = klass;
8008                         event->attrs = eb->attrs;
8009                         event->name = mono_string_to_utf8 (eb->name);
8010                         if (eb->add_method)
8011                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8012                         if (eb->remove_method)
8013                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8014                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8015                         *event = *((MonoReflectionEvent *) obj)->event;
8016
8017                         if (event->add)
8018                                 event->add = inflate_mono_method (type, event->add, NULL);
8019                         if (event->remove)
8020                                 event->remove = inflate_mono_method (type, event->remove, NULL);
8021                 } else
8022                         g_assert_not_reached ();
8023         }
8024
8025         ginst->initialized = TRUE;
8026 }
8027
8028 static void
8029 ensure_runtime_vtable (MonoClass *klass)
8030 {
8031         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8032         int i, num, j, onum;
8033         MonoMethod **overrides;
8034
8035         if (!tb || klass->wastypebuilder)
8036                 return;
8037         if (klass->parent)
8038                 ensure_runtime_vtable (klass->parent);
8039
8040         num = tb->ctors? mono_array_length (tb->ctors): 0;
8041         num += tb->num_methods;
8042         klass->method.count = num;
8043         klass->methods = g_new (MonoMethod*, num);
8044         num = tb->ctors? mono_array_length (tb->ctors): 0;
8045         for (i = 0; i < num; ++i)
8046                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8047         num = tb->num_methods;
8048         j = i;
8049         for (i = 0; i < num; ++i)
8050                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8051
8052         klass->wastypebuilder = TRUE;
8053         if (tb->interfaces) {
8054                 klass->interface_count = mono_array_length (tb->interfaces);
8055                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8056                 for (i = 0; i < klass->interface_count; ++i) {
8057                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8058                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8059                 }
8060         }
8061
8062         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8063                 for (i = 0; i < klass->method.count; ++i)
8064                         klass->methods [i]->slot = i;
8065
8066         /* Overrides */
8067         onum = 0;
8068         if (tb->methods) {
8069                 for (i = 0; i < tb->num_methods; ++i) {
8070                         MonoReflectionMethodBuilder *mb = 
8071                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8072                         if (mb->override_method)
8073                                 onum ++;
8074                 }
8075         }
8076
8077         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8078
8079         if (tb->methods) {
8080                 onum = 0;
8081                 for (i = 0; i < tb->num_methods; ++i) {
8082                         MonoReflectionMethodBuilder *mb = 
8083                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8084                         if (mb->override_method) {
8085                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8086                                 overrides [onum * 2] = 
8087                                         mb->override_method->method;
8088                                 overrides [onum * 2 + 1] =
8089                                         mb->mhandle;
8090
8091                                 g_assert (mb->mhandle);
8092
8093                                 onum ++;
8094                         }
8095                 }
8096         }
8097
8098         mono_class_setup_vtable (klass, overrides, onum);
8099 }
8100
8101 static void
8102 typebuilder_setup_fields (MonoClass *klass)
8103 {
8104         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8105         MonoReflectionFieldBuilder *fb;
8106         MonoClassField *field;
8107         const char *p, *p2;
8108         int i;
8109         guint32 len, idx;
8110
8111         klass->field.count = tb->num_fields;
8112         klass->field.first = 0;
8113         klass->field.last = klass->field.count;
8114
8115         if (!klass->field.count)
8116                 return;
8117         
8118         klass->fields = g_new0 (MonoClassField, klass->field.count);
8119
8120         for (i = 0; i < klass->field.count; ++i) {
8121                 fb = mono_array_get (tb->fields, gpointer, i);
8122                 field = &klass->fields [i];
8123                 field->name = mono_string_to_utf8 (fb->name);
8124                 if (fb->attrs) {
8125                         /* FIXME: handle type modifiers */
8126                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
8127                         field->type->attrs = fb->attrs;
8128                 } else {
8129                         field->type = fb->type->type;
8130                 }
8131                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8132                         field->data = mono_array_addr (fb->rva_data, char, 0);
8133                 if (fb->offset != -1)
8134                         field->offset = fb->offset;
8135                 field->parent = klass;
8136                 fb->handle = field;
8137                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8138
8139                 if (fb->def_value) {
8140                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8141                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8142                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
8143                         /* Copy the data from the blob since it might get realloc-ed */
8144                         p = assembly->blob.data + idx;
8145                         len = mono_metadata_decode_blob_size (p, &p2);
8146                         len += p2 - p;
8147                         field->data = g_malloc (len);
8148                         memcpy ((gpointer)field->data, p, len);
8149                 }
8150         }
8151         mono_class_layout_fields (klass);
8152 }
8153
8154 static void
8155 typebuilder_setup_properties (MonoClass *klass)
8156 {
8157         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8158         MonoReflectionPropertyBuilder *pb;
8159         int i;
8160
8161         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8162         klass->property.first = 0;
8163         klass->property.last = klass->property.count;
8164
8165         klass->properties = g_new0 (MonoProperty, klass->property.count);
8166         for (i = 0; i < klass->property.count; ++i) {
8167                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8168                 klass->properties [i].parent = klass;
8169                 klass->properties [i].attrs = pb->attrs;
8170                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8171                 if (pb->get_method)
8172                         klass->properties [i].get = pb->get_method->mhandle;
8173                 if (pb->set_method)
8174                         klass->properties [i].set = pb->set_method->mhandle;
8175         }
8176 }
8177
8178 MonoReflectionEvent *
8179 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8180 {
8181         MonoEvent *event = g_new0 (MonoEvent, 1);
8182         MonoClass *klass;
8183         int j;
8184
8185         klass = my_mono_class_from_mono_type (tb->type.type);
8186
8187         event->parent = klass;
8188         event->attrs = eb->attrs;
8189         event->name = mono_string_to_utf8 (eb->name);
8190         if (eb->add_method)
8191                 event->add = eb->add_method->mhandle;
8192         if (eb->remove_method)
8193                 event->remove = eb->remove_method->mhandle;
8194         if (eb->raise_method)
8195                 event->raise = eb->raise_method->mhandle;
8196
8197         if (eb->other_methods) {
8198                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8199                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8200                         MonoReflectionMethodBuilder *mb = 
8201                                 mono_array_get (eb->other_methods,
8202                                                 MonoReflectionMethodBuilder*, j);
8203                         event->other [j] = mb->mhandle;
8204                 }
8205         }
8206
8207         return mono_event_get_object (mono_object_domain (tb), klass, event);
8208 }
8209
8210 static void
8211 typebuilder_setup_events (MonoClass *klass)
8212 {
8213         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8214         MonoReflectionEventBuilder *eb;
8215         int i, j;
8216
8217         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8218         klass->event.first = 0;
8219         klass->event.last = klass->event.count;
8220
8221         klass->events = g_new0 (MonoEvent, klass->event.count);
8222         for (i = 0; i < klass->event.count; ++i) {
8223                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8224                 klass->events [i].parent = klass;
8225                 klass->events [i].attrs = eb->attrs;
8226                 klass->events [i].name = mono_string_to_utf8 (eb->name);
8227                 if (eb->add_method)
8228                         klass->events [i].add = eb->add_method->mhandle;
8229                 if (eb->remove_method)
8230                         klass->events [i].remove = eb->remove_method->mhandle;
8231                 if (eb->raise_method)
8232                         klass->events [i].raise = eb->raise_method->mhandle;
8233
8234                 if (eb->other_methods) {
8235                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8236                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8237                                 MonoReflectionMethodBuilder *mb = 
8238                                         mono_array_get (eb->other_methods,
8239                                                                         MonoReflectionMethodBuilder*, j);
8240                                 klass->events [i].other [j] = mb->mhandle;
8241                         }
8242                 }
8243         }
8244 }
8245
8246 MonoReflectionType*
8247 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8248 {
8249         MonoClass *klass;
8250         MonoReflectionType* res;
8251         int i;
8252
8253         MONO_ARCH_SAVE_REGS;
8254
8255         klass = my_mono_class_from_mono_type (tb->type.type);
8256
8257         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8258
8259         /*
8260          * Fields to set in klass:
8261          * the various flags: delegate/unicode/contextbound etc.
8262          */
8263         klass->flags = tb->attrs;
8264
8265         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8266                 /* No need to fully construct the type */
8267                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8268
8269         /* enums are done right away */
8270         if (!klass->enumtype)
8271                 ensure_runtime_vtable (klass);
8272
8273         if (tb->subtypes) {
8274                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8275                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8276                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8277                 }
8278         }
8279
8280         /* fields and object layout */
8281         if (klass->parent) {
8282                 if (!klass->parent->size_inited)
8283                         mono_class_init (klass->parent);
8284                 klass->instance_size += klass->parent->instance_size;
8285                 klass->class_size += klass->parent->class_size;
8286                 klass->min_align = klass->parent->min_align;
8287         } else {
8288                 klass->instance_size = sizeof (MonoObject);
8289                 klass->min_align = 1;
8290         }
8291
8292         /* FIXME: handle packing_size and instance_size */
8293         typebuilder_setup_fields (klass);
8294
8295         typebuilder_setup_properties (klass);
8296
8297         typebuilder_setup_events (klass);
8298
8299         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8300         /* with enums res == tb: need to fix that. */
8301         if (!klass->enumtype)
8302                 g_assert (res != (MonoReflectionType*)tb);
8303         return res;
8304 }
8305
8306 void
8307 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8308 {
8309         MonoGenericParam *param;
8310         MonoImage *image;
8311
8312         MONO_ARCH_SAVE_REGS;
8313
8314         param = g_new0 (MonoGenericParam, 1);
8315
8316         param->method = NULL;
8317         param->name = mono_string_to_utf8 (gparam->name);
8318         param->num = gparam->index;
8319
8320         image = &gparam->tbuilder->module->dynamic_image->image;
8321         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8322
8323         param->pklass->reflection_info = gparam;
8324
8325         gparam->type.type = g_new0 (MonoType, 1);
8326         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8327         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8328         gparam->type.type->data.generic_param = param;
8329 }
8330
8331 MonoArray *
8332 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8333 {
8334         MonoDynamicImage *assembly = sig->module->dynamic_image;
8335         guint32 na = mono_array_length (sig->arguments);
8336         guint32 buflen, i;
8337         MonoArray *result;
8338         char *buf, *p;
8339
8340         MONO_ARCH_SAVE_REGS;
8341
8342         p = buf = g_malloc (10 + na * 10);
8343
8344         mono_metadata_encode_value (0x07, p, &p);
8345         mono_metadata_encode_value (na, p, &p);
8346         for (i = 0; i < na; ++i) {
8347                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8348                 encode_reflection_type (assembly, type, p, &p);
8349         }
8350
8351         buflen = p - buf;
8352         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8353         p = mono_array_addr (result, char, 0);
8354         memcpy (p, buf, buflen);
8355         g_free (buf);
8356
8357         return result;
8358 }
8359
8360 MonoArray *
8361 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8362 {
8363         MonoDynamicImage *assembly = sig->module->dynamic_image;
8364         guint32 na = mono_array_length (sig->arguments);
8365         guint32 buflen, i;
8366         MonoArray *result;
8367         char *buf, *p;
8368
8369         MONO_ARCH_SAVE_REGS;
8370
8371         p = buf = g_malloc (10 + na * 10);
8372
8373         mono_metadata_encode_value (0x06, p, &p);
8374         for (i = 0; i < na; ++i) {
8375                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8376                 encode_reflection_type (assembly, type, p, &p);
8377         }
8378
8379         buflen = p - buf;
8380         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8381         p = mono_array_addr (result, char, 0);
8382         memcpy (p, buf, buflen);
8383         g_free (buf);
8384
8385         return result;
8386 }
8387
8388 void 
8389 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8390 {
8391         ReflectionMethodBuilder rmb;
8392         MonoMethodSignature *sig;
8393         int i;
8394
8395         sig = dynamic_method_to_signature (mb);
8396
8397         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8398
8399         /*
8400          * Resolve references.
8401          */
8402         rmb.nrefs = mb->nrefs;
8403         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8404         for (i = 0; i < mb->nrefs; ++i) {
8405                 gpointer ref = resolve_object (mb->module->image, 
8406                                                mono_array_get (mb->refs, MonoObject*, i));
8407                 if (!ref) {
8408                         g_free (rmb.refs);
8409                         mono_raise_exception (mono_get_exception_type_load (NULL));
8410                         return;
8411                 }
8412                 rmb.refs [i] = ref;
8413         }               
8414
8415         /* FIXME: class */
8416         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8417
8418         g_free (rmb.refs);
8419
8420         /* ilgen is no longer needed */
8421         mb->ilgen = NULL;
8422 }
8423
8424 /**
8425  * mono_reflection_lookup_dynamic_token:
8426  *
8427  *  Finish the Builder object pointed to by TOKEN and return the corresponding
8428  * runtime structure.
8429  */
8430 gpointer
8431 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8432 {
8433         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8434         MonoObject *obj;
8435
8436         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8437         g_assert (obj);
8438
8439         return resolve_object (image, obj);
8440 }
8441
8442 static gpointer
8443 resolve_object (MonoImage *image, MonoObject *obj)
8444 {
8445         gpointer result = NULL;
8446
8447         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8448                 result = mono_string_intern ((MonoString*)obj);
8449                 g_assert (result);
8450         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8451                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8452                 result = mono_class_from_mono_type (tb->type);
8453                 g_assert (result);
8454         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8455                 result = ((MonoReflectionMethod*)obj)->method;
8456                 g_assert (result);
8457         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8458                 result = ((MonoReflectionMethod*)obj)->method;
8459                 g_assert (result);
8460         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8461                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8462                 result = mb->mhandle;
8463                 if (!result) {
8464                         /* Type is not yet created */
8465                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8466
8467                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8468
8469                         /*
8470                          * Hopefully this has been filled in by calling CreateType() on the
8471                          * TypeBuilder.
8472                          */
8473                         /**
8474                          * TODO: This won't work if the application finishes another 
8475                          * TypeBuilder instance instead of this one.
8476                          */
8477                         result = mb->mhandle;
8478                 }
8479         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8480                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8481
8482                 result = cb->mhandle;
8483                 if (!result) {
8484                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8485
8486                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8487                         result = cb->mhandle;
8488                 }
8489         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8490                 result = ((MonoReflectionField*)obj)->field;
8491                 g_assert (result);
8492         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8493                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8494                 result = fb->handle;
8495
8496                 if (!result) {
8497                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8498
8499                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8500                         result = fb->handle;
8501                 }
8502         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8503                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8504                 MonoClass *klass;
8505
8506                 klass = tb->type.type->data.klass;
8507                 if (klass->wastypebuilder) {
8508                         /* Already created */
8509                         result = klass;
8510                 }
8511                 else {
8512                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8513                         result = tb->type.type->data.klass;
8514                         g_assert (result);
8515                 }
8516         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8517                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8518                 MonoMethodSignature *sig;
8519                 int nargs, i;
8520
8521                 if (helper->arguments)
8522                         nargs = mono_array_length (helper->arguments);
8523                 else
8524                         nargs = 0;
8525
8526                 sig = mono_metadata_signature_alloc (image, nargs);
8527                 sig->explicit_this = helper->call_conv & 64;
8528                 sig->hasthis = helper->call_conv & 32;
8529
8530                 if (helper->call_conv == 0) /* unmanaged */
8531                         sig->call_convention = helper->unmanaged_call_conv - 1;
8532                 else
8533                         if (helper->call_conv & 0x02)
8534                                 sig->call_convention = MONO_CALL_VARARG;
8535                 else
8536                         sig->call_convention = MONO_CALL_DEFAULT;
8537
8538                 sig->param_count = nargs;
8539                 /* TODO: Copy type ? */
8540                 sig->ret = helper->return_type->type;
8541                 for (i = 0; i < nargs; ++i) {
8542                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8543                         sig->params [i] = rt->type;
8544                 }
8545
8546                 result = sig;
8547         } else {
8548                 g_print (obj->vtable->klass->name);
8549                 g_assert_not_reached ();
8550         }
8551         return result;
8552 }
8553