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