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