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