2004-12-08 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include "image.h"
29 #include "cil-coff.h"
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
32 #include "private.h"
33 #include <mono/os/gc_wrapper.h>
34
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA  0x00002000
40
41 typedef struct {
42         MonoReflectionILGen *ilgen;
43         MonoReflectionType *rtype;
44         MonoArray *parameters;
45         MonoArray *generic_params;
46         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->generic_type, 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->generic_type);
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         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3195         if (assoc)
3196                 return assoc;
3197         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3198 }
3199
3200 static int
3201 compare_custom_attrs (const void *a, const void *b)
3202 {
3203         const guint32 *a_values = a;
3204         const guint32 *b_values = b;
3205
3206         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3207 }
3208
3209 static int
3210 compare_field_marshal (const void *a, const void *b)
3211 {
3212         const guint32 *a_values = a;
3213         const guint32 *b_values = b;
3214
3215         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3216 }
3217
3218 static int
3219 compare_nested (const void *a, const void *b)
3220 {
3221         const guint32 *a_values = a;
3222         const guint32 *b_values = b;
3223
3224         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3225 }
3226
3227 static int
3228 compare_genericparam (const void *a, const void *b)
3229 {
3230         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3231         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3232
3233         if ((*b_entry)->owner == (*a_entry)->owner)
3234                 return 
3235                         (*a_entry)->gparam->type.type->data.generic_param->num - 
3236                         (*b_entry)->gparam->type.type->data.generic_param->num;
3237         else
3238                 return (*b_entry)->owner - (*a_entry)->owner;
3239 }
3240
3241 static int
3242 compare_declsecurity_attrs (const void *a, const void *b)
3243 {
3244         const guint32 *a_values = a;
3245         const guint32 *b_values = b;
3246
3247         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3248 }
3249
3250 static void
3251 pad_heap (MonoDynamicStream *sh)
3252 {
3253         if (sh->index & 3) {
3254                 int sz = 4 - (sh->index & 3);
3255                 memset (sh->data + sh->index, 0, sz);
3256                 sh->index += sz;
3257         }
3258 }
3259
3260 struct StreamDesc {
3261         const char *name;
3262         MonoDynamicStream *stream;
3263 };
3264
3265 /*
3266  * build_compressed_metadata() fills in the blob of data that represents the 
3267  * raw metadata as it will be saved in the PE file. The five streams are output 
3268  * and the metadata tables are comnpressed from the guint32 array representation, 
3269  * to the compressed on-disk format.
3270  */
3271 static void
3272 build_compressed_metadata (MonoDynamicImage *assembly)
3273 {
3274         MonoDynamicTable *table;
3275         int i;
3276         guint64 valid_mask = 0;
3277         guint64 sorted_mask;
3278         guint32 heapt_size = 0;
3279         guint32 meta_size = 256; /* allow for header and other stuff */
3280         guint32 table_offset;
3281         guint32 ntables = 0;
3282         guint64 *int64val;
3283         guint32 *int32val;
3284         guint16 *int16val;
3285         MonoImage *meta;
3286         unsigned char *p;
3287         struct StreamDesc stream_desc [5];
3288
3289         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3290         for (i = 0; i < assembly->gen_params->len; i++){
3291                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3292                 write_generic_param_entry (assembly, entry);
3293         }
3294
3295         stream_desc [0].name  = "#~";
3296         stream_desc [0].stream = &assembly->tstream;
3297         stream_desc [1].name  = "#Strings";
3298         stream_desc [1].stream = &assembly->sheap;
3299         stream_desc [2].name  = "#US";
3300         stream_desc [2].stream = &assembly->us;
3301         stream_desc [3].name  = "#Blob";
3302         stream_desc [3].stream = &assembly->blob;
3303         stream_desc [4].name  = "#GUID";
3304         stream_desc [4].stream = &assembly->guid;
3305         
3306         /* tables that are sorted */
3307         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3308                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3309                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3310                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3311                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3312                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3313         
3314         /* Compute table sizes */
3315         /* the MonoImage has already been created in mono_image_basic_init() */
3316         meta = &assembly->image;
3317
3318         /* sizes should be multiple of 4 */
3319         pad_heap (&assembly->blob);
3320         pad_heap (&assembly->guid);
3321         pad_heap (&assembly->sheap);
3322         pad_heap (&assembly->us);
3323
3324         /* Setup the info used by compute_sizes () */
3325         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3326         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3327         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3328
3329         meta_size += assembly->blob.index;
3330         meta_size += assembly->guid.index;
3331         meta_size += assembly->sheap.index;
3332         meta_size += assembly->us.index;
3333
3334         for (i=0; i < 64; ++i)
3335                 meta->tables [i].rows = assembly->tables [i].rows;
3336         
3337         for (i = 0; i < 64; i++){
3338                 if (meta->tables [i].rows == 0)
3339                         continue;
3340                 valid_mask |= (guint64)1 << i;
3341                 ntables ++;
3342                 meta->tables [i].row_size = mono_metadata_compute_size (
3343                         meta, i, &meta->tables [i].size_bitfield);
3344                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3345         }
3346         heapt_size += 24; /* #~ header size */
3347         heapt_size += ntables * 4;
3348         /* make multiple of 4 */
3349         heapt_size += 3;
3350         heapt_size &= ~3;
3351         meta_size += heapt_size;
3352         meta->raw_metadata = g_malloc0 (meta_size);
3353         p = meta->raw_metadata;
3354         /* the metadata signature */
3355         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3356         /* version numbers and 4 bytes reserved */
3357         int16val = (guint16*)p;
3358         *int16val++ = GUINT16_TO_LE (1);
3359         *int16val = GUINT16_TO_LE (1);
3360         p += 8;
3361         /* version string */
3362         int32val = (guint32*)p;
3363         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3364         p += 4;
3365         memcpy (p, meta->version, strlen (meta->version));
3366         p += GUINT32_FROM_LE (*int32val);
3367         align_pointer (meta->raw_metadata, p);
3368         int16val = (guint16*)p;
3369         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3370         *int16val = GUINT16_TO_LE (5); /* number of streams */
3371         p += 4;
3372
3373         /*
3374          * write the stream info.
3375          */
3376         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3377         table_offset += 3; table_offset &= ~3;
3378
3379         assembly->tstream.index = heapt_size;
3380         for (i = 0; i < 5; ++i) {
3381                 int32val = (guint32*)p;
3382                 stream_desc [i].stream->offset = table_offset;
3383                 *int32val++ = GUINT32_TO_LE (table_offset);
3384                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3385                 table_offset += GUINT32_FROM_LE (*int32val);
3386                 table_offset += 3; table_offset &= ~3;
3387                 p += 8;
3388                 strcpy (p, stream_desc [i].name);
3389                 p += strlen (stream_desc [i].name) + 1;
3390                 align_pointer (meta->raw_metadata, p);
3391         }
3392         /* 
3393          * now copy the data, the table stream header and contents goes first.
3394          */
3395         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3396         p = meta->raw_metadata + assembly->tstream.offset;
3397         int32val = (guint32*)p;
3398         *int32val = GUINT32_TO_LE (0); /* reserved */
3399         p += 4;
3400
3401         if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3402                         (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3403                         (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3404                 *p++ = 1; /* version */
3405                 *p++ = 1;
3406         } else {
3407                 *p++ = 1; /* version */
3408                 *p++ = 0;
3409         }
3410
3411         if (meta->idx_string_wide)
3412                 *p |= 0x01;
3413         if (meta->idx_guid_wide)
3414                 *p |= 0x02;
3415         if (meta->idx_blob_wide)
3416                 *p |= 0x04;
3417         ++p;
3418         *p++ = 1; /* reserved */
3419         int64val = (guint64*)p;
3420         *int64val++ = GUINT64_TO_LE (valid_mask);
3421         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3422         p += 16;
3423         int32val = (guint32*)p;
3424         for (i = 0; i < 64; i++){
3425                 if (meta->tables [i].rows == 0)
3426                         continue;
3427                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3428         }
3429         p = (unsigned char*)int32val;
3430
3431         /* sort the tables that still need sorting */
3432         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3433         if (table->rows)
3434                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3435         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3436         if (table->rows)
3437                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3438         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3439         if (table->rows)
3440                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3441         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3442         if (table->rows)
3443                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3444         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3445         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3446         if (table->rows)
3447                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3448
3449         /* compress the tables */
3450         for (i = 0; i < 64; i++){
3451                 int row, col;
3452                 guint32 *values;
3453                 guint32 bitfield = meta->tables [i].size_bitfield;
3454                 if (!meta->tables [i].rows)
3455                         continue;
3456                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3457                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3458                 meta->tables [i].base = p;
3459                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3460                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3461                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3462                                 switch (mono_metadata_table_size (bitfield, col)) {
3463                                 case 1:
3464                                         *p++ = values [col];
3465                                         break;
3466                                 case 2:
3467                                         *p++ = values [col] & 0xff;
3468                                         *p++ = (values [col] >> 8) & 0xff;
3469                                         break;
3470                                 case 4:
3471                                         *p++ = values [col] & 0xff;
3472                                         *p++ = (values [col] >> 8) & 0xff;
3473                                         *p++ = (values [col] >> 16) & 0xff;
3474                                         *p++ = (values [col] >> 24) & 0xff;
3475                                         break;
3476                                 default:
3477                                         g_assert_not_reached ();
3478                                 }
3479                         }
3480                 }
3481                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3482         }
3483         
3484         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3485         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3486         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3487         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3488         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3489
3490         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3491 }
3492
3493 /*
3494  * Some tables in metadata need to be sorted according to some criteria, but
3495  * when methods and fields are first created with reflection, they may be assigned a token
3496  * that doesn't correspond to the final token they will get assigned after the sorting.
3497  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3498  * with the reflection objects that represent them. Once all the tables are set up, the 
3499  * reflection objects will contains the correct table index. fixup_method() will fixup the
3500  * tokens for the method with ILGenerator @ilgen.
3501  */
3502 static void
3503 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3504         guint32 code_idx = GPOINTER_TO_UINT (value);
3505         MonoReflectionILTokenInfo *iltoken;
3506         MonoReflectionFieldBuilder *field;
3507         MonoReflectionCtorBuilder *ctor;
3508         MonoReflectionMethodBuilder *method;
3509         MonoReflectionTypeBuilder *tb;
3510         MonoReflectionArrayMethod *am;
3511         guint32 i, idx = 0;
3512         unsigned char *target;
3513
3514         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3515                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3516                 target = assembly->code.data + code_idx + iltoken->code_pos;
3517                 switch (target [3]) {
3518                 case MONO_TABLE_FIELD:
3519                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3520                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3521                                 idx = field->table_idx;
3522                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3523                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3524                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3525                         } else {
3526                                 g_assert_not_reached ();
3527                         }
3528                         break;
3529                 case MONO_TABLE_METHOD:
3530                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3531                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3532                                 idx = method->table_idx;
3533                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3534                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3535                                 idx = ctor->table_idx;
3536                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3537                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3538                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3539                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3540                         } else {
3541                                 g_assert_not_reached ();
3542                         }
3543                         break;
3544                 case MONO_TABLE_TYPEDEF:
3545                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3546                                 g_assert_not_reached ();
3547                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3548                         idx = tb->table_idx;
3549                         break;
3550                 case MONO_TABLE_MEMBERREF:
3551                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3552                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3553                                 idx = am->table_idx;
3554                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3555                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3556                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3557                                 g_assert (m->klass->generic_class);
3558                                 continue;
3559                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3560                                 continue;
3561                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3562                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3563                                 g_assert (f->generic_info);
3564                                 continue;
3565                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3566                                 continue;
3567                         } else {
3568                                 g_assert_not_reached ();
3569                         }
3570                         break;
3571                 case MONO_TABLE_METHODSPEC:
3572                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3573                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3574                                 g_assert (m->signature->generic_param_count);
3575                                 continue;
3576                         } else {
3577                                 g_assert_not_reached ();
3578                         }
3579                         break;
3580                 default:
3581                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
3582                 }
3583                 target [0] = idx & 0xff;
3584                 target [1] = (idx >> 8) & 0xff;
3585                 target [2] = (idx >> 16) & 0xff;
3586         }
3587 }
3588
3589 /*
3590  * fixup_cattrs:
3591  *
3592  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3593  * value is not known when the table is emitted.
3594  */
3595 static void
3596 fixup_cattrs (MonoDynamicImage *assembly)
3597 {
3598         MonoDynamicTable *table;
3599         guint32 *values;
3600         guint32 type, i, idx, token;
3601         MonoObject *ctor;
3602
3603         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3604
3605         for (i = 0; i < table->rows; ++i) {
3606                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3607
3608                 type = values [MONO_CUSTOM_ATTR_TYPE];
3609                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3610                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3611                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3612                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3613                         g_assert (ctor);
3614
3615                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3616                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3617                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3618                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3619                         }
3620                 }
3621         }
3622 }
3623
3624 static void
3625 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3626 {
3627         MonoDynamicTable *table;
3628         guint32 *values;
3629         char *name;
3630
3631         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3632         table->rows++;
3633         alloc_table (table, table->rows);
3634         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3635         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3636         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3637         name = mono_string_to_utf8 (rsrc->name);
3638         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3639         g_free (name);
3640         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3641         table->next_idx++;
3642 }
3643
3644 static void
3645 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3646 {
3647         MonoDynamicTable *table;
3648         guint32 *values;
3649         char blob_size [6];
3650         guchar hash [20];
3651         char *b = blob_size;
3652         char *name, *sname;
3653         guint32 idx, offset;
3654
3655         if (rsrc->filename) {
3656                 name = mono_string_to_utf8 (rsrc->filename);
3657                 sname = g_path_get_basename (name);
3658         
3659                 table = &assembly->tables [MONO_TABLE_FILE];
3660                 table->rows++;
3661                 alloc_table (table, table->rows);
3662                 values = table->values + table->next_idx * MONO_FILE_SIZE;
3663                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3664                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3665                 g_free (sname);
3666
3667                 mono_sha1_get_digest_from_file (name, hash);
3668                 mono_metadata_encode_value (20, b, &b);
3669                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3670                 mono_image_add_stream_data (&assembly->blob, hash, 20);
3671                 g_free (name);
3672                 idx = table->next_idx++;
3673                 rsrc->offset = 0;
3674                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3675         } else {
3676                 char sizebuf [4];
3677                 offset = mono_array_length (rsrc->data);
3678                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3679                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3680                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3681                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3682
3683                 if (!mb->is_main)
3684                         /* 
3685                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3686                          * the main module, but that needs to reference the FILE table
3687                          * which isn't emitted yet.
3688                          */
3689                         return;
3690                 else
3691                         idx = 0;
3692         }
3693
3694         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3695 }
3696
3697 static void
3698 set_version_from_string (MonoString *version, guint32 *values)
3699 {
3700         gchar *ver, *p, *str;
3701         guint32 i;
3702         
3703         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3704         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3705         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3706         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3707         if (!version)
3708                 return;
3709         ver = str = mono_string_to_utf8 (version);
3710         for (i = 0; i < 4; ++i) {
3711                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3712                 switch (*p) {
3713                 case '.':
3714                         p++;
3715                         break;
3716                 case '*':
3717                         /* handle Revision and Build */
3718                         p++;
3719                         break;
3720                 }
3721                 ver = p;
3722         }
3723         g_free (str);
3724 }
3725
3726 static guint32
3727 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3728         gsize len;
3729         guint32 token = 0;
3730         char blob_size [6];
3731         char *b = blob_size;
3732
3733         if (!pkey)
3734                 return token;
3735
3736         len = mono_array_length (pkey);
3737         mono_metadata_encode_value (len, b, &b);
3738         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3739         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3740
3741         /* need to get the actual value from the key type... */
3742         assembly->strong_name_size = 128;
3743         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3744
3745         return token;
3746 }
3747
3748 static void
3749 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3750 {
3751         MonoDynamicTable *table;
3752         MonoDynamicImage *assembly;
3753         MonoReflectionAssemblyBuilder *assemblyb;
3754         MonoDomain *domain;
3755         guint32 *values;
3756         char *name;
3757         int i;
3758         guint32 module_index;
3759
3760         assemblyb = moduleb->assemblyb;
3761         assembly = moduleb->dynamic_image;
3762         domain = mono_object_domain (assemblyb);
3763
3764         /* Emit ASSEMBLY table */
3765         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3766         alloc_table (table, 1);
3767         values = table->values + MONO_ASSEMBLY_SIZE;
3768         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3769         name = mono_string_to_utf8 (assemblyb->name);
3770         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3771         g_free (name);
3772         if (assemblyb->culture) {
3773                 name = mono_string_to_utf8 (assemblyb->culture);
3774                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3775                 g_free (name);
3776         } else {
3777                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3778         }
3779         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3780         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3781         set_version_from_string (assemblyb->version, values);
3782
3783         /* Emit FILE + EXPORTED_TYPE table */
3784         module_index = 0;
3785         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3786                 int j;
3787                 MonoReflectionModuleBuilder *file_module = 
3788                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3789                 if (file_module != moduleb) {
3790                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3791                         module_index ++;
3792                         if (file_module->types) {
3793                                 for (j = 0; j < file_module->num_types; ++j) {
3794                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3795                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3796                                 }
3797                         }
3798                 }
3799         }
3800         if (assemblyb->loaded_modules) {
3801                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3802                         MonoReflectionModule *file_module = 
3803                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3804                         mono_image_fill_file_table (domain, file_module, assembly);
3805                         module_index ++;
3806                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3807                 }
3808         }
3809
3810         /* Emit MANIFESTRESOURCE table */
3811         module_index = 0;
3812         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3813                 int j;
3814                 MonoReflectionModuleBuilder *file_module = 
3815                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3816                 /* The table for the main module is emitted later */
3817                 if (file_module != moduleb) {
3818                         module_index ++;
3819                         if (file_module->resources) {
3820                                 int len = mono_array_length (file_module->resources);
3821                                 for (j = 0; j < len; ++j) {
3822                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3823                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3824                                 }
3825                         }
3826                 }
3827         }               
3828 }
3829
3830 /*
3831  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3832  * for the modulebuilder @moduleb.
3833  * At the end of the process, method and field tokens are fixed up and the 
3834  * on-disk compressed metadata representation is created.
3835  */
3836 void
3837 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3838 {
3839         MonoDynamicTable *table;
3840         MonoDynamicImage *assembly;
3841         MonoReflectionAssemblyBuilder *assemblyb;
3842         MonoDomain *domain;
3843         guint32 *values;
3844         int i;
3845
3846         assemblyb = moduleb->assemblyb;
3847         assembly = moduleb->dynamic_image;
3848         domain = mono_object_domain (assemblyb);
3849
3850         if (assembly->text_rva)
3851                 return;
3852
3853         assembly->text_rva = START_TEXT_RVA;
3854
3855         if (moduleb->is_main) {
3856                 mono_image_emit_manifest (moduleb);
3857         }
3858
3859         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3860         table->rows = 1; /* .<Module> */
3861         table->next_idx++;
3862         alloc_table (table, table->rows);
3863         /*
3864          * Set the first entry.
3865          */
3866         values = table->values + table->columns;
3867         values [MONO_TYPEDEF_FLAGS] = 0;
3868         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3869         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3870         values [MONO_TYPEDEF_EXTENDS] = 0;
3871         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3872         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3873
3874         /* 
3875          * handle global methods 
3876          * FIXME: test what to do when global methods are defined in multiple modules.
3877          */
3878         if (moduleb->global_methods) {
3879                 table = &assembly->tables [MONO_TABLE_METHOD];
3880                 table->rows += mono_array_length (moduleb->global_methods);
3881                 alloc_table (table, table->rows);
3882                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3883                         mono_image_get_method_info (
3884                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3885         }
3886         if (moduleb->global_fields) {
3887                 table = &assembly->tables [MONO_TABLE_FIELD];
3888                 table->rows += mono_array_length (moduleb->global_fields);
3889                 alloc_table (table, table->rows);
3890                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3891                         mono_image_get_field_info (
3892                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3893         }
3894
3895         table = &assembly->tables [MONO_TABLE_MODULE];
3896         alloc_table (table, 1);
3897         mono_image_fill_module_table (domain, moduleb, assembly);
3898
3899         /* Emit types */
3900         {
3901                 /* Collect all types into a list sorted by their table_idx */
3902                 GPtrArray *types = g_ptr_array_new ();
3903
3904                 if (moduleb->types)
3905                         for (i = 0; i < moduleb->num_types; ++i) {
3906                                 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3907                                 collect_types (types, type);
3908                         }
3909
3910                 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3911                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3912                 table->rows += types->len;
3913                 alloc_table (table, table->rows);
3914
3915                 for (i = 0; i < types->len; ++i) {
3916                         MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3917                         mono_image_get_type_info (domain, type, assembly);
3918                 }
3919                 g_ptr_array_free (types, TRUE);
3920         }
3921
3922         /* 
3923          * table->rows is already set above and in mono_image_fill_module_table.
3924          */
3925         /* add all the custom attributes at the end, once all the indexes are stable */
3926         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3927
3928         /* CAS assembly permissions */
3929         if (assemblyb->permissions_minimum)
3930                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3931         if (assemblyb->permissions_optional)
3932                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3933         if (assemblyb->permissions_refused)
3934                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3935
3936         module_add_cattrs (assembly, moduleb);
3937
3938         /* fixup tokens */
3939         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3940         fixup_cattrs (assembly);
3941 }
3942
3943 /*
3944  * mono_image_insert_string:
3945  * @module: module builder object
3946  * @str: a string
3947  *
3948  * Insert @str into the user string stream of @module.
3949  */
3950 guint32
3951 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3952 {
3953         MonoDynamicImage *assembly;
3954         guint32 idx;
3955         char buf [16];
3956         char *b = buf;
3957         
3958         MONO_ARCH_SAVE_REGS;
3959
3960         if (!module->dynamic_image)
3961                 mono_image_module_basic_init (module);
3962
3963         assembly = module->dynamic_image;
3964         
3965         if (assembly->save) {
3966                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3967                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3968 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3969         {
3970                 char *swapped = g_malloc (2 * mono_string_length (str));
3971                 const char *p = (const char*)mono_string_chars (str);
3972
3973                 swap_with_size (swapped, p, 2, mono_string_length (str));
3974                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3975                 g_free (swapped);
3976         }
3977 #else
3978                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3979 #endif
3980                 mono_image_add_stream_data (&assembly->us, "", 1);
3981         } else {
3982                 idx = assembly->us.index ++;
3983         }
3984
3985         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3986
3987         return MONO_TOKEN_STRING | idx;
3988 }
3989
3990 guint32
3991 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3992 {
3993         MonoClass *klass;
3994         guint32 token = 0;
3995
3996         klass = obj->vtable->klass;
3997         if (strcmp (klass->name, "MonoMethod") == 0) {
3998                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3999                 MonoMethodSignature *sig, *old;
4000                 guint32 sig_token, parent;
4001                 int nargs, i;
4002
4003                 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4004
4005                 nargs = mono_array_length (opt_param_types);
4006                 old = method->signature;
4007                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4008
4009                 sig->hasthis = old->hasthis;
4010                 sig->explicit_this = old->explicit_this;
4011                 sig->call_convention = old->call_convention;
4012                 sig->generic_param_count = old->generic_param_count;
4013                 sig->param_count = old->param_count + nargs;
4014                 sig->sentinelpos = old->param_count;
4015                 sig->ret = old->ret;
4016
4017                 for (i = 0; i < old->param_count; i++)
4018                         sig->params [i] = old->params [i];
4019
4020                 for (i = 0; i < nargs; i++) {
4021                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4022                         sig->params [old->param_count + i] = rt->type;
4023                 }
4024
4025                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4026                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4027                 parent >>= MONO_TYPEDEFORREF_BITS;
4028
4029                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4030                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4031
4032                 sig_token = method_encode_signature (assembly, sig);
4033                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4034         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4035                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4036                 ReflectionMethodBuilder rmb;
4037                 guint32 parent, sig;
4038         
4039                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4040                 rmb.opt_types = opt_param_types;
4041
4042                 sig = method_builder_encode_signature (assembly, &rmb);
4043
4044                 parent = mono_image_create_token (assembly, obj, TRUE);
4045                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4046
4047                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4048                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4049
4050                 token = mono_image_get_varargs_method_token (
4051                         assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4052         } else {
4053                 g_error ("requested method token for %s\n", klass->name);
4054         }
4055
4056         return token;
4057 }
4058
4059 /*
4060  * mono_image_create_token:
4061  * @assembly: a dynamic assembly
4062  * @obj:
4063  *
4064  * Get a token to insert in the IL code stream for the given MemberInfo.
4065  * @obj can be one of:
4066  *      ConstructorBuilder
4067  *      MethodBuilder
4068  *      FieldBuilder
4069  *      MonoCMethod
4070  *      MonoMethod
4071  *      MonoField
4072  *      MonoType
4073  *      TypeBuilder
4074  */
4075 guint32
4076 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4077 {
4078         MonoClass *klass;
4079         guint32 token = 0;
4080
4081         klass = obj->vtable->klass;
4082         if (strcmp (klass->name, "MethodBuilder") == 0) {
4083                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4084
4085                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4086                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4087                 else
4088                         token = mono_image_get_methodbuilder_token (assembly, mb);
4089                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4090         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4091                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4092
4093                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4094                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4095                 else
4096                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4097                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4098         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4099                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4100                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4101                 if (tb->generic_params) {
4102                         token = mono_image_get_generic_field_token (assembly, fb);
4103                 } else {
4104                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4105                 }
4106         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4107                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4108                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4109         } else if (strcmp (klass->name, "MonoType") == 0 ||
4110                  strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4111                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4112                 token = mono_metadata_token_from_dor (
4113                         mono_image_typedef_or_ref (assembly, tb->type));
4114         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4115                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4116                 token = mono_metadata_token_from_dor (
4117                         mono_image_typedef_or_ref (assembly, tb->type));
4118         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4119                         strcmp (klass->name, "MonoMethod") == 0) {
4120                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4121                 if (m->method->signature->is_inflated) {
4122                         if (create_methodspec)
4123                                 token = mono_image_get_methodspec_token (assembly, m->method);
4124                         else
4125                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4126                 } else if ((m->method->klass->image == &assembly->image) &&
4127                          !m->method->klass->generic_class) {
4128                         static guint32 method_table_idx = 0xffffff;
4129                         if (m->method->klass->wastypebuilder) {
4130                                 /* we use the same token as the one that was assigned
4131                                  * to the Methodbuilder.
4132                                  * FIXME: do the equivalent for Fields.
4133                                  */
4134                                 token = m->method->token;
4135                         } else {
4136                                 /*
4137                                  * Each token should have a unique index, but the indexes are
4138                                  * assigned by managed code, so we don't know about them. An
4139                                  * easy solution is to count backwards...
4140                                  */
4141                                 method_table_idx --;
4142                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4143                         }
4144                 } else {
4145                         token = mono_image_get_methodref_token (assembly, m->method);
4146                 }
4147                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4148         } else if (strcmp (klass->name, "MonoField") == 0) {
4149                 MonoReflectionField *f = (MonoReflectionField *)obj;
4150                 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4151                         static guint32 field_table_idx = 0xffffff;
4152                         field_table_idx --;
4153                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4154                 } else {
4155                         token = mono_image_get_fieldref_token (assembly, f);
4156                 }
4157                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4158         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4159                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4160                 token = mono_image_get_array_token (assembly, m);
4161         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4162                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4163                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4164         } else {
4165                 g_error ("requested token for %s\n", klass->name);
4166         }
4167
4168         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4169
4170         return token;
4171 }
4172
4173 typedef struct {
4174         guint32 import_lookup_table;
4175         guint32 timestamp;
4176         guint32 forwarder;
4177         guint32 name_rva;
4178         guint32 import_address_table_rva;
4179 } MonoIDT;
4180
4181 typedef struct {
4182         guint32 name_rva;
4183         guint32 flags;
4184 } MonoILT;
4185
4186 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4187
4188 static MonoDynamicImage*
4189 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4190 {
4191         static const guchar entrycode [16] = {0xff, 0x25, 0};
4192         MonoDynamicImage *image;
4193         int i;
4194
4195         const char *version = mono_get_runtime_version ();
4196
4197 #if HAVE_BOEHM_GC
4198         image = GC_MALLOC (sizeof (MonoDynamicImage));
4199 #else
4200         image = g_new0 (MonoDynamicImage, 1);
4201 #endif
4202
4203         /* keep in sync with image.c */
4204         image->image.name = assembly_name;
4205         image->image.assembly_name = image->image.name; /* they may be different */
4206         image->image.module_name = module_name;
4207         image->image.version = g_strdup (version);
4208         image->image.dynamic = TRUE;
4209
4210         image->image.references = g_new0 (MonoAssembly*, 1);
4211         image->image.references [0] = NULL;
4212
4213         mono_image_init (&image->image);
4214
4215         image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4216         image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4217         image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4218         image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4219         image->handleref = g_hash_table_new (NULL, NULL);
4220         image->tokens = mono_g_hash_table_new (NULL, NULL);
4221         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4222         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4223         image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4224         image->gen_params = g_ptr_array_new ();
4225
4226         string_heap_init (&image->sheap);
4227         mono_image_add_stream_data (&image->us, "", 1);
4228         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4229         /* import tables... */
4230         mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4231         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4232         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4233         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4234         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4235         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4236         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4237         stream_data_align (&image->code);
4238
4239         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4240
4241         for (i=0; i < 64; ++i) {
4242                 image->tables [i].next_idx = 1;
4243                 image->tables [i].columns = table_sizes [i];
4244         }
4245
4246         image->image.assembly = (MonoAssembly*)assembly;
4247         image->run = assembly->run;
4248         image->save = assembly->save;
4249         image->pe_kind = 0x1; /* ILOnly */
4250         image->machine = 0x14c; /* I386 */
4251
4252         return image;
4253 }
4254
4255 /*
4256  * mono_image_basic_init:
4257  * @assembly: an assembly builder object
4258  *
4259  * Create the MonoImage that represents the assembly builder and setup some
4260  * of the helper hash table and the basic metadata streams.
4261  */
4262 void
4263 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4264 {
4265         MonoDynamicAssembly *assembly;
4266         MonoDynamicImage *image;
4267         
4268         MONO_ARCH_SAVE_REGS;
4269
4270         if (assemblyb->dynamic_assembly)
4271                 return;
4272
4273 #if HAVE_BOEHM_GC
4274         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4275 #else
4276         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4277 #endif
4278
4279         assembly->assembly.dynamic = TRUE;
4280         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4281         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4282         if (assemblyb->culture)
4283                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4284         else
4285                 assembly->assembly.aname.culture = g_strdup ("");
4286
4287         assembly->run = assemblyb->access != 2;
4288         assembly->save = assemblyb->access != 1;
4289
4290         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4291         image->initial_image = TRUE;
4292         assembly->assembly.aname.name = image->image.name;
4293         assembly->assembly.image = &image->image;
4294
4295         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4296         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4297 }
4298
4299 static int
4300 calc_section_size (MonoDynamicImage *assembly)
4301 {
4302         int nsections = 0;
4303
4304         /* alignment constraints */
4305         assembly->code.index += 3;
4306         assembly->code.index &= ~3;
4307         assembly->meta_size += 3;
4308         assembly->meta_size &= ~3;
4309         assembly->resources.index += 3;
4310         assembly->resources.index &= ~3;
4311
4312         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4313         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4314         nsections++;
4315
4316         if (assembly->win32_res) {
4317                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4318
4319                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4320                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4321                 nsections++;
4322         }
4323
4324         assembly->sections [MONO_SECTION_RELOC].size = 12;
4325         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4326         nsections++;
4327
4328         return nsections;
4329 }
4330
4331 typedef struct {
4332         guint32 id;
4333         guint32 offset;
4334         GSList *children;
4335         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4336 } ResTreeNode;
4337
4338 static int
4339 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4340 {
4341         ResTreeNode *t1 = (ResTreeNode*)a;
4342         ResTreeNode *t2 = (ResTreeNode*)b;
4343
4344         return t1->id - t2->id;
4345 }
4346
4347 /*
4348  * resource_tree_create:
4349  *
4350  *  Organize the resources into a resource tree.
4351  */
4352 static ResTreeNode *
4353 resource_tree_create (MonoArray *win32_resources)
4354 {
4355         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4356         GSList *l;
4357         int i;
4358
4359         tree = g_new0 (ResTreeNode, 1);
4360         
4361         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4362                 MonoReflectionWin32Resource *win32_res =
4363                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4364
4365                 /* Create node */
4366
4367                 lang_node = g_new0 (ResTreeNode, 1);
4368                 lang_node->id = win32_res->lang_id;
4369                 lang_node->win32_res = win32_res;
4370
4371                 /* Create type node if neccesary */
4372                 type_node = NULL;
4373                 for (l = tree->children; l; l = l->next)
4374                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4375                                 type_node = (ResTreeNode*)l->data;
4376                                 break;
4377                         }
4378
4379                 if (!type_node) {
4380                         type_node = g_new0 (ResTreeNode, 1);
4381                         type_node->id = win32_res->res_type;
4382
4383                         /* 
4384                          * The resource types have to be sorted otherwise
4385                          * Windows Explorer can't display the version information.
4386                          */
4387                         tree->children = g_slist_insert_sorted (tree->children, 
4388                                 type_node, resource_tree_compare_by_id);
4389                 }
4390
4391                 /* Create res node if neccesary */
4392                 res_node = NULL;
4393                 for (l = type_node->children; l; l = l->next)
4394                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4395                                 res_node = (ResTreeNode*)l->data;
4396                                 break;
4397                         }
4398
4399                 if (!res_node) {
4400                         res_node = g_new0 (ResTreeNode, 1);
4401                         res_node->id = win32_res->res_id;
4402                         type_node->children = g_slist_append (type_node->children, res_node);
4403                 }
4404
4405                 res_node->children = g_slist_append (res_node->children, lang_node);
4406         }
4407
4408         return tree;
4409 }
4410
4411 /*
4412  * resource_tree_encode:
4413  * 
4414  *   Encode the resource tree into the format used in the PE file.
4415  */
4416 static void
4417 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4418 {
4419         char *entries;
4420         MonoPEResourceDir dir;
4421         MonoPEResourceDirEntry dir_entry;
4422         MonoPEResourceDataEntry data_entry;
4423         GSList *l;
4424
4425         /*
4426          * For the format of the resource directory, see the article
4427          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4428          * Matt Pietrek
4429          */
4430
4431         memset (&dir, 0, sizeof (dir));
4432         memset (&dir_entry, 0, sizeof (dir_entry));
4433         memset (&data_entry, 0, sizeof (data_entry));
4434
4435         g_assert (sizeof (dir) == 16);
4436         g_assert (sizeof (dir_entry) == 8);
4437         g_assert (sizeof (data_entry) == 16);
4438
4439         node->offset = p - begin;
4440
4441         /* IMAGE_RESOURCE_DIRECTORY */
4442         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4443
4444         memcpy (p, &dir, sizeof (dir));
4445         p += sizeof (dir);
4446
4447         /* Reserve space for entries */
4448         entries = p;
4449         p += sizeof (dir_entry) * dir.res_id_entries;
4450
4451         /* Write children */
4452         for (l = node->children; l; l = l->next) {
4453                 ResTreeNode *child = (ResTreeNode*)l->data;
4454
4455                 if (child->win32_res) {
4456
4457                         child->offset = p - begin;
4458
4459                         /* IMAGE_RESOURCE_DATA_ENTRY */
4460                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4461                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4462
4463                         memcpy (p, &data_entry, sizeof (data_entry));
4464                         p += sizeof (data_entry);
4465
4466                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4467                         p += data_entry.rde_size;
4468                 } else {
4469                         resource_tree_encode (child, begin, p, &p);
4470                 }
4471         }
4472
4473         /* IMAGE_RESOURCE_ENTRY */
4474         for (l = node->children; l; l = l->next) {
4475                 ResTreeNode *child = (ResTreeNode*)l->data;
4476                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4477
4478                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4479                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4480
4481                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4482                 entries += sizeof (dir_entry);
4483         }
4484
4485         *endbuf = p;
4486 }
4487
4488 static void
4489 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4490 {
4491         char *buf;
4492         char *p;
4493         guint32 size, i;
4494         MonoReflectionWin32Resource *win32_res;
4495         ResTreeNode *tree;
4496
4497         if (!assemblyb->win32_resources)
4498                 return;
4499
4500         /*
4501          * Resources are stored in a three level tree inside the PE file.
4502          * - level one contains a node for each type of resource
4503          * - level two contains a node for each resource
4504          * - level three contains a node for each instance of a resource for a
4505          *   specific language.
4506          */
4507
4508         tree = resource_tree_create (assemblyb->win32_resources);
4509
4510         /* Estimate the size of the encoded tree */
4511         size = 0;
4512         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4513                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4514                 size += mono_array_length (win32_res->res_data);
4515         }
4516         /* Directory structure */
4517         size += mono_array_length (assemblyb->win32_resources) * 256;
4518         p = buf = g_malloc (size);
4519
4520         resource_tree_encode (tree, p, p, &p);
4521
4522         g_assert (p - buf < size);
4523
4524         assembly->win32_res = g_malloc (p - buf);
4525         assembly->win32_res_size = p - buf;
4526         memcpy (assembly->win32_res, buf, p - buf);
4527
4528         g_free (buf);
4529 }
4530
4531 static void
4532 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4533 {
4534         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4535         int i;
4536
4537         p += sizeof (MonoPEResourceDir);
4538         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4539                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4540                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4541                 if (dir_entry->is_dir) {
4542                         fixup_resource_directory (res_section, child, rva);
4543                 } else {
4544                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4545                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4546                 }
4547
4548                 p += sizeof (MonoPEResourceDirEntry);
4549         }
4550 }
4551
4552 static void
4553 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4554 {
4555         guint32 dummy;
4556         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4557                 g_error ("WriteFile returned %d\n", GetLastError ());
4558 }
4559
4560 /*
4561  * mono_image_create_pefile:
4562  * @mb: a module builder object
4563  * 
4564  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4565  * assembly->pefile where it can be easily retrieved later in chunks.
4566  */
4567 void
4568 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4569         MonoMSDOSHeader *msdos;
4570         MonoDotNetHeader *header;
4571         MonoSectionTable *section;
4572         MonoCLIHeader *cli_header;
4573         guint32 size, image_size, virtual_base, text_offset;
4574         guint32 header_start, section_start, file_offset, virtual_offset;
4575         MonoDynamicImage *assembly;
4576         MonoReflectionAssemblyBuilder *assemblyb;
4577         MonoDynamicStream pefile_stream = {0};
4578         MonoDynamicStream *pefile = &pefile_stream;
4579         int i, nsections;
4580         guint32 *rva, value;
4581         guchar *p;
4582         static const unsigned char msheader[] = {
4583                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4584                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4585                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4586                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4587                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4588                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4589                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4590                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4591         };
4592
4593         assemblyb = mb->assemblyb;
4594
4595         mono_image_basic_init (assemblyb);
4596         assembly = mb->dynamic_image;
4597
4598         assembly->pe_kind = assemblyb->pe_kind;
4599         assembly->machine = assemblyb->machine;
4600         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4601         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4602         
4603         mono_image_build_metadata (mb);
4604
4605         if (mb->is_main && assemblyb->resources) {
4606                 int len = mono_array_length (assemblyb->resources);
4607                 for (i = 0; i < len; ++i)
4608                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4609         }
4610
4611         if (mb->resources) {
4612                 int len = mono_array_length (mb->resources);
4613                 for (i = 0; i < len; ++i)
4614                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4615         }
4616
4617         build_compressed_metadata (assembly);
4618
4619         if (mb->is_main)
4620                 assembly_add_win32_resources (assembly, assemblyb);
4621
4622         nsections = calc_section_size (assembly);
4623         
4624         /* The DOS header and stub */
4625         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4626         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4627
4628         /* the dotnet header */
4629         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4630
4631         /* the section tables */
4632         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4633
4634         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4635         virtual_offset = VIRT_ALIGN;
4636         image_size = 0;
4637
4638         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4639                 if (!assembly->sections [i].size)
4640                         continue;
4641                 /* align offsets */
4642                 file_offset += FILE_ALIGN - 1;
4643                 file_offset &= ~(FILE_ALIGN - 1);
4644                 virtual_offset += VIRT_ALIGN - 1;
4645                 virtual_offset &= ~(VIRT_ALIGN - 1);
4646
4647                 assembly->sections [i].offset = file_offset;
4648                 assembly->sections [i].rva = virtual_offset;
4649
4650                 file_offset += assembly->sections [i].size;
4651                 virtual_offset += assembly->sections [i].size;
4652                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4653         }
4654
4655         file_offset += FILE_ALIGN - 1;
4656         file_offset &= ~(FILE_ALIGN - 1);
4657
4658         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4659
4660         /* back-patch info */
4661         msdos = (MonoMSDOSHeader*)pefile->data;
4662         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4663         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4664         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4665
4666         header = (MonoDotNetHeader*)(pefile->data + header_start);
4667         header->pesig [0] = 'P';
4668         header->pesig [1] = 'E';
4669         
4670         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4671         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4672         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4673         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4674         if (assemblyb->pekind == 1) {
4675                 /* it's a dll */
4676                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4677         } else {
4678                 /* it's an exe */
4679                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4680         }
4681
4682         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4683
4684         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4685         header->pe.pe_major = 6;
4686         header->pe.pe_minor = 0;
4687         size = assembly->sections [MONO_SECTION_TEXT].size;
4688         size += FILE_ALIGN - 1;
4689         size &= ~(FILE_ALIGN - 1);
4690         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4691         size = assembly->sections [MONO_SECTION_RSRC].size;
4692         size += FILE_ALIGN - 1;
4693         size &= ~(FILE_ALIGN - 1);
4694         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4695         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4696         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4697         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4698         /* pe_rva_entry_point always at the beginning of the text section */
4699         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4700
4701         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4702         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4703         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4704         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4705         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4706         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4707         size = section_start;
4708         size += FILE_ALIGN - 1;
4709         size &= ~(FILE_ALIGN - 1);
4710         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4711         size = image_size;
4712         size += VIRT_ALIGN - 1;
4713         size &= ~(VIRT_ALIGN - 1);
4714         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4715
4716         /*
4717         // Translate the PEFileKind value to the value expected by the Windows loader
4718         */
4719         {
4720                 short kind;
4721
4722                 /*
4723                 // PEFileKinds.Dll == 1
4724                 // PEFileKinds.ConsoleApplication == 2
4725                 // PEFileKinds.WindowApplication == 3
4726                 //
4727                 // need to get:
4728                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4729                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4730                 */
4731                 if (assemblyb->pekind == 3)
4732                         kind = 2;
4733                 else
4734                         kind = 3;
4735                 
4736                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4737         }    
4738         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4739         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4740         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4741         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4742         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4743         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4744
4745         /* fill data directory entries */
4746
4747         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4748         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4749
4750         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4751         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4752
4753         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4754         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4755         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4756         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4757         /* patch entrypoint name */
4758         if (assemblyb->pekind == 1)
4759                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4760         else
4761                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4762         /* patch imported function RVA name */
4763         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4764         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4765
4766         /* the import table */
4767         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4768         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4769         /* patch imported dll RVA name and other entries in the dir */
4770         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4771         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4772         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4773         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4774         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4775         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4776
4777         p = (assembly->code.data + assembly->ilt_offset);
4778         value = (assembly->text_rva + assembly->imp_names_offset);
4779         *p++ = (value) & 0xff;
4780         *p++ = (value >> 8) & (0xff);
4781         *p++ = (value >> 16) & (0xff);
4782         *p++ = (value >> 24) & (0xff);
4783
4784         /* the CLI header info */
4785         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4786         cli_header->ch_size = GUINT32_FROM_LE (72);
4787         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4788         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4789         if (assemblyb->entry_point) {
4790                 guint32 table_idx = 0;
4791                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4792                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4793                         table_idx = methodb->table_idx;
4794                 } else {
4795                         table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4796                 }
4797                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4798         } else {
4799                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4800         }
4801         /* The embedded managed resources */
4802         text_offset = assembly->text_rva + assembly->code.index;
4803         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4804         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4805         text_offset += assembly->resources.index;
4806         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4807         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4808         text_offset += assembly->meta_size;
4809         if (assembly->strong_name_size) {
4810                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4811                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4812                 text_offset += assembly->strong_name_size;
4813         }
4814
4815         /* write the section tables and section content */
4816         section = (MonoSectionTable*)(pefile->data + section_start);
4817         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4818                 static const char *section_names [] = {
4819                         ".text", ".rsrc", ".reloc"
4820                 };
4821                 if (!assembly->sections [i].size)
4822                         continue;
4823                 strcpy (section->st_name, section_names [i]);
4824                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4825                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4826                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4827                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4828                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4829                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4830                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4831                 section ++;
4832         }
4833         
4834         checked_write_file (file, pefile->data, pefile->index);
4835         
4836         mono_dynamic_stream_reset (pefile);
4837         
4838         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4839                 if (!assembly->sections [i].size)
4840                         continue;
4841                 
4842                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4843                         g_error ("SetFilePointer returned %d\n", GetLastError ());
4844                 
4845                 switch (i) {
4846                 case MONO_SECTION_TEXT:
4847                         /* patch entry point */
4848                         p = (assembly->code.data + 2);
4849                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4850                         *p++ = (value) & 0xff;
4851                         *p++ = (value >> 8) & 0xff;
4852                         *p++ = (value >> 16) & 0xff;
4853                         *p++ = (value >> 24) & 0xff;
4854                 
4855                         checked_write_file (file, assembly->code.data, assembly->code.index);
4856                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
4857                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4858                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4859                                 
4860
4861                         g_free (assembly->image.raw_metadata);
4862                         break;
4863                 case MONO_SECTION_RELOC: {
4864                         struct {
4865                                 guint32 page_rva;
4866                                 guint32 block_size;
4867                                 guint16 type_and_offset;
4868                                 guint16 term;
4869                         } reloc;
4870                         
4871                         g_assert (sizeof (reloc) == 12);
4872                         
4873                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4874                         reloc.block_size = GUINT32_FROM_LE (12);
4875                         
4876                         /* 
4877                          * the entrypoint is always at the start of the text section 
4878                          * 3 is IMAGE_REL_BASED_HIGHLOW
4879                          * 2 is patch_size_rva - text_rva
4880                          */
4881                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4882                         reloc.term = 0;
4883                         
4884                         checked_write_file (file, &reloc, sizeof (reloc));
4885                         
4886                         break;
4887                 }
4888                 case MONO_SECTION_RSRC:
4889                         if (assembly->win32_res) {
4890
4891                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4892                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4893                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4894                         }
4895                         break;
4896                 default:
4897                         g_assert_not_reached ();
4898                 }
4899         }
4900         
4901         /* check that the file is properly padded */
4902         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4903                 g_error ("SetFilePointer returned %d\n", GetLastError ());
4904         if (! SetEndOfFile (file))
4905                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4906         
4907         mono_dynamic_stream_reset (&assembly->code);
4908         mono_dynamic_stream_reset (&assembly->us);
4909         mono_dynamic_stream_reset (&assembly->blob);
4910         mono_dynamic_stream_reset (&assembly->guid);
4911         string_heap_free (&assembly->sheap);
4912
4913         mono_g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4914         mono_g_hash_table_destroy (assembly->blob_cache);
4915 }
4916
4917 MonoReflectionModule *
4918 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4919 {
4920         char *name;
4921         MonoImage *image;
4922         MonoImageOpenStatus status;
4923         MonoDynamicAssembly *assembly;
4924         guint32 module_count;
4925         MonoImage **new_modules;
4926         
4927         name = mono_string_to_utf8 (fileName);
4928
4929         image = mono_image_open (name, &status);
4930         if (status) {
4931                 MonoException *exc;
4932                 if (status == MONO_IMAGE_ERROR_ERRNO)
4933                         exc = mono_get_exception_file_not_found (fileName);
4934                 else
4935                         exc = mono_get_exception_bad_image_format (name);
4936                 g_free (name);
4937                 mono_raise_exception (exc);
4938         }
4939
4940         g_free (name);
4941
4942         assembly = ab->dynamic_assembly;
4943         image->assembly = (MonoAssembly*)assembly;
4944
4945         module_count = image->assembly->image->module_count;
4946         new_modules = g_new0 (MonoImage *, module_count + 1);
4947
4948         if (image->assembly->image->modules)
4949                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4950         new_modules [module_count] = image;
4951
4952         g_free (image->assembly->image->modules);
4953         image->assembly->image->modules = new_modules;
4954         image->assembly->image->module_count ++;
4955
4956         mono_assembly_load_references (image, &status);
4957         if (status) {
4958                 mono_image_close (image);
4959                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4960         }
4961
4962         return mono_module_get_object (mono_domain_get (), image);
4963 }
4964
4965 /*
4966  * We need to return always the same object for MethodInfo, FieldInfo etc..
4967  * but we need to consider the reflected type.
4968  * type uses a different hash, since it uses custom hash/equal functions.
4969  */
4970
4971 typedef struct {
4972         gpointer item;
4973         MonoClass *refclass;
4974 } ReflectedEntry;
4975
4976 static gboolean
4977 reflected_equal (gconstpointer a, gconstpointer b) {
4978         const ReflectedEntry *ea = a;
4979         const ReflectedEntry *eb = b;
4980
4981         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4982 }
4983
4984 static guint
4985 reflected_hash (gconstpointer a) {
4986         const ReflectedEntry *ea = a;
4987         return GPOINTER_TO_UINT (ea->item);
4988 }
4989
4990 #define CHECK_OBJECT(t,p,k)     \
4991         do {    \
4992                 t _obj; \
4993                 ReflectedEntry e;       \
4994                 e.item = (p);   \
4995                 e.refclass = (k);       \
4996                 mono_domain_lock (domain);      \
4997                 if (!domain->refobject_hash)    \
4998                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
4999                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5000                         mono_domain_unlock (domain);    \
5001                         return _obj;    \
5002                 }       \
5003         } while (0)
5004
5005 #if HAVE_BOEHM_GC
5006 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5007 #else
5008 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5009 #endif
5010
5011 #define CACHE_OBJECT(p,o,k)     \
5012         do {    \
5013                 ReflectedEntry *e = ALLOC_REFENTRY;     \
5014                 e->item = (p);  \
5015                 e->refclass = (k);      \
5016                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5017                 mono_domain_unlock (domain);    \
5018         } while (0)
5019
5020 static void 
5021 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5022 {
5023         /* this is done only once */
5024         mono_domain_lock (domain);
5025         CACHE_OBJECT (assembly, res, NULL);
5026 }
5027
5028 static void
5029 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5030 {
5031         /* this is done only once */
5032         mono_domain_lock (domain);
5033         CACHE_OBJECT (module, res, NULL);
5034 }
5035
5036 void
5037 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5038 {
5039         MonoDynamicImage *image = moduleb->dynamic_image;
5040         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5041         if (!image) {
5042                 /*
5043                  * FIXME: we already created an image in mono_image_basic_init (), but
5044                  * we don't know which module it belongs to, since that is only 
5045                  * determined at assembly save time.
5046                  */
5047                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5048                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5049
5050                 moduleb->module.image = &image->image;
5051                 moduleb->dynamic_image = image;
5052                 register_module (mono_object_domain (moduleb), moduleb, image);
5053         }
5054 }
5055
5056 /*
5057  * mono_assembly_get_object:
5058  * @domain: an app domain
5059  * @assembly: an assembly
5060  *
5061  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5062  */
5063 MonoReflectionAssembly*
5064 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5065 {
5066         static MonoClass *System_Reflection_Assembly;
5067         MonoReflectionAssembly *res;
5068         
5069         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5070         if (!System_Reflection_Assembly)
5071                 System_Reflection_Assembly = mono_class_from_name (
5072                         mono_defaults.corlib, "System.Reflection", "Assembly");
5073         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5074         res->assembly = assembly;
5075
5076         /* FIXME: This is a workaround for 1.1.3 */
5077         if (!strcmp (assembly->aname.name, "__MetadataTypes"))
5078                 res->corlib_internal = TRUE;
5079
5080         CACHE_OBJECT (assembly, res, NULL);
5081         return res;
5082 }
5083
5084
5085
5086 MonoReflectionModule*   
5087 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5088 {
5089         static MonoClass *System_Reflection_Module;
5090         MonoReflectionModule *res;
5091         char* basename;
5092         
5093         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5094         if (!System_Reflection_Module)
5095                 System_Reflection_Module = mono_class_from_name (
5096                         mono_defaults.corlib, "System.Reflection", "Module");
5097         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5098
5099         res->image = image;
5100         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5101
5102         res->fqname    = mono_string_new (domain, image->name);
5103         res->name      = mono_string_new (domain, basename = g_path_get_basename (image->name));
5104         res->scopename = mono_string_new (domain, image->module_name);
5105         
5106         g_free (basename);
5107
5108         if (image->assembly->image == image) {
5109                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5110         } else {
5111                 int i;
5112                 g_assert (image->assembly->image->modules);
5113                 res->token = 0;
5114                 for (i = 0; i < image->assembly->image->module_count; i++) {
5115                         if (image->assembly->image->modules [i] == image)
5116                                 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5117                 }
5118                 g_assert (res->token);
5119         }
5120
5121         mono_image_addref (image);
5122
5123         CACHE_OBJECT (image, res, NULL);
5124         return res;
5125 }
5126
5127 MonoReflectionModule*   
5128 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5129 {
5130         static MonoClass *System_Reflection_Module;
5131         MonoReflectionModule *res;
5132         MonoTableInfo *table;
5133         guint32 cols [MONO_FILE_SIZE];
5134         const char *name;
5135         guint32 i, name_idx;
5136         const char *val;
5137         
5138         if (!System_Reflection_Module)
5139                 System_Reflection_Module = mono_class_from_name (
5140                         mono_defaults.corlib, "System.Reflection", "Module");
5141         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5142
5143         table = &image->tables [MONO_TABLE_FILE];
5144         g_assert (table_index < table->rows);
5145         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5146
5147         res->image = 0;
5148         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5149         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5150
5151         /* Check whenever the row has a corresponding row in the moduleref table */
5152         table = &image->tables [MONO_TABLE_MODULEREF];
5153         for (i = 0; i < table->rows; ++i) {
5154                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5155                 val = mono_metadata_string_heap (image, name_idx);
5156                 if (strcmp (val, name) == 0)
5157                         res->image = image->modules [i];
5158         }
5159
5160         res->fqname    = mono_string_new (domain, name);
5161         res->name      = mono_string_new (domain, name);
5162         res->scopename = mono_string_new (domain, name);
5163         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5164         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5165
5166         return res;
5167 }
5168
5169 static gboolean
5170 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5171 {
5172         if ((t1->type != t2->type) ||
5173             (t1->byref != t2->byref))
5174                 return FALSE;
5175
5176         switch (t1->type) {
5177         case MONO_TYPE_VOID:
5178         case MONO_TYPE_BOOLEAN:
5179         case MONO_TYPE_CHAR:
5180         case MONO_TYPE_I1:
5181         case MONO_TYPE_U1:
5182         case MONO_TYPE_I2:
5183         case MONO_TYPE_U2:
5184         case MONO_TYPE_I4:
5185         case MONO_TYPE_U4:
5186         case MONO_TYPE_I8:
5187         case MONO_TYPE_U8:
5188         case MONO_TYPE_R4:
5189         case MONO_TYPE_R8:
5190         case MONO_TYPE_STRING:
5191         case MONO_TYPE_I:
5192         case MONO_TYPE_U:
5193         case MONO_TYPE_OBJECT:
5194         case MONO_TYPE_TYPEDBYREF:
5195                 return TRUE;
5196         case MONO_TYPE_VALUETYPE:
5197         case MONO_TYPE_CLASS:
5198         case MONO_TYPE_SZARRAY:
5199                 return t1->data.klass == t2->data.klass;
5200         case MONO_TYPE_PTR:
5201                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5202         case MONO_TYPE_ARRAY:
5203                 if (t1->data.array->rank != t2->data.array->rank)
5204                         return FALSE;
5205                 return t1->data.array->eklass == t2->data.array->eklass;
5206         case MONO_TYPE_GENERICINST: {
5207                 int i;
5208                 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5209                         return FALSE;
5210                 if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
5211                         return FALSE;
5212                 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5213                         if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5214                                 return FALSE;
5215                 }
5216                 return TRUE;
5217         }
5218         case MONO_TYPE_VAR:
5219         case MONO_TYPE_MVAR:
5220                 return t1->data.generic_param == t2->data.generic_param;
5221         default:
5222                 g_error ("implement type compare for %0x!", t1->type);
5223                 return FALSE;
5224         }
5225
5226         return FALSE;
5227 }
5228
5229 static guint
5230 mymono_metadata_type_hash (MonoType *t1)
5231 {
5232         guint hash;
5233
5234         hash = t1->type;
5235
5236         hash |= t1->byref << 6; /* do not collide with t1->type values */
5237         switch (t1->type) {
5238         case MONO_TYPE_VALUETYPE:
5239         case MONO_TYPE_CLASS:
5240         case MONO_TYPE_SZARRAY:
5241                 /* check if the distribution is good enough */
5242                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5243         case MONO_TYPE_PTR:
5244                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5245         }
5246         return hash;
5247 }
5248
5249 static MonoReflectionGenericClass*
5250 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5251 {
5252         static MonoClass *System_Reflection_MonoGenericClass;
5253         MonoReflectionGenericClass *res;
5254         MonoGenericClass *gclass;
5255         MonoClass *gklass;
5256
5257         if (!System_Reflection_MonoGenericClass) {
5258                 System_Reflection_MonoGenericClass = mono_class_from_name (
5259                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5260                 g_assert (System_Reflection_MonoGenericClass);
5261         }
5262
5263         gclass = geninst->data.generic_class;
5264         gklass = mono_class_from_mono_type (gclass->generic_type);
5265
5266         mono_class_init (gclass->klass);
5267
5268         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5269
5270         res->type.type = geninst;
5271         if (gklass->wastypebuilder && gklass->reflection_info)
5272                 res->generic_type = gklass->reflection_info;
5273         else
5274                 res->generic_type = mono_type_get_object (domain, gclass->generic_type);
5275
5276         return res;
5277 }
5278
5279 /*
5280  * mono_type_get_object:
5281  * @domain: an app domain
5282  * @type: a type
5283  *
5284  * Return an System.MonoType object representing the type @type.
5285  */
5286 MonoReflectionType*
5287 mono_type_get_object (MonoDomain *domain, MonoType *type)
5288 {
5289         MonoReflectionType *res;
5290         MonoClass *klass = mono_class_from_mono_type (type);
5291
5292         mono_domain_lock (domain);
5293         if (!domain->type_hash)
5294                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
5295                                 (GCompareFunc)mymono_metadata_type_equal);
5296         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5297                 mono_domain_unlock (domain);
5298                 return res;
5299         }
5300         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5301                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5302                 mono_g_hash_table_insert (domain->type_hash, type, res);
5303                 mono_domain_unlock (domain);
5304                 return res;
5305         }
5306         if (klass->reflection_info && !klass->wastypebuilder) {
5307                 /* g_assert_not_reached (); */
5308                 /* should this be considered an error condition? */
5309                 if (!type->byref) {
5310                         mono_domain_unlock (domain);
5311                         return klass->reflection_info;
5312                 }
5313         }
5314         mono_class_init (klass);
5315         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5316         res->type = type;
5317         mono_g_hash_table_insert (domain->type_hash, type, res);
5318         mono_domain_unlock (domain);
5319         return res;
5320 }
5321
5322 /*
5323  * mono_method_get_object:
5324  * @domain: an app domain
5325  * @method: a method
5326  * @refclass: the reflected type (can be NULL)
5327  *
5328  * Return an System.Reflection.MonoMethod object representing the method @method.
5329  */
5330 MonoReflectionMethod*
5331 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5332 {
5333         /*
5334          * We use the same C representation for methods and constructors, but the type 
5335          * name in C# is different.
5336          */
5337         const char *cname;
5338         MonoClass *klass;
5339         MonoReflectionMethod *ret;
5340
5341         if (!refclass)
5342                 refclass = method->klass;
5343
5344         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5345         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5346                 cname = "MonoCMethod";
5347         else
5348                 cname = "MonoMethod";
5349         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5350
5351         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5352         ret->method = method;
5353         ret->name = mono_string_new (domain, method->name);
5354         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5355         CACHE_OBJECT (method, ret, refclass);
5356         return ret;
5357 }
5358
5359 /*
5360  * mono_field_get_object:
5361  * @domain: an app domain
5362  * @klass: a type
5363  * @field: a field
5364  *
5365  * Return an System.Reflection.MonoField object representing the field @field
5366  * in class @klass.
5367  */
5368 MonoReflectionField*
5369 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5370 {
5371         MonoReflectionField *res;
5372         MonoClass *oklass;
5373
5374         CHECK_OBJECT (MonoReflectionField *, field, klass);
5375         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5376         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5377         res->klass = klass;
5378         res->field = field;
5379         res->name = mono_string_new (domain, field->name);
5380         if (field->generic_info)
5381                 res->attrs = field->generic_info->generic_type->attrs;
5382         else
5383                 res->attrs = field->type->attrs;
5384         res->type = mono_type_get_object (domain, field->type);
5385         CACHE_OBJECT (field, res, klass);
5386         return res;
5387 }
5388
5389 /*
5390  * mono_property_get_object:
5391  * @domain: an app domain
5392  * @klass: a type
5393  * @property: a property
5394  *
5395  * Return an System.Reflection.MonoProperty object representing the property @property
5396  * in class @klass.
5397  */
5398 MonoReflectionProperty*
5399 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5400 {
5401         MonoReflectionProperty *res;
5402         MonoClass *oklass;
5403
5404         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5405         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5406         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5407         res->klass = klass;
5408         res->property = property;
5409         CACHE_OBJECT (property, res, klass);
5410         return res;
5411 }
5412
5413 /*
5414  * mono_event_get_object:
5415  * @domain: an app domain
5416  * @klass: a type
5417  * @event: a event
5418  *
5419  * Return an System.Reflection.MonoEvent object representing the event @event
5420  * in class @klass.
5421  */
5422 MonoReflectionEvent*
5423 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5424 {
5425         MonoReflectionEvent *res;
5426         MonoClass *oklass;
5427
5428         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5429         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5430         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5431         res->klass = klass;
5432         res->event = event;
5433         CACHE_OBJECT (event, res, klass);
5434         return res;
5435 }
5436
5437 /*
5438  * mono_param_get_objects:
5439  * @domain: an app domain
5440  * @method: a method
5441  *
5442  * Return an System.Reflection.ParameterInfo array object representing the parameters
5443  * in the method @method.
5444  */
5445 MonoArray*
5446 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5447 {
5448         static MonoClass *System_Reflection_ParameterInfo;
5449         MonoArray *res = NULL;
5450         MonoReflectionMethod *member = NULL;
5451         MonoReflectionParameter *param = NULL;
5452         char **names, **blobs = NULL;
5453         MonoObject *dbnull = mono_get_dbnull_object (domain);
5454         MonoMarshalSpec **mspecs;
5455         int i;
5456
5457         if (!System_Reflection_ParameterInfo)
5458                 System_Reflection_ParameterInfo = mono_class_from_name (
5459                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5460         
5461         if (!method->signature->param_count)
5462                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5463
5464         /* Note: the cache is based on the address of the signature into the method
5465          * since we already cache MethodInfos with the method as keys.
5466          */
5467         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5468
5469         member = mono_method_get_object (domain, method, NULL);
5470         names = g_new (char *, method->signature->param_count);
5471         mono_method_get_param_names (method, (const char **) names);
5472
5473         mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5474         mono_method_get_marshal_info (method, mspecs);
5475
5476         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5477         for (i = 0; i < method->signature->param_count; ++i) {
5478                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5479                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5480                 param->MemberImpl = (MonoObject*)member;
5481                 param->NameImpl = mono_string_new (domain, names [i]);
5482                 param->PositionImpl = i;
5483                 param->AttrsImpl = method->signature->params [i]->attrs;
5484
5485                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5486                         param->DefaultValueImpl = dbnull;
5487                 } else {
5488                         MonoType *type = param->ClassImpl->type;
5489
5490                         if (!blobs) {
5491                                 blobs = g_new0 (char *, method->signature->param_count);
5492                                 get_default_param_value_blobs (method, blobs); 
5493                         }
5494
5495                         param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5496
5497                         if (!param->DefaultValueImpl) {
5498                                 param->DefaultValueImpl = dbnull;
5499                         }
5500                 }
5501
5502                 if (mspecs [i + 1])
5503                         param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5504                 
5505                 mono_array_set (res, gpointer, i, param);
5506         }
5507         g_free (names);
5508         g_free (blobs);
5509
5510         for (i = method->signature->param_count; i >= 0; i--)
5511                 if (mspecs [i])
5512                         mono_metadata_free_marshal_spec (mspecs [i]);
5513         g_free (mspecs);
5514         
5515         CACHE_OBJECT (&(method->signature), res, NULL);
5516         return res;
5517 }
5518
5519 /*
5520  * mono_method_body_get_object:
5521  * @domain: an app domain
5522  * @method: a method
5523  *
5524  * Return an System.Reflection.MethodBody object representing the method @method.
5525  */
5526 MonoReflectionMethodBody*
5527 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5528 {
5529         static MonoClass *System_Reflection_MethodBody = NULL;
5530         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5531         MonoReflectionMethodBody *ret;
5532         MonoMethodNormal *mn;
5533         MonoMethodHeader *header;
5534         int i;
5535
5536         if (!System_Reflection_MethodBody)
5537                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5538         if (!System_Reflection_LocalVariableInfo)
5539                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5540
5541         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5542
5543         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5544             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5545                 return NULL;
5546         mn = (MonoMethodNormal *)method;
5547         header = mono_method_get_header (method);
5548
5549         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5550         /* FIXME: Other fields */
5551         ret->init_locals = header->init_locals;
5552         ret->max_stack = header->max_stack;
5553         ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5554         memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5555         ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5556         for (i = 0; i < header->num_locals; ++i) {
5557                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5558                 info->local_type = mono_type_get_object (domain, header->locals [i]);
5559                 info->is_pinned = header->locals [i]->pinned;
5560                 info->local_index = 0;
5561         }
5562                 
5563         CACHE_OBJECT (method, ret, NULL);
5564         return ret;
5565 }
5566
5567 MonoObject *
5568 mono_get_dbnull_object (MonoDomain *domain)
5569 {
5570         MonoObject *obj;
5571         MonoClass *klass;
5572         static MonoClassField *dbnull_value_field = NULL;
5573         
5574         if (!dbnull_value_field) {
5575                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5576                 mono_class_init (klass);
5577                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5578                 g_assert (dbnull_value_field);
5579         }
5580         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5581         g_assert (obj);
5582         return obj;
5583 }
5584
5585
5586 static void
5587 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5588 {
5589         guint32 param_index, i, lastp, crow = 0;
5590         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5591         gint32 idx = -1;
5592
5593         MonoClass *klass = method->klass;
5594         MonoImage *image = klass->image;
5595         MonoMethodSignature *methodsig = method->signature;
5596
5597         MonoTableInfo *constt;
5598         MonoTableInfo *methodt;
5599         MonoTableInfo *paramt;
5600
5601         if (!methodsig->param_count)
5602                 return;
5603
5604         if (klass->generic_class) {
5605                 return; /* FIXME - ??? */
5606         }
5607
5608         mono_class_init (klass);
5609
5610         if (klass->image->dynamic) {
5611                 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5612                 if (aux && aux->param_defaults)
5613                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5614                 return;
5615         }
5616
5617         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5618         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5619         constt = &image->tables [MONO_TABLE_CONSTANT];
5620
5621         for (i = 0; i < klass->method.count; ++i) {
5622                 if (method == klass->methods [i]) {
5623                         idx = klass->method.first + i;
5624                         break;
5625                 }
5626         }
5627
5628         g_assert (idx != -1);
5629
5630         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5631         if (idx + 1 < methodt->rows)
5632                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5633         else
5634                 lastp = paramt->rows + 1;
5635
5636         for (i = param_index; i < lastp; ++i) {
5637                 guint32 paramseq;
5638
5639                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5640                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5641
5642                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5643                         continue;
5644
5645                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5646                 if (!crow) {
5647                         continue;
5648                 }
5649         
5650                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5651                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5652         }
5653
5654         return;
5655 }
5656
5657 static MonoObject *
5658 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5659 {
5660         void *retval;
5661         MonoClass *klass;
5662         MonoObject *object;
5663
5664         if (!blob)
5665                 return NULL;
5666         
5667         klass = mono_class_from_mono_type (type);
5668         if (klass->valuetype) {
5669                 object = mono_object_new (domain, klass);
5670                 retval = ((gchar *) object + sizeof (MonoObject));
5671         } else {
5672                 retval = &object;
5673         }
5674                         
5675         if (!mono_get_constant_value_from_blob (domain, type->type,  blob, retval))
5676                 return object;
5677         else
5678                 return NULL;
5679 }
5680
5681 static int
5682 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5683         int found_sep;
5684         char *s;
5685
5686         memset (assembly, 0, sizeof (MonoAssemblyName));
5687         assembly->name = p;
5688         assembly->culture = "";
5689         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5690
5691         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5692                 p++;
5693         found_sep = 0;
5694         while (g_ascii_isspace (*p) || *p == ',') {
5695                 *p++ = 0;
5696                 found_sep = 1;
5697                 continue;
5698         }
5699         /* failed */
5700         if (!found_sep)
5701                 return 1;
5702         while (*p) {
5703                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5704                         p += 8;
5705                         assembly->major = strtoul (p, &s, 10);
5706                         if (s == p || *s != '.')
5707                                 return 1;
5708                         p = ++s;
5709                         assembly->minor = strtoul (p, &s, 10);
5710                         if (s == p || *s != '.')
5711                                 return 1;
5712                         p = ++s;
5713                         assembly->build = strtoul (p, &s, 10);
5714                         if (s == p || *s != '.')
5715                                 return 1;
5716                         p = ++s;
5717                         assembly->revision = strtoul (p, &s, 10);
5718                         if (s == p)
5719                                 return 1;
5720                         p = s;
5721                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5722                         p += 8;
5723                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5724                                 assembly->culture = "";
5725                                 p += 7;
5726                         } else {
5727                                 assembly->culture = p;
5728                                 while (*p && *p != ',') {
5729                                         p++;
5730                                 }
5731                         }
5732                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5733                         p += 15;
5734                         if (strncmp (p, "null", 4) == 0) {
5735                                 p += 4;
5736                         } else {
5737                                 int len;
5738                                 gchar *start = p;
5739                                 while (*p && *p != ',') {
5740                                         p++;
5741                                 }
5742                                 len = (p - start + 1);
5743                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5744                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5745                                 g_strlcpy (assembly->public_key_token, start, len);
5746                         }
5747                 } else {
5748                         while (*p && *p != ',')
5749                                 p++;
5750                 }
5751                 found_sep = 0;
5752                 while (g_ascii_isspace (*p) || *p == ',') {
5753                         *p++ = 0;
5754                         found_sep = 1;
5755                         continue;
5756                 }
5757                 /* failed */
5758                 if (!found_sep)
5759                         return 1;
5760         }
5761
5762         return 0;
5763 }
5764
5765 /*
5766  * mono_reflection_parse_type:
5767  * @name: type name
5768  *
5769  * Parse a type name as accepted by the GetType () method and output the info
5770  * extracted in the info structure.
5771  * the name param will be mangled, so, make a copy before passing it to this function.
5772  * The fields in info will be valid until the memory pointed to by name is valid.
5773  *
5774  * See also mono_type_get_name () below.
5775  *
5776  * Returns: 0 on parse error.
5777  */
5778 int
5779 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5780
5781         char *start, *p, *w, *last_point, *startn;
5782         int in_modifiers = 0;
5783         int isbyref = 0, rank;
5784
5785         start = p = w = name;
5786
5787         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5788         info->name = info->name_space = NULL;
5789         info->nested = NULL;
5790         info->modifiers = NULL;
5791
5792         /* last_point separates the namespace from the name */
5793         last_point = NULL;
5794
5795         while (*p) {
5796                 switch (*p) {
5797                 case '+':
5798                         *p = 0; /* NULL terminate the name */
5799                         startn = p + 1;
5800                         info->nested = g_list_append (info->nested, startn);
5801                         /* we have parsed the nesting namespace + name */
5802                         if (info->name)
5803                                 break;
5804                         if (last_point) {
5805                                 info->name_space = start;
5806                                 *last_point = 0;
5807                                 info->name = last_point + 1;
5808                         } else {
5809                                 info->name_space = (char *)"";
5810                                 info->name = start;
5811                         }
5812                         break;
5813                 case '.':
5814                         last_point = w;
5815                         break;
5816                 case '\\':
5817                         ++p;
5818                         break;
5819                 case '&':
5820                 case '*':
5821                 case '[':
5822                 case ',':
5823                         in_modifiers = 1;
5824                         break;
5825                 default:
5826                         break;
5827                 }
5828                 if (in_modifiers)
5829                         break;
5830                 *w++ = *p++;
5831         }
5832         
5833         if (!info->name) {
5834                 if (last_point) {
5835                         info->name_space = start;
5836                         *last_point = 0;
5837                         info->name = last_point + 1;
5838                 } else {
5839                         info->name_space = (char *)"";
5840                         info->name = start;
5841                 }
5842         }
5843         while (*p) {
5844                 switch (*p) {
5845                 case '&':
5846                         if (isbyref) /* only one level allowed by the spec */
5847                                 return 0;
5848                         isbyref = 1;
5849                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5850                         *p++ = 0;
5851                         break;
5852                 case '*':
5853                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5854                         *p++ = 0;
5855                         break;
5856                 case '[':
5857                         rank = 1;
5858                         *p++ = 0;
5859                         while (*p) {
5860                                 if (*p == ']')
5861                                         break;
5862                                 if (*p == ',')
5863                                         rank++;
5864                                 else if (*p != '*') /* '*' means unknown lower bound */
5865                                         return 0;
5866                                 ++p;
5867                         }
5868                         if (*p++ != ']')
5869                                 return 0;
5870                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5871                         break;
5872                 case ',':
5873                         *p++ = 0;
5874                         while (*p) {
5875                                 if (g_ascii_isspace (*p)) {
5876                                         ++p;
5877                                         continue;
5878                                 }
5879                                 break;
5880                         }
5881                         if (!*p)
5882                                 return 0; /* missing assembly name */
5883                         if (!assembly_name_to_aname (&info->assembly, p))
5884                                 return 0;
5885                         break;
5886                 default:
5887                         return 0;
5888                         break;
5889                 }
5890                 if (info->assembly.name)
5891                         break;
5892         }
5893         *w = 0; /* terminate class name */
5894         if (!info->name || !*info->name)
5895                 return 0;
5896         /* add other consistency checks */
5897         return 1;
5898 }
5899
5900 static MonoType*
5901 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5902 {
5903         MonoClass *klass;
5904         GList *mod;
5905         int modval;
5906         
5907         if (!image)
5908                 image = mono_defaults.corlib;
5909
5910         if (ignorecase)
5911                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5912         else
5913                 klass = mono_class_from_name (image, info->name_space, info->name);
5914         if (!klass)
5915                 return NULL;
5916         for (mod = info->nested; mod; mod = mod->next) {
5917                 GList *nested;
5918
5919                 mono_class_init (klass);
5920                 nested = klass->nested_classes;
5921                 klass = NULL;
5922                 while (nested) {
5923                         klass = nested->data;
5924                         if (ignorecase) {
5925                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5926                                         break;
5927                         } else {
5928                                 if (strcmp (klass->name, mod->data) == 0)
5929                                         break;
5930                         }
5931                         klass = NULL;
5932                         nested = nested->next;
5933                 }
5934                 if (!klass)
5935                         break;
5936         }
5937         if (!klass)
5938                 return NULL;
5939         mono_class_init (klass);
5940         for (mod = info->modifiers; mod; mod = mod->next) {
5941                 modval = GPOINTER_TO_UINT (mod->data);
5942                 if (!modval) { /* byref: must be last modifier */
5943                         return &klass->this_arg;
5944                 } else if (modval == -1) {
5945                         klass = mono_ptr_class_get (&klass->byval_arg);
5946                 } else { /* array rank */
5947                         klass = mono_array_class_get (klass, modval);
5948                 }
5949                 mono_class_init (klass);
5950         }
5951
5952         return &klass->byval_arg;
5953 }
5954
5955 /*
5956  * mono_reflection_get_type:
5957  * @image: a metadata context
5958  * @info: type description structure
5959  * @ignorecase: flag for case-insensitive string compares
5960  * @type_resolve: whenever type resolve was already tried
5961  *
5962  * Build a MonoType from the type description in @info.
5963  * 
5964  */
5965
5966 MonoType*
5967 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5968 {
5969         MonoType *type;
5970         MonoReflectionAssembly *assembly;
5971         GString *fullName;
5972         GList *mod;
5973
5974         type = mono_reflection_get_type_internal (image, info, ignorecase);
5975         if (type)
5976                 return type;
5977         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5978                 return NULL;
5979
5980         if (type_resolve) {
5981                 if (*type_resolve) 
5982                         return NULL;
5983                 else
5984                         *type_resolve = TRUE;
5985         }
5986         
5987         /* Reconstruct the type name */
5988         fullName = g_string_new ("");
5989         if (info->name_space && (info->name_space [0] != '\0'))
5990                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5991         else
5992                 g_string_printf (fullName, info->name);
5993         for (mod = info->nested; mod; mod = mod->next)
5994                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5995
5996         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5997         if (assembly) {
5998                 if (assembly->assembly->dynamic) {
5999                         /* Enumerate all modules */
6000                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6001                         int i;
6002
6003                         type = NULL;
6004                         if (abuilder->modules) {
6005                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6006                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6007                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6008                                         if (type)
6009                                                 break;
6010                                 }
6011                         }
6012
6013                         if (!type && abuilder->loaded_modules) {
6014                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6015                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6016                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6017                                         if (type)
6018                                                 break;
6019                                 }
6020                         }
6021                 }
6022                 else
6023                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
6024                                                                                                           info, ignorecase);
6025         }
6026         g_string_free (fullName, TRUE);
6027         return type;
6028 }
6029
6030 /*
6031  * mono_reflection_type_from_name:
6032  * @name: type name.
6033  * @image: a metadata context (can be NULL).
6034  *
6035  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6036  * it defaults to get the type from @image or, if @image is NULL or loading
6037  * from it fails, uses corlib.
6038  * 
6039  */
6040 MonoType*
6041 mono_reflection_type_from_name (char *name, MonoImage *image)
6042 {
6043         MonoType *type;
6044         MonoTypeNameParse info;
6045         MonoAssembly *assembly;
6046         char *tmp;
6047         gboolean type_resolve = FALSE;
6048
6049         /* Make a copy since parse_type modifies its argument */
6050         tmp = g_strdup (name);
6051         
6052         /*g_print ("requested type %s\n", str);*/
6053         if (!mono_reflection_parse_type (tmp, &info)) {
6054                 g_free (tmp);
6055                 g_list_free (info.modifiers);
6056                 g_list_free (info.nested);
6057                 return NULL;
6058         }
6059
6060         if (info.assembly.name) {
6061                 assembly = mono_assembly_loaded (&info.assembly);
6062                 if (!assembly) {
6063                         /* then we must load the assembly ourselve - see #60439 */
6064                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6065                         if (!assembly) {
6066                                 g_free (tmp);
6067                                 g_list_free (info.modifiers);
6068                                 g_list_free (info.nested);
6069                                 return NULL;
6070                         }
6071                 }
6072                 image = assembly->image;
6073         } else if (image == NULL) {
6074                 image = mono_defaults.corlib;
6075         }
6076
6077         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6078         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6079                 image = mono_defaults.corlib;
6080                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6081         }
6082
6083         g_free (tmp);
6084         g_list_free (info.modifiers);
6085         g_list_free (info.nested);
6086         return type;
6087 }
6088
6089 /*
6090  * mono_reflection_get_token:
6091  *
6092  *   Return the metadata token of OBJ which should be an object
6093  * representing a metadata element.
6094  */
6095 guint32
6096 mono_reflection_get_token (MonoObject *obj)
6097 {
6098         MonoClass *klass;
6099         guint32 token = 0;
6100
6101         klass = obj->vtable->klass;
6102
6103         if (strcmp (klass->name, "MethodBuilder") == 0) {
6104                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6105
6106                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6107         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6108                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6109
6110                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6111         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6112                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6113                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6114                 if (tb->generic_params) {
6115                         g_assert_not_reached ();
6116                 } else {
6117                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6118                 }
6119         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6120                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6121                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6122         } else if (strcmp (klass->name, "MonoType") == 0) {
6123                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6124                 token = mono_class_from_mono_type (tb->type)->type_token;
6125         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6126                         strcmp (klass->name, "MonoMethod") == 0) {
6127                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6128                 if (m->method->signature->is_inflated) {
6129                         g_assert_not_reached ();
6130                 } else if (m->method->signature->generic_param_count) {
6131                         g_assert_not_reached ();
6132                 } else if (m->method->klass->generic_class) {
6133                         g_assert_not_reached ();
6134                 } else {
6135                         token = m->method->token;
6136                 }
6137         } else if (strcmp (klass->name, "MonoField") == 0) {
6138                 MonoReflectionField *f = (MonoReflectionField*)obj;
6139
6140                 token = mono_class_get_field_token (f->field);
6141         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6142                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6143
6144                 token = mono_class_get_property_token (p->property);
6145         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6146                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6147
6148                 token = mono_class_get_event_token (p->event);
6149         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6150                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6151
6152                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6153         } else if (strcmp (klass->name, "Module") == 0) {
6154                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6155
6156                 token = m->token;
6157         } else if (strcmp (klass->name, "Assembly") == 0) {
6158                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6159         } else {
6160                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6161                 MonoException *ex = mono_get_exception_not_implemented (msg);
6162                 g_free (msg);
6163                 mono_raise_exception (ex);
6164         }
6165
6166         return token;
6167 }
6168
6169 static void*
6170 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6171 {
6172         int slen, type = t->type;
6173 handle_enum:
6174         switch (type) {
6175         case MONO_TYPE_U1:
6176         case MONO_TYPE_I1:
6177         case MONO_TYPE_BOOLEAN: {
6178                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6179                 *bval = *p;
6180                 *end = p + 1;
6181                 return bval;
6182         }
6183         case MONO_TYPE_CHAR:
6184         case MONO_TYPE_U2:
6185         case MONO_TYPE_I2: {
6186                 guint16 *val = g_malloc (sizeof (guint16));
6187                 *val = read16 (p);
6188                 *end = p + 2;
6189                 return val;
6190         }
6191 #if SIZEOF_VOID_P == 4
6192         case MONO_TYPE_U:
6193         case MONO_TYPE_I:
6194 #endif
6195         case MONO_TYPE_R4:
6196         case MONO_TYPE_U4:
6197         case MONO_TYPE_I4: {
6198                 guint32 *val = g_malloc (sizeof (guint32));
6199                 *val = read32 (p);
6200                 *end = p + 4;
6201                 return val;
6202         }
6203 #if SIZEOF_VOID_P == 8
6204         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6205         case MONO_TYPE_I:
6206 #endif
6207         case MONO_TYPE_R8:
6208         case MONO_TYPE_U8:
6209         case MONO_TYPE_I8: {
6210                 guint64 *val = g_malloc (sizeof (guint64));
6211                 *val = read64 (p);
6212                 *end = p + 8;
6213                 return val;
6214         }
6215         case MONO_TYPE_VALUETYPE:
6216                 if (t->data.klass->enumtype) {
6217                         type = t->data.klass->enum_basetype->type;
6218                         goto handle_enum;
6219                 } else {
6220                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6221                 }
6222                 break;
6223         case MONO_TYPE_STRING:
6224                 if (*p == (char)0xFF) {
6225                         *end = p + 1;
6226                         return NULL;
6227                 }
6228                 slen = mono_metadata_decode_value (p, &p);
6229                 *end = p + slen;
6230                 return mono_string_new_len (mono_domain_get (), p, slen);
6231         case MONO_TYPE_CLASS: {
6232                 char *n;
6233                 MonoType *t;
6234                 if (*p == (char)0xFF) {
6235                         *end = p + 1;
6236                         return NULL;
6237                 }
6238 handle_type:
6239                 slen = mono_metadata_decode_value (p, &p);
6240                 n = g_memdup (p, slen + 1);
6241                 n [slen] = 0;
6242                 t = mono_reflection_type_from_name (n, image);
6243                 if (!t)
6244                         g_warning ("Cannot load type '%s'", n);
6245                 g_free (n);
6246                 *end = p + slen;
6247                 if (t)
6248                         return mono_type_get_object (mono_domain_get (), t);
6249                 else
6250                         return NULL;
6251         }
6252         case MONO_TYPE_OBJECT: {
6253                 char subt = *p++;
6254                 MonoObject *obj;
6255                 MonoClass *subc = NULL;
6256                 void *val;
6257
6258                 if (subt == 0x50) {
6259                         goto handle_type;
6260                 } else if (subt == 0x0E) {
6261                         type = MONO_TYPE_STRING;
6262                         goto handle_enum;
6263                 } else if (subt == 0x55) {
6264                         char *n;
6265                         MonoType *t;
6266                         slen = mono_metadata_decode_value (p, &p);
6267                         n = g_memdup (p, slen + 1);
6268                         n [slen] = 0;
6269                         t = mono_reflection_type_from_name (n, image);
6270                         if (!t)
6271                                 g_warning ("Cannot load type '%s'", n);
6272                         g_free (n);
6273                         p += slen;
6274                         subc = mono_class_from_mono_type (t);
6275                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6276                         MonoType simple_type = {{0}};
6277                         simple_type.type = subt;
6278                         subc = mono_class_from_mono_type (&simple_type);
6279                 } else {
6280                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6281                 }
6282                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6283                 obj = mono_object_new (mono_domain_get (), subc);
6284                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6285                 g_free (val);
6286                 return obj;
6287         }
6288         case MONO_TYPE_SZARRAY: {
6289                 MonoArray *arr;
6290                 guint32 i, alen, basetype;
6291                 alen = read32 (p);
6292                 p += 4;
6293                 if (alen == 0xffffffff) {
6294                         *end = p;
6295                         return NULL;
6296                 }
6297                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6298                 basetype = t->data.klass->byval_arg.type;
6299                 switch (basetype)
6300                 {
6301                         case MONO_TYPE_U1:
6302                         case MONO_TYPE_I1:
6303                         case MONO_TYPE_BOOLEAN:
6304                                 for (i = 0; i < alen; i++) {
6305                                         MonoBoolean val = *p++;
6306                                         mono_array_set (arr, MonoBoolean, i, val);
6307                                 }
6308                                 break;
6309                         case MONO_TYPE_CHAR:
6310                         case MONO_TYPE_U2:
6311                         case MONO_TYPE_I2:
6312                                 for (i = 0; i < alen; i++) {
6313                                         guint16 val = read16 (p);
6314                                         mono_array_set (arr, guint16, i, val);
6315                                         p += 2;
6316                                 }
6317                                 break;
6318                         case MONO_TYPE_R4:
6319                         case MONO_TYPE_U4:
6320                         case MONO_TYPE_I4:
6321                                 for (i = 0; i < alen; i++) {
6322                                         guint32 val = read32 (p);
6323                                         mono_array_set (arr, guint32, i, val);
6324                                         p += 4;
6325                                 }
6326                                 break;
6327                         case MONO_TYPE_R8:
6328                         case MONO_TYPE_U8:
6329                         case MONO_TYPE_I8:
6330                                 for (i = 0; i < alen; i++) {
6331                                         guint64 val = read64 (p);
6332                                         mono_array_set (arr, guint64, i, val);
6333                                         p += 8;
6334                                 }
6335                                 break;
6336                         case MONO_TYPE_CLASS:
6337                         case MONO_TYPE_OBJECT:
6338                         case MONO_TYPE_STRING:
6339                                 for (i = 0; i < alen; i++) {
6340                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6341                                         mono_array_set (arr, gpointer, i, item);
6342                                 }
6343                                 break;
6344                         default:
6345                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6346                 }
6347                 *end=p;
6348                 return arr;
6349         }
6350         default:
6351                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6352         }
6353         return NULL;
6354 }
6355
6356 static gboolean
6357 type_is_reference (MonoType *type)
6358 {
6359         switch (type->type) {
6360         case MONO_TYPE_BOOLEAN:
6361         case MONO_TYPE_CHAR:
6362         case MONO_TYPE_U:
6363         case MONO_TYPE_I:
6364         case MONO_TYPE_U1:
6365         case MONO_TYPE_I1:
6366         case MONO_TYPE_U2:
6367         case MONO_TYPE_I2:
6368         case MONO_TYPE_U4:
6369         case MONO_TYPE_I4:
6370         case MONO_TYPE_U8:
6371         case MONO_TYPE_I8:
6372         case MONO_TYPE_R8:
6373         case MONO_TYPE_R4:
6374         case MONO_TYPE_VALUETYPE:
6375                 return FALSE;
6376         default:
6377                 return TRUE;
6378         }
6379 }
6380
6381 static void
6382 free_param_data (MonoMethodSignature *sig, void **params) {
6383         int i;
6384         for (i = 0; i < sig->param_count; ++i) {
6385                 if (!type_is_reference (sig->params [i]))
6386                         g_free (params [i]);
6387         }
6388 }
6389
6390 /*
6391  * Find the method index in the metadata methodDef table.
6392  * Later put these three helper methods in metadata and export them.
6393  */
6394 static guint32
6395 find_method_index (MonoMethod *method) {
6396         MonoClass *klass = method->klass;
6397         int i;
6398
6399         for (i = 0; i < klass->method.count; ++i) {
6400                 if (method == klass->methods [i])
6401                         return klass->method.first + 1 + i;
6402         }
6403         return 0;
6404 }
6405
6406 /*
6407  * Find the field index in the metadata FieldDef table.
6408  */
6409 static guint32
6410 find_field_index (MonoClass *klass, MonoClassField *field) {
6411         int i;
6412
6413         for (i = 0; i < klass->field.count; ++i) {
6414                 if (field == &klass->fields [i])
6415                         return klass->field.first + 1 + i;
6416         }
6417         return 0;
6418 }
6419
6420 /*
6421  * Find the property index in the metadata Property table.
6422  */
6423 static guint32
6424 find_property_index (MonoClass *klass, MonoProperty *property) {
6425         int i;
6426
6427         for (i = 0; i < klass->property.count; ++i) {
6428                 if (property == &klass->properties [i])
6429                         return klass->property.first + 1 + i;
6430         }
6431         return 0;
6432 }
6433
6434 /*
6435  * Find the event index in the metadata Event table.
6436  */
6437 static guint32
6438 find_event_index (MonoClass *klass, MonoEvent *event) {
6439         int i;
6440
6441         for (i = 0; i < klass->event.count; ++i) {
6442                 if (event == &klass->events [i])
6443                         return klass->event.first + 1 + i;
6444         }
6445         return 0;
6446 }
6447
6448 static MonoObject*
6449 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6450 {
6451         const char *p = data;
6452         const char *named;
6453         guint32 i, j, num_named;
6454         MonoObject *attr;
6455         void **params;
6456
6457         mono_class_init (method->klass);
6458
6459         if (len == 0) {
6460                 attr = mono_object_new (mono_domain_get (), method->klass);
6461                 mono_runtime_invoke (method, attr, NULL, NULL);
6462                 return attr;
6463         }
6464
6465         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6466                 return NULL;
6467
6468         /*g_print ("got attr %s\n", method->klass->name);*/
6469         
6470         params = g_new (void*, method->signature->param_count);
6471
6472         /* skip prolog */
6473         p += 2;
6474         for (i = 0; i < method->signature->param_count; ++i) {
6475                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6476         }
6477
6478         named = p;
6479         attr = mono_object_new (mono_domain_get (), method->klass);
6480         mono_runtime_invoke (method, attr, params, NULL);
6481         free_param_data (method->signature, params);
6482         g_free (params);
6483         num_named = read16 (named);
6484         named += 2;
6485         for (j = 0; j < num_named; j++) {
6486                 gint name_len;
6487                 char *name, named_type, data_type;
6488                 named_type = *named++;
6489                 data_type = *named++; /* type of data */
6490                 if (data_type == 0x55) {
6491                         gint type_len;
6492                         char *type_name;
6493                         type_len = mono_metadata_decode_blob_size (named, &named);
6494                         type_name = g_malloc (type_len + 1);
6495                         memcpy (type_name, named, type_len);
6496                         type_name [type_len] = 0;
6497                         named += type_len;
6498                         /* FIXME: lookup the type and check type consistency */
6499                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6500                         /* this seems to be the type of the element of the array */
6501                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6502                         named++;
6503                 }
6504                 name_len = mono_metadata_decode_blob_size (named, &named);
6505                 name = g_malloc (name_len + 1);
6506                 memcpy (name, named, name_len);
6507                 name [name_len] = 0;
6508                 named += name_len;
6509                 if (named_type == 0x53) {
6510                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6511                         void *val = load_cattr_value (image, field->type, named, &named);
6512                         mono_field_set_value (attr, field, val);
6513                         if (!type_is_reference (field->type))
6514                                 g_free (val);
6515                 } else if (named_type == 0x54) {
6516                         MonoProperty *prop;
6517                         void *pparams [1];
6518                         MonoType *prop_type;
6519
6520                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6521                         /* can we have more that 1 arg in a custom attr named property? */
6522                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6523                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6524                         mono_property_set_value (prop, attr, pparams, NULL);
6525                         if (!type_is_reference (prop_type))
6526                                 g_free (pparams [0]);
6527                 }
6528                 g_free (name);
6529         }
6530
6531         return attr;
6532 }
6533
6534 MonoArray*
6535 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6536 {
6537         MonoArray *result;
6538         MonoClass *klass;
6539         MonoObject *attr;
6540         int i;
6541
6542         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6543         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6544         for (i = 0; i < cinfo->num_attrs; ++i) {
6545                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6546                 mono_array_set (result, gpointer, i, attr);
6547         }
6548         return result;
6549 }
6550
6551 MonoCustomAttrInfo*
6552 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6553 {
6554         guint32 mtoken, i, len;
6555         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6556         MonoTableInfo *ca;
6557         MonoCustomAttrInfo *ainfo;
6558         GList *tmp, *list = NULL;
6559         const char *data;
6560
6561         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6562
6563         i = mono_metadata_custom_attrs_from_index (image, idx);
6564         if (!i)
6565                 return NULL;
6566         i --;
6567         while (i < ca->rows) {
6568                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6569                         break;
6570                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6571                 ++i;
6572         }
6573         len = g_list_length (list);
6574         if (!len)
6575                 return NULL;
6576         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6577         ainfo->num_attrs = len;
6578         ainfo->image = image;
6579         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6580                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6581                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6582                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6583                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6584                         mtoken |= MONO_TOKEN_METHOD_DEF;
6585                         break;
6586                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6587                         mtoken |= MONO_TOKEN_MEMBER_REF;
6588                         break;
6589                 default:
6590                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6591                         break;
6592                 }
6593                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6594                 if (!ainfo->attrs [i].ctor)
6595                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6596                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6597                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6598                 ainfo->attrs [i].data = data;
6599         }
6600         g_list_free (list);
6601
6602         return ainfo;
6603 }
6604
6605 MonoCustomAttrInfo*
6606 mono_custom_attrs_from_method (MonoMethod *method)
6607 {
6608         MonoCustomAttrInfo *cinfo;
6609         guint32 idx;
6610         
6611         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6612                 return cinfo;
6613         idx = find_method_index (method);
6614         idx <<= MONO_CUSTOM_ATTR_BITS;
6615         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6616         return mono_custom_attrs_from_index (method->klass->image, idx);
6617 }
6618
6619 MonoCustomAttrInfo*
6620 mono_custom_attrs_from_class (MonoClass *klass)
6621 {
6622         MonoCustomAttrInfo *cinfo;
6623         guint32 idx;
6624         
6625         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6626                 return cinfo;
6627         idx = mono_metadata_token_index (klass->type_token);
6628         idx <<= MONO_CUSTOM_ATTR_BITS;
6629         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6630         return mono_custom_attrs_from_index (klass->image, idx);
6631 }
6632
6633 MonoCustomAttrInfo*
6634 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6635 {
6636         MonoCustomAttrInfo *cinfo;
6637         guint32 idx;
6638         
6639         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6640                 return cinfo;
6641         idx = 1; /* there is only one assembly */
6642         idx <<= MONO_CUSTOM_ATTR_BITS;
6643         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6644         return mono_custom_attrs_from_index (assembly->image, idx);
6645 }
6646
6647 static MonoCustomAttrInfo*
6648 mono_custom_attrs_from_module (MonoImage *image)
6649 {
6650         MonoCustomAttrInfo *cinfo;
6651         guint32 idx;
6652         
6653         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6654                 return cinfo;
6655         idx = 1; /* there is only one module */
6656         idx <<= MONO_CUSTOM_ATTR_BITS;
6657         idx |= MONO_CUSTOM_ATTR_MODULE;
6658         return mono_custom_attrs_from_index (image, idx);
6659 }
6660
6661 MonoCustomAttrInfo*
6662 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6663 {
6664         MonoCustomAttrInfo *cinfo;
6665         guint32 idx;
6666         
6667         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6668                 return cinfo;
6669         idx = find_property_index (klass, property);
6670         idx <<= MONO_CUSTOM_ATTR_BITS;
6671         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6672         return mono_custom_attrs_from_index (klass->image, idx);
6673 }
6674
6675 MonoCustomAttrInfo*
6676 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6677 {
6678         MonoCustomAttrInfo *cinfo;
6679         guint32 idx;
6680         
6681         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6682                 return cinfo;
6683         idx = find_event_index (klass, event);
6684         idx <<= MONO_CUSTOM_ATTR_BITS;
6685         idx |= MONO_CUSTOM_ATTR_EVENT;
6686         return mono_custom_attrs_from_index (klass->image, idx);
6687 }
6688
6689 MonoCustomAttrInfo*
6690 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6691 {
6692         MonoCustomAttrInfo *cinfo;
6693         guint32 idx;
6694         
6695         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6696                 return cinfo;
6697         idx = find_field_index (klass, field);
6698         idx <<= MONO_CUSTOM_ATTR_BITS;
6699         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6700         return mono_custom_attrs_from_index (klass->image, idx);
6701 }
6702
6703 MonoCustomAttrInfo*
6704 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6705 {
6706         MonoTableInfo *ca;
6707         guint32 i, idx, method_index;
6708         guint32 param_list, param_last, param_pos, found;
6709         MonoImage *image;
6710         MonoReflectionMethodAux *aux;
6711
6712         if (method->klass->image->dynamic) {
6713                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6714                 if (!aux || !aux->param_cattr)
6715                         return NULL;
6716                 return aux->param_cattr [param];
6717         }
6718
6719         image = method->klass->image;
6720         method_index = find_method_index (method);
6721         ca = &image->tables [MONO_TABLE_METHOD];
6722
6723         if (method->klass->generic_class || method->klass->generic_container ||
6724             method->signature->generic_param_count) {
6725                 /* FIXME FIXME FIXME */
6726                 return NULL;
6727         }
6728
6729         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6730         if (method_index == ca->rows) {
6731                 ca = &image->tables [MONO_TABLE_PARAM];
6732                 param_last = ca->rows + 1;
6733         } else {
6734                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6735                 ca = &image->tables [MONO_TABLE_PARAM];
6736         }
6737         found = FALSE;
6738         for (i = param_list; i < param_last; ++i) {
6739                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6740                 if (param_pos == param) {
6741                         found = TRUE;
6742                         break;
6743                 }
6744         }
6745         if (!found)
6746                 return NULL;
6747         idx = i;
6748         idx <<= MONO_CUSTOM_ATTR_BITS;
6749         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6750         return mono_custom_attrs_from_index (image, idx);
6751 }
6752
6753 /*
6754  * mono_reflection_get_custom_attrs:
6755  * @obj: a reflection object handle
6756  *
6757  * Return an array with all the custom attributes defined of the
6758  * reflection handle @obj. The objects are fully build.
6759  */
6760 MonoArray*
6761 mono_reflection_get_custom_attrs (MonoObject *obj)
6762 {
6763         MonoClass *klass;
6764         MonoArray *result;
6765         MonoCustomAttrInfo *cinfo = NULL;
6766         
6767         MONO_ARCH_SAVE_REGS;
6768
6769         klass = obj->vtable->klass;
6770         if (klass == mono_defaults.monotype_class) {
6771                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6772                 klass = mono_class_from_mono_type (rtype->type);
6773                 cinfo = mono_custom_attrs_from_class (klass);
6774         } else if (strcmp ("Assembly", klass->name) == 0) {
6775                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6776                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6777         } else if (strcmp ("Module", klass->name) == 0) {
6778                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6779                 cinfo = mono_custom_attrs_from_module (module->image);
6780         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6781                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6782                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6783         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6784                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6785                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6786         } else if (strcmp ("MonoField", klass->name) == 0) {
6787                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6788                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6789         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6790                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6791                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6792         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6793                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6794                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6795                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6796         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6797                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6798                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6799         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6800                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6801                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6802         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6803                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6804                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6805         } else { /* handle other types here... */
6806                 g_error ("get custom attrs not yet supported for %s", klass->name);
6807         }
6808
6809         if (cinfo) {
6810                 result = mono_custom_attrs_construct (cinfo);
6811                 if (!cinfo->cached)
6812                         mono_custom_attrs_free (cinfo);
6813         } else {
6814                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6815                 result = mono_array_new (mono_domain_get (), klass, 0);
6816         }
6817
6818         return result;
6819 }
6820
6821 static MonoMethodSignature*
6822 parameters_to_signature (MonoArray *parameters) {
6823         MonoMethodSignature *sig;
6824         int count, i;
6825
6826         count = parameters? mono_array_length (parameters): 0;
6827
6828         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6829         sig->param_count = count;
6830         sig->sentinelpos = -1; /* FIXME */
6831         for (i = 0; i < count; ++i) {
6832                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6833                 sig->params [i] = pt->type;
6834         }
6835         return sig;
6836 }
6837
6838 static MonoMethodSignature*
6839 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6840         MonoMethodSignature *sig;
6841
6842         sig = parameters_to_signature (ctor->parameters);
6843         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6844         sig->ret = &mono_defaults.void_class->byval_arg;
6845         return sig;
6846 }
6847
6848 static MonoMethodSignature*
6849 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6850         MonoMethodSignature *sig;
6851
6852         sig = parameters_to_signature (method->parameters);
6853         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6854         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6855         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6856         return sig;
6857 }
6858
6859 static MonoMethodSignature*
6860 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6861         MonoMethodSignature *sig;
6862
6863         sig = parameters_to_signature (method->parameters);
6864         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6865         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6866         sig->generic_param_count = 0;
6867         return sig;
6868 }
6869
6870 static void
6871 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6872 {
6873         MonoClass *klass = mono_object_class (prop);
6874         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6875                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6876                 *name = mono_string_to_utf8 (pb->name);
6877                 *type = pb->type->type;
6878         } else {
6879                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6880                 *name = g_strdup (p->property->name);
6881                 if (p->property->get)
6882                         *type = p->property->get->signature->ret;
6883                 else
6884                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6885         }
6886 }
6887
6888 static void
6889 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6890 {
6891         MonoClass *klass = mono_object_class (field);
6892         if (strcmp (klass->name, "FieldBuilder") == 0) {
6893                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6894                 *name = mono_string_to_utf8 (fb->name);
6895                 *type = fb->type->type;
6896         } else {
6897                 MonoReflectionField *f = (MonoReflectionField *)field;
6898                 *name = g_strdup (f->field->name);
6899                 *type = f->field->type;
6900         }
6901 }
6902
6903 /*
6904  * Encode a value in a custom attribute stream of bytes.
6905  * The value to encode is either supplied as an object in argument val
6906  * (valuetypes are boxed), or as a pointer to the data in the
6907  * argument argval.
6908  * @type represents the type of the value
6909  * @buffer is the start of the buffer
6910  * @p the current position in the buffer
6911  * @buflen contains the size of the buffer and is used to return the new buffer size
6912  * if this needs to be realloced.
6913  * @retbuffer and @retp return the start and the position of the buffer
6914  */
6915 static void
6916 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6917 {
6918         MonoTypeEnum simple_type;
6919         
6920         if ((p-buffer) + 10 >= *buflen) {
6921                 char *newbuf;
6922                 *buflen *= 2;
6923                 newbuf = g_realloc (buffer, *buflen);
6924                 p = newbuf + (p-buffer);
6925                 buffer = newbuf;
6926         }
6927         if (!argval)
6928                 argval = ((char*)arg + sizeof (MonoObject));
6929         simple_type = type->type;
6930 handle_enum:
6931         switch (simple_type) {
6932         case MONO_TYPE_BOOLEAN:
6933         case MONO_TYPE_U1:
6934         case MONO_TYPE_I1:
6935                 *p++ = *argval;
6936                 break;
6937         case MONO_TYPE_CHAR:
6938         case MONO_TYPE_U2:
6939         case MONO_TYPE_I2:
6940                 swap_with_size (p, argval, 2, 1);
6941                 p += 2;
6942                 break;
6943         case MONO_TYPE_U4:
6944         case MONO_TYPE_I4:
6945         case MONO_TYPE_R4:
6946                 swap_with_size (p, argval, 4, 1);
6947                 p += 4;
6948                 break;
6949         case MONO_TYPE_U8:
6950         case MONO_TYPE_I8:
6951         case MONO_TYPE_R8:
6952                 swap_with_size (p, argval, 8, 1);
6953                 p += 8;
6954                 break;
6955         case MONO_TYPE_VALUETYPE:
6956                 if (type->data.klass->enumtype) {
6957                         simple_type = type->data.klass->enum_basetype->type;
6958                         goto handle_enum;
6959                 } else {
6960                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6961                 }
6962                 break;
6963         case MONO_TYPE_STRING: {
6964                 char *str;
6965                 guint32 slen;
6966                 if (!arg) {
6967                         *p++ = 0xFF;
6968                         break;
6969                 }
6970                 str = mono_string_to_utf8 ((MonoString*)arg);
6971                 slen = strlen (str);
6972                 if ((p-buffer) + 10 + slen >= *buflen) {
6973                         char *newbuf;
6974                         *buflen *= 2;
6975                         *buflen += slen;
6976                         newbuf = g_realloc (buffer, *buflen);
6977                         p = newbuf + (p-buffer);
6978                         buffer = newbuf;
6979                 }
6980                 mono_metadata_encode_value (slen, p, &p);
6981                 memcpy (p, str, slen);
6982                 p += slen;
6983                 g_free (str);
6984                 break;
6985         }
6986         case MONO_TYPE_CLASS: {
6987                 char *str;
6988                 guint32 slen;
6989                 MonoClass *k;
6990                 if (!arg) {
6991                         *p++ = 0xFF;
6992                         break;
6993                 }
6994                 k = mono_object_class (arg);
6995                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6996                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6997                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6998 handle_type:
6999                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7000                 slen = strlen (str);
7001                 if ((p-buffer) + 10 + slen >= *buflen) {
7002                         char *newbuf;
7003                         *buflen *= 2;
7004                         *buflen += slen;
7005                         newbuf = g_realloc (buffer, *buflen);
7006                         p = newbuf + (p-buffer);
7007                         buffer = newbuf;
7008                 }
7009                 mono_metadata_encode_value (slen, p, &p);
7010                 memcpy (p, str, slen);
7011                 p += slen;
7012                 g_free (str);
7013                 break;
7014         }
7015         case MONO_TYPE_SZARRAY: {
7016                 int len, i;
7017                 MonoClass *eclass, *arg_eclass;
7018
7019                 if (!arg) {
7020                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7021                         break;
7022                 }
7023                 len = mono_array_length ((MonoArray*)arg);
7024                 *p++ = len & 0xff;
7025                 *p++ = (len >> 8) & 0xff;
7026                 *p++ = (len >> 16) & 0xff;
7027                 *p++ = (len >> 24) & 0xff;
7028                 *retp = p;
7029                 *retbuffer = buffer;
7030                 eclass = type->data.klass;
7031                 arg_eclass = mono_object_class (arg)->element_class;
7032                 if (eclass->valuetype && arg_eclass->valuetype) {
7033                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7034                         int elsize = mono_class_array_element_size (eclass);
7035                         for (i = 0; i < len; ++i) {
7036                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7037                                 elptr += elsize;
7038                         }
7039                 } else {
7040                         for (i = 0; i < len; ++i) {
7041                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7042                         }
7043                 }
7044                 break;
7045         }
7046         /* it may be a boxed value or a Type */
7047         case MONO_TYPE_OBJECT: {
7048                 MonoClass *klass = mono_object_class (arg);
7049                 char *str;
7050                 guint32 slen;
7051                 
7052                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7053                         *p++ = 0x50;
7054                         goto handle_type;
7055                 } else if (klass->enumtype) {
7056                         *p++ = 0x55;
7057                 } else if (klass == mono_defaults.string_class) {
7058                         simple_type = MONO_TYPE_STRING;
7059                         *p++ = 0x0E;
7060                         goto handle_enum;
7061                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7062                         *p++ = simple_type = klass->byval_arg.type;
7063                         goto handle_enum;
7064                 } else {
7065                         g_error ("unhandled type in custom attr");
7066                 }
7067                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7068                 slen = strlen (str);
7069                 if ((p-buffer) + 10 + slen >= *buflen) {
7070                         char *newbuf;
7071                         *buflen *= 2;
7072                         *buflen += slen;
7073                         newbuf = g_realloc (buffer, *buflen);
7074                         p = newbuf + (p-buffer);
7075                         buffer = newbuf;
7076                 }
7077                 mono_metadata_encode_value (slen, p, &p);
7078                 memcpy (p, str, slen);
7079                 p += slen;
7080                 g_free (str);
7081                 simple_type = klass->enum_basetype->type;
7082                 goto handle_enum;
7083         }
7084         default:
7085                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7086         }
7087         *retp = p;
7088         *retbuffer = buffer;
7089 }
7090
7091 /*
7092  * mono_reflection_get_custom_attrs_blob:
7093  * @ctor: custom attribute constructor
7094  * @ctorArgs: arguments o the constructor
7095  * @properties:
7096  * @propValues:
7097  * @fields:
7098  * @fieldValues:
7099  * 
7100  * Creates the blob of data that needs to be saved in the metadata and that represents
7101  * the custom attributed described by @ctor, @ctorArgs etc.
7102  * Returns: a Byte array representing the blob of data.
7103  */
7104 MonoArray*
7105 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
7106 {
7107         MonoArray *result;
7108         MonoMethodSignature *sig;
7109         MonoObject *arg;
7110         char *buffer, *p;
7111         guint32 buflen, i;
7112
7113         MONO_ARCH_SAVE_REGS;
7114
7115         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7116                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7117         } else {
7118                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7119         }
7120         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7121         buflen = 256;
7122         p = buffer = g_malloc (buflen);
7123         /* write the prolog */
7124         *p++ = 1;
7125         *p++ = 0;
7126         for (i = 0; i < sig->param_count; ++i) {
7127                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7128                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7129         }
7130         i = 0;
7131         if (properties)
7132                 i += mono_array_length (properties);
7133         if (fields)
7134                 i += mono_array_length (fields);
7135         *p++ = i & 0xff;
7136         *p++ = (i >> 8) & 0xff;
7137         if (properties) {
7138                 MonoObject *prop;
7139                 for (i = 0; i < mono_array_length (properties); ++i) {
7140                         MonoType *ptype;
7141                         char *pname;
7142                         int len;
7143                         
7144                         prop = mono_array_get (properties, gpointer, i);
7145                         get_prop_name_and_type (prop, &pname, &ptype);
7146                         *p++ = 0x54; /* PROPERTY signature */
7147
7148                         /* Preallocate a large enough buffer */
7149                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7150                                 char *str = type_get_qualified_name (ptype, NULL);
7151                                 len = strlen (str);
7152                                 g_free (str);
7153                         }
7154                         else
7155                                 len = 0;
7156                         len += strlen (pname);
7157
7158                         if ((p-buffer) + 20 + len >= buflen) {
7159                                 char *newbuf;
7160                                 buflen *= 2;
7161                                 buflen += len;
7162                                 newbuf = g_realloc (buffer, buflen);
7163                                 p = newbuf + (p-buffer);
7164                                 buffer = newbuf;
7165                         }
7166
7167                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7168                                 char *str = type_get_qualified_name (ptype, NULL);
7169                                 int slen = strlen (str);
7170
7171                                 *p++ = 0x55;
7172                                 /*
7173                                  * This seems to be optional...
7174                                  * *p++ = 0x80;
7175                                  */
7176                                 mono_metadata_encode_value (slen, p, &p);
7177                                 memcpy (p, str, slen);
7178                                 p += slen;
7179                                 g_free (str);
7180                         } else {
7181                                 mono_metadata_encode_value (ptype->type, p, &p);
7182                                 if (ptype->type == MONO_TYPE_SZARRAY)
7183                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7184                         }
7185                         len = strlen (pname);
7186                         mono_metadata_encode_value (len, p, &p);
7187                         memcpy (p, pname, len);
7188                         p += len;
7189                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7190                         g_free (pname);
7191                 }
7192         }
7193
7194         if (fields) {
7195                 MonoObject *field;
7196                 for (i = 0; i < mono_array_length (fields); ++i) {
7197                         MonoType *ftype;
7198                         char *fname;
7199                         int len;
7200                         
7201                         field = mono_array_get (fields, gpointer, i);
7202                         get_field_name_and_type (field, &fname, &ftype);
7203                         *p++ = 0x53; /* FIELD signature */
7204                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7205                                 char *str = type_get_qualified_name (ftype, NULL);
7206                                 int slen = strlen (str);
7207                                 if ((p-buffer) + 10 + slen >= buflen) {
7208                                         char *newbuf;
7209                                         buflen *= 2;
7210                                         buflen += slen;
7211                                         newbuf = g_realloc (buffer, buflen);
7212                                         p = newbuf + (p-buffer);
7213                                         buffer = newbuf;
7214                                 }
7215                                 *p++ = 0x55;
7216                                 /*
7217                                  * This seems to be optional...
7218                                  * *p++ = 0x80;
7219                                  */
7220                                 mono_metadata_encode_value (slen, p, &p);
7221                                 memcpy (p, str, slen);
7222                                 p += slen;
7223                                 g_free (str);
7224                         } else {
7225                                 mono_metadata_encode_value (ftype->type, p, &p);
7226                                 if (ftype->type == MONO_TYPE_SZARRAY)
7227                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7228                         }
7229                         len = strlen (fname);
7230                         mono_metadata_encode_value (len, p, &p);
7231                         memcpy (p, fname, len);
7232                         p += len;
7233                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7234                         g_free (fname);
7235                 }
7236         }
7237
7238         g_assert (p - buffer <= buflen);
7239         buflen = p - buffer;
7240         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7241         p = mono_array_addr (result, char, 0);
7242         memcpy (p, buffer, buflen);
7243         g_free (buffer);
7244         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7245                 g_free (sig);
7246         return result;
7247 }
7248
7249 /*
7250  * mono_reflection_setup_internal_class:
7251  * @tb: a TypeBuilder object
7252  *
7253  * Creates a MonoClass that represents the TypeBuilder.
7254  * This is a trick that lets us simplify a lot of reflection code
7255  * (and will allow us to support Build and Run assemblies easier).
7256  */
7257 void
7258 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7259 {
7260         MonoClass *klass, *parent;
7261
7262         MONO_ARCH_SAVE_REGS;
7263
7264         if (tb->parent) {
7265                 /* check so we can compile corlib correctly */
7266                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7267                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7268                         parent = tb->parent->type->data.klass;
7269                 } else {
7270                         parent = my_mono_class_from_mono_type (tb->parent->type);
7271                 }
7272         } else {
7273                 parent = NULL;
7274         }
7275         
7276         /* the type has already being created: it means we just have to change the parent */
7277         if (tb->type.type) {
7278                 klass = mono_class_from_mono_type (tb->type.type);
7279                 klass->parent = NULL;
7280                 /* fool mono_class_setup_parent */
7281                 g_free (klass->supertypes);
7282                 klass->supertypes = NULL;
7283                 mono_class_setup_parent (klass, parent);
7284                 mono_class_setup_mono_type (klass);
7285                 return;
7286         }
7287         
7288         klass = g_new0 (MonoClass, 1);
7289
7290         klass->image = &tb->module->dynamic_image->image;
7291
7292         klass->inited = 1; /* we lie to the runtime */
7293         klass->name = mono_string_to_utf8 (tb->name);
7294         klass->name_space = mono_string_to_utf8 (tb->nspace);
7295         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7296         klass->flags = tb->attrs;
7297
7298         klass->element_class = klass;
7299         klass->reflection_info = tb; /* need to pin. */
7300
7301         /* Put into cache so mono_class_get () will find it */
7302         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7303
7304         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7305                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7306
7307         if (parent != NULL) {
7308                 mono_class_setup_parent (klass, parent);
7309         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7310                 const char *old_n = klass->name;
7311                 /* trick to get relative numbering right when compiling corlib */
7312                 klass->name = "BuildingObject";
7313                 mono_class_setup_parent (klass, mono_defaults.object_class);
7314                 klass->name = old_n;
7315         }
7316
7317         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7318                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7319                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7320                 klass->instance_size = sizeof (MonoObject);
7321                 klass->size_inited = 1;
7322                 mono_class_setup_vtable (klass, NULL, 0);
7323         }
7324
7325         mono_class_setup_mono_type (klass);
7326
7327         mono_class_setup_supertypes (klass);
7328
7329         /*
7330          * FIXME: handle interfaces.
7331          */
7332
7333         tb->type.type = &klass->byval_arg;
7334
7335         if (tb->nesting_type) {
7336                 g_assert (tb->nesting_type->type);
7337                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7338         }
7339
7340         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7341 }
7342
7343 /*
7344  * mono_reflection_setup_generic_class:
7345  * @tb: a TypeBuilder object
7346  *
7347  * Setup the generic class before adding the first generic parameter.
7348  */
7349 void
7350 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7351 {
7352         MonoClass *klass;
7353
7354         MONO_ARCH_SAVE_REGS;
7355
7356         klass = my_mono_class_from_mono_type (tb->type.type);
7357         if (tb->generic_container)
7358                 return;
7359
7360         tb->generic_container = g_new0 (MonoGenericContainer, 1);
7361         tb->generic_container->klass = klass;
7362
7363         tb->generic_container->context.container = tb->generic_container;
7364 }
7365
7366 /*
7367  * mono_reflection_create_generic_class:
7368  * @tb: a TypeBuilder object
7369  *
7370  * Creates the generic class after all generic parameters have been added.
7371  */
7372 void
7373 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7374 {
7375         MonoClass *klass;
7376         int count, i;
7377
7378         MONO_ARCH_SAVE_REGS;
7379
7380         klass = my_mono_class_from_mono_type (tb->type.type);
7381
7382         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7383
7384         if (klass->generic_container || (count == 0))
7385                 return;
7386
7387         g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7388
7389         klass->generic_container = tb->generic_container;
7390
7391         klass->generic_container->type_argc = count;
7392         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7393
7394         for (i = 0; i < count; i++) {
7395                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7396                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7397                 g_assert (klass->generic_container->type_params [i].owner);
7398         }
7399 }
7400
7401 /*
7402  * mono_reflection_create_internal_class:
7403  * @tb: a TypeBuilder object
7404  *
7405  * Actually create the MonoClass that is associated with the TypeBuilder.
7406  */
7407 void
7408 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7409 {
7410         MonoClass *klass;
7411
7412         MONO_ARCH_SAVE_REGS;
7413
7414         klass = my_mono_class_from_mono_type (tb->type.type);
7415
7416         if (klass->enumtype && klass->enum_basetype == NULL) {
7417                 MonoReflectionFieldBuilder *fb;
7418                 MonoClass *ec;
7419
7420                 g_assert (tb->fields != NULL);
7421                 g_assert (mono_array_length (tb->fields) >= 1);
7422
7423                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7424
7425                 klass->enum_basetype = fb->type->type;
7426                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7427                 if (!klass->element_class)
7428                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7429
7430                 /*
7431                  * get the element_class from the current corlib.
7432                  */
7433                 ec = default_class_from_mono_type (klass->enum_basetype);
7434                 klass->instance_size = ec->instance_size;
7435                 klass->size_inited = 1;
7436                 /* 
7437                  * this is almost safe to do with enums and it's needed to be able
7438                  * to create objects of the enum type (for use in SetConstant).
7439                  */
7440                 /* FIXME: Does this mean enums can't have method overrides ? */
7441                 mono_class_setup_vtable (klass, NULL, 0);
7442         }
7443 }
7444
7445 static MonoMarshalSpec*
7446 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7447                                                                 MonoReflectionMarshal *minfo)
7448 {
7449         MonoMarshalSpec *res;
7450
7451         res = g_new0 (MonoMarshalSpec, 1);
7452         res->native = minfo->type;
7453
7454         switch (minfo->type) {
7455         case MONO_NATIVE_LPARRAY:
7456                 res->data.array_data.elem_type = minfo->eltype;
7457                 res->data.array_data.param_num = 0; /* Not yet */
7458                 res->data.array_data.num_elem = minfo->count;
7459                 break;
7460
7461         case MONO_NATIVE_BYVALTSTR:
7462         case MONO_NATIVE_BYVALARRAY:
7463                 res->data.array_data.num_elem = minfo->count;
7464                 break;
7465
7466         case MONO_NATIVE_CUSTOM:
7467                 if (minfo->marshaltyperef)
7468                         res->data.custom_data.custom_name =
7469                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7470                 if (minfo->mcookie)
7471                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7472                 break;
7473
7474         default:
7475                 break;
7476         }
7477
7478         return res;
7479 }
7480
7481 MonoReflectionMarshal*
7482 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7483                                                                                    MonoMarshalSpec *spec)
7484 {
7485         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7486         MonoReflectionMarshal *minfo;
7487         MonoType *mtype;
7488
7489         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7490                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7491                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7492                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7493         }
7494
7495         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7496         minfo->type = spec->native;
7497
7498         switch (minfo->type) {
7499         case MONO_NATIVE_LPARRAY:
7500                 minfo->eltype = spec->data.array_data.elem_type;
7501                 minfo->count = spec->data.array_data.num_elem;
7502                 break;
7503
7504         case MONO_NATIVE_BYVALTSTR:
7505         case MONO_NATIVE_BYVALARRAY:
7506                 minfo->count = spec->data.array_data.num_elem;
7507                 break;
7508
7509         case MONO_NATIVE_CUSTOM:
7510                 if (spec->data.custom_data.custom_name) {
7511                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7512                         if (mtype)
7513                                 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7514
7515                         minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7516                 }
7517                 if (spec->data.custom_data.cookie)
7518                         minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7519                 break;
7520
7521         default:
7522                 break;
7523         }
7524
7525         return minfo;
7526 }
7527
7528 static MonoMethod*
7529 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7530                                          ReflectionMethodBuilder *rmb,
7531                                          MonoMethodSignature *sig)
7532 {
7533         MonoMethod *m;
7534         MonoMethodNormal *pm;
7535         MonoMarshalSpec **specs;
7536         MonoReflectionMethodAux *method_aux;
7537         int i;
7538
7539         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7540                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7541                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7542         else if (rmb->refs)
7543                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7544         else
7545                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7546
7547         pm = (MonoMethodNormal*)m;
7548
7549         m->slot = -1;
7550         m->flags = rmb->attrs;
7551         m->iflags = rmb->iattrs;
7552         m->name = mono_string_to_utf8 (rmb->name);
7553         m->klass = klass;
7554         m->signature = sig;
7555         if (rmb->table_idx)
7556                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7557
7558         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7559                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7560                         m->string_ctor = 1;
7561
7562                 m->signature->pinvoke = 1;
7563         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7564                 m->signature->pinvoke = 1;
7565
7566                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7567
7568                 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7569                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7570                 
7571                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7572
7573                 if (klass->image->dynamic)
7574                         mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7575
7576                 return m;
7577         } else if (!m->klass->dummy && 
7578                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7579                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7580                 MonoMethodHeader *header;
7581                 guint32 code_size;
7582                 gint32 max_stack, i;
7583                 gint32 num_locals = 0;
7584                 gint32 num_clauses = 0;
7585                 guint8 *code;
7586
7587                 if (rmb->ilgen) {
7588                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7589                         code_size = rmb->ilgen->code_len;
7590                         max_stack = rmb->ilgen->max_stack;
7591                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7592                         if (rmb->ilgen->ex_handlers)
7593                                 num_clauses = method_count_clauses (rmb->ilgen);
7594                 } else {
7595                         if (rmb->code) {
7596                                 code = mono_array_addr (rmb->code, guint8, 0);
7597                                 code_size = mono_array_length (rmb->code);
7598                                 /* we probably need to run a verifier on the code... */
7599                                 max_stack = 8; 
7600                         }
7601                         else {
7602                                 code = NULL;
7603                                 code_size = 0;
7604                                 max_stack = 8;
7605                         }
7606                 }
7607
7608                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7609                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7610                 header->code_size = code_size;
7611                 header->code = g_malloc (code_size);
7612                 memcpy ((char*)header->code, code, code_size);
7613                 header->max_stack = max_stack;
7614                 header->init_locals = rmb->init_locals;
7615                 header->num_locals = num_locals;
7616
7617                 for (i = 0; i < num_locals; ++i) {
7618                         MonoReflectionLocalBuilder *lb = 
7619                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7620
7621                         header->locals [i] = g_new0 (MonoType, 1);
7622                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7623                 }
7624
7625                 header->num_clauses = num_clauses;
7626                 if (num_clauses) {
7627                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7628                                  rmb->ilgen, num_clauses);
7629                 }
7630
7631                 pm->header = header;
7632         }
7633
7634         if (rmb->generic_params) {
7635                 int count = mono_array_length (rmb->generic_params);
7636                 MonoGenericContainer *container;
7637
7638                 pm->generic_container = container = rmb->generic_container;
7639                 container->type_argc = count;
7640                 container->type_params = g_new0 (MonoGenericParam, count);
7641
7642                 for (i = 0; i < count; i++) {
7643                         MonoReflectionGenericParam *gp =
7644                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7645
7646                         container->type_params [i] = *gp->type.type->data.generic_param;
7647                 }
7648         }
7649
7650         if (rmb->refs) {
7651                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7652                 int i;
7653
7654                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7655
7656                 for (i = 0; i < rmb->nrefs; ++i)
7657                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7658         }
7659
7660         method_aux = NULL;
7661
7662         /* Parameter info */
7663         if (rmb->pinfo) {
7664                 if (!method_aux)
7665                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7666                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7667                 for (i = 0; i <= m->signature->param_count; ++i) {
7668                         MonoReflectionParamBuilder *pb;
7669                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7670                                 if (i > 0)
7671                                         m->signature->params [i - 1]->attrs = pb->attrs;
7672
7673                                 if (pb->def_value) {
7674                                         MonoDynamicImage *assembly;
7675                                         guint32 idx, def_type, len;
7676                                         char *p;
7677                                         const char *p2;
7678
7679                                         if (!method_aux->param_defaults)
7680                                                 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7681                                         assembly = (MonoDynamicImage*)klass->image;
7682                                         idx = encode_constant (assembly, pb->def_value, &def_type);
7683                                         /* Copy the data from the blob since it might get realloc-ed */
7684                                         p = assembly->blob.data + idx;
7685                                         len = mono_metadata_decode_blob_size (p, &p2);
7686                                         len += p2 - p;
7687                                         method_aux->param_defaults [i] = g_malloc (len);
7688                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7689                                 }
7690
7691                                 if (pb->name)
7692                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7693                                 if (pb->cattrs) {
7694                                         if (!method_aux->param_cattr)
7695                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7696                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7697                                 }
7698                         }
7699                 }
7700         }
7701
7702         /* Parameter marshalling */
7703         specs = NULL;
7704         if (rmb->pinfo)         
7705                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7706                         MonoReflectionParamBuilder *pb;
7707                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7708                                 if (pb->marshal_info) {
7709                                         if (specs == NULL)
7710                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7711                                         specs [pb->position] = 
7712                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7713                                 }
7714                         }
7715                 }
7716         if (specs != NULL) {
7717                 if (!method_aux)
7718                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7719                 method_aux->param_marshall = specs;
7720         }
7721
7722         if (klass->image->dynamic && method_aux)
7723                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7724
7725         return m;
7726 }       
7727
7728 static MonoMethod*
7729 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7730 {
7731         ReflectionMethodBuilder rmb;
7732         MonoMethodSignature *sig;
7733
7734         sig = ctor_builder_to_signature (mb);
7735
7736         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7737
7738         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7739         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7740
7741         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7742                 /* ilgen is no longer needed */
7743                 mb->ilgen = NULL;
7744         }
7745
7746         return mb->mhandle;
7747 }
7748
7749 static MonoMethod*
7750 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7751 {
7752         ReflectionMethodBuilder rmb;
7753         MonoMethodSignature *sig;
7754
7755         sig = method_builder_to_signature (mb);
7756
7757         reflection_methodbuilder_from_method_builder (&rmb, mb);
7758
7759         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7760         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7761
7762         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7763                 /* ilgen is no longer needed */
7764                 mb->ilgen = NULL;
7765         }
7766         return mb->mhandle;
7767 }
7768
7769 static MonoClassField*
7770 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7771 {
7772         MonoClassField *field;
7773         const char *p, *p2;
7774         guint32 len, idx;
7775
7776         if (fb->handle)
7777                 return fb->handle;
7778
7779         field = g_new0 (MonoClassField, 1);
7780
7781         field->name = mono_string_to_utf8 (fb->name);
7782         if (fb->attrs) {
7783                 /* FIXME: handle type modifiers */
7784                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7785                 field->type->attrs = fb->attrs;
7786         } else {
7787                 field->type = fb->type->type;
7788         }
7789         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7790                 field->data = mono_array_addr (fb->rva_data, char, 0);
7791         if (fb->offset != -1)
7792                 field->offset = fb->offset;
7793         field->parent = klass;
7794         fb->handle = field;
7795         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7796
7797         if (fb->def_value) {
7798                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7799                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7800                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7801                 /* Copy the data from the blob since it might get realloc-ed */
7802                 p = assembly->blob.data + idx;
7803                 len = mono_metadata_decode_blob_size (p, &p2);
7804                 len += p2 - p;
7805                 field->data = g_malloc (len);
7806                 memcpy ((gpointer)field->data, p, len);
7807         }
7808
7809         return field;
7810 }
7811
7812 static MonoType*
7813 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7814                                             MonoType *parent)
7815 {
7816         MonoClass *klass, *gklass;
7817         MonoReflectionTypeBuilder *tb = NULL;
7818         MonoGenericClass *gclass, *cached;
7819         MonoDomain *domain;
7820         MonoType *geninst;
7821         int icount, i;
7822
7823         klass = mono_class_from_mono_type (type->type);
7824         if (!klass->generic_container && !klass->generic_class &&
7825             !(klass->nested_in && klass->nested_in->generic_container))
7826                 return NULL;
7827
7828         mono_loader_lock ();
7829
7830         domain = mono_object_domain (type);
7831
7832         gclass = g_new0 (MonoGenericClass, 1);
7833         gclass->inst = g_new0 (MonoGenericInst, 1);
7834
7835         gclass->inst->type_argc = type_argc;
7836         gclass->inst->type_argv = types;
7837
7838         for (i = 0; i < gclass->inst->type_argc; ++i) {
7839                 if (!gclass->inst->is_open)
7840                         gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7841         }
7842
7843         gclass->generic_type = &klass->byval_arg;
7844
7845         if (klass->generic_class) {
7846                 MonoGenericClass *kgclass = klass->generic_class;
7847                 MonoGenericClass *ogclass = gclass;
7848
7849                 ogclass->context = g_new0 (MonoGenericContext, 1);
7850                 ogclass->context->container = ogclass->container;
7851                 ogclass->context->gclass = ogclass;
7852
7853                 gclass = g_new0 (MonoGenericClass, 1);
7854                 gclass->inst = g_new0 (MonoGenericInst, 1);
7855
7856                 gclass->inst->type_argc = kgclass->inst->type_argc;
7857                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7858
7859                 for (i = 0; i < gclass->inst->type_argc; i++) {
7860                         MonoType *t = kgclass->inst->type_argv [i];
7861
7862                         t = mono_class_inflate_generic_type (t, ogclass->context);
7863
7864                         if (!gclass->inst->is_open)
7865                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7866
7867                         gclass->inst->type_argv [i] = t;
7868                 }
7869
7870                 gclass->generic_type = kgclass->generic_type;
7871         }
7872
7873         geninst = g_new0 (MonoType, 1);
7874         geninst->type = MONO_TYPE_GENERICINST;
7875
7876         cached = mono_metadata_lookup_generic_class (gclass);
7877         if (cached) {
7878                 g_free (gclass);
7879                 mono_loader_unlock ();
7880                 geninst->data.generic_class = cached;
7881                 return geninst;
7882         }
7883
7884         gklass = mono_class_from_mono_type (gclass->generic_type);
7885         g_assert ((gclass->container = gklass->generic_container) != NULL);
7886
7887         geninst->data.generic_class = gclass;
7888
7889         gclass->parent = parent;
7890
7891         gclass->context = g_new0 (MonoGenericContext, 1);
7892         gclass->context->container = gclass->container;
7893         gclass->context->gclass = gclass;
7894
7895         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7896                 tb = (MonoReflectionTypeBuilder *) type;
7897
7898                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7899                 gclass->is_dynamic = TRUE;
7900         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7901                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7902                 MonoReflectionType *rgt = rgi->generic_type;
7903
7904                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7905                 tb = (MonoReflectionTypeBuilder *) rgt;
7906
7907                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7908                 gclass->is_dynamic = TRUE;
7909         } else {
7910                 icount = klass->interface_count;
7911         }
7912
7913         gclass->ifaces = g_new0 (MonoType *, icount);
7914         gclass->count_ifaces = icount;
7915
7916         for (i = 0; i < icount; i++) {
7917                 MonoReflectionType *itype;
7918
7919                 if (tb)
7920                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7921                 else
7922                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7923                 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7924                 if (!gclass->ifaces [i])
7925                         gclass->ifaces [i] = itype->type;
7926         }
7927
7928         mono_class_create_generic (gclass);
7929         mono_class_create_generic_2 (gclass);
7930
7931         mono_loader_unlock ();
7932
7933         return geninst;
7934 }
7935
7936 MonoType*
7937 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7938 {
7939         MonoClass *klass, *pklass = NULL;
7940         MonoReflectionType *parent = NULL;
7941         MonoType *the_parent = NULL, *geninst;
7942         MonoReflectionTypeBuilder *tb = NULL;
7943         MonoGenericClass *gclass;
7944         MonoDomain *domain;
7945
7946         domain = mono_object_domain (type);
7947         klass = mono_class_from_mono_type (type->type);
7948
7949         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7950                 tb = (MonoReflectionTypeBuilder *) type;
7951
7952                 if (tb->parent) {
7953                         parent = tb->parent;
7954                         pklass = mono_class_from_mono_type (parent->type);
7955                 }
7956         } else {
7957                 pklass = klass->parent;
7958                 if (pklass)
7959                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7960                 else if (klass->generic_class && klass->generic_class->parent) {
7961                         parent = mono_type_get_object (domain, klass->generic_class->parent);
7962                         pklass = mono_class_from_mono_type (klass->generic_class->parent);
7963                 }
7964         }
7965
7966         if (pklass && pklass->generic_class)
7967                 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7968
7969         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7970         if (!geninst)
7971                 return NULL;
7972
7973         gclass = geninst->data.generic_class;
7974
7975         return geninst;
7976 }
7977
7978 static MonoType*
7979 dup_type (const MonoType *original)
7980 {
7981         MonoType *r = g_new0 (MonoType, 1);
7982         *r = *original;
7983         r->attrs = original->attrs;
7984         r->byref = original->byref;
7985         mono_stats.generics_metadata_size += sizeof (MonoType);
7986         return r;
7987 }
7988
7989 MonoReflectionMethod*
7990 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7991 {
7992         MonoMethod *method, *inflated;
7993         MonoReflectionMethodBuilder *mb = NULL;
7994         MonoGenericContainer *container;
7995         MonoGenericMethod *gmethod;
7996         MonoGenericContext *context;
7997         MonoGenericInst *ginst;
7998         int count, i;
7999
8000         MONO_ARCH_SAVE_REGS;
8001         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8002                 MonoReflectionTypeBuilder *tb;
8003                 MonoClass *klass;
8004
8005                 mb = (MonoReflectionMethodBuilder *) rmethod;
8006                 tb = (MonoReflectionTypeBuilder *) mb->type;
8007                 klass = mono_class_from_mono_type (tb->type.type);
8008
8009                 method = methodbuilder_to_mono_method (klass, mb);
8010         } else {
8011                 method = rmethod->method;
8012         }
8013
8014         count = method->signature->generic_param_count;
8015         if (count != mono_array_length (types))
8016                 return NULL;
8017
8018         container = ((MonoMethodNormal*) method)->generic_container;
8019         g_assert (container);
8020
8021         if (!container->method_hash)
8022                 container->method_hash = g_hash_table_new (
8023                         (GHashFunc) mono_metadata_generic_method_hash,
8024                         (GCompareFunc) mono_metadata_generic_method_equal);
8025
8026         ginst = g_new0 (MonoGenericInst,1 );
8027         ginst->type_argc = count;
8028         ginst->type_argv = g_new0 (MonoType *, count);
8029         for (i = 0; i < count; i++) {
8030                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8031                 ginst->type_argv [i] = dup_type (garg->type);
8032
8033                 if (!ginst->is_open)
8034                         ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8035         }
8036         ginst = mono_metadata_lookup_generic_inst (ginst);
8037
8038         gmethod = g_new0 (MonoGenericMethod, 1);
8039         gmethod->container = container;
8040         gmethod->inst = ginst;
8041
8042         inflated = g_hash_table_lookup (container->method_hash, gmethod);
8043         if (inflated) {
8044                 g_free (gmethod);
8045
8046                 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8047         }
8048
8049         gmethod->reflection_info = rmethod;
8050
8051         context = g_new0 (MonoGenericContext, 1);
8052         context->container = container;
8053         context->gclass = method->klass->generic_class;
8054         context->gmethod = gmethod;
8055
8056         inflated = mono_class_inflate_generic_method (method, context, NULL);
8057         g_hash_table_insert (container->method_hash, gmethod, inflated);
8058
8059         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8060 }
8061
8062 static MonoMethod *
8063 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8064 {
8065         MonoGenericMethod *gmethod;
8066         MonoGenericClass *gclass;
8067         MonoGenericContext *context;
8068         int i;
8069
8070         gclass = type->type.type->data.generic_class;
8071
8072         gmethod = g_new0 (MonoGenericMethod, 1);
8073         gmethod->inst = g_new0 (MonoGenericInst, 1);
8074         gmethod->reflection_info = obj;
8075
8076         gmethod->inst->type_argc = method->signature->generic_param_count;
8077         gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8078
8079         for (i = 0; i < gmethod->inst->type_argc; i++) {
8080                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8081                 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8082
8083                 g_assert (gparam->pklass);
8084                 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8085         }
8086
8087         context = g_new0 (MonoGenericContext, 1);
8088         context->container = gclass->container;
8089         context->gclass = gclass;
8090         context->gmethod = gmethod;
8091
8092         return mono_class_inflate_generic_method (method, context, gclass->klass);
8093 }
8094
8095 static MonoMethod *
8096 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8097 {
8098         MonoMethod *method;
8099         MonoClass *klass;
8100
8101         klass = mono_class_from_mono_type (type->type.type);
8102
8103         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8104                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8105         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8106                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8107         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8108                 method = ((MonoReflectionMethod *) obj)->method;
8109         else {
8110                 method = NULL; /* prevent compiler warning */
8111                 g_assert_not_reached ();
8112         }
8113
8114         return inflate_mono_method (type, method, obj);
8115 }
8116
8117 void
8118 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
8119                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8120                                           MonoArray *events)
8121 {
8122         MonoGenericClass *gclass;
8123         MonoDynamicGenericClass *dgclass;
8124         MonoClass *klass, *gklass, *pklass;
8125         int i;
8126
8127         MONO_ARCH_SAVE_REGS;
8128
8129         klass = mono_class_from_mono_type (type->type.type);
8130         gclass = type->type.type->data.generic_class;
8131
8132         if (gclass->initialized)
8133                 return;
8134
8135         dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
8136
8137         gklass = mono_class_from_mono_type (gclass->generic_type);
8138         mono_class_init (gklass);
8139
8140         if (gclass->parent)
8141                 pklass = mono_class_from_mono_type (gclass->parent);
8142         else
8143                 pklass = gklass->parent;
8144
8145         mono_class_setup_parent (klass, pklass);
8146
8147         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8148         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8149         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8150         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8151         dgclass->count_events = events ? mono_array_length (events) : 0;
8152
8153         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8154         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8155         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8156         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8157         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8158
8159         for (i = 0; i < dgclass->count_methods; i++) {
8160                 MonoObject *obj = mono_array_get (methods, gpointer, i);
8161
8162                 dgclass->methods [i] = inflate_method (type, obj);
8163         }
8164
8165         for (i = 0; i < dgclass->count_ctors; i++) {
8166                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8167
8168                 dgclass->ctors [i] = inflate_method (type, obj);
8169         }
8170
8171         for (i = 0; i < dgclass->count_fields; i++) {
8172                 MonoObject *obj = mono_array_get (fields, gpointer, i);
8173                 MonoClassField *field;
8174                 MonoInflatedField *ifield;
8175
8176                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8177                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8178                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8179                         field = ((MonoReflectionField *) obj)->field;
8180                 else {
8181                         field = NULL; /* prevent compiler warning */
8182                         g_assert_not_reached ();
8183                 }
8184
8185                 ifield = g_new0 (MonoInflatedField, 1);
8186                 ifield->generic_type = field->type;
8187                 ifield->reflection_info = obj;
8188
8189                 dgclass->fields [i] = *field;
8190                 dgclass->fields [i].generic_info = ifield;
8191                 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8192         }
8193
8194         for (i = 0; i < dgclass->count_properties; i++) {
8195                 MonoObject *obj = mono_array_get (properties, gpointer, i);
8196                 MonoProperty *property = &dgclass->properties [i];
8197
8198                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8199                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8200
8201                         property->parent = klass;
8202                         property->attrs = pb->attrs;
8203                         property->name = mono_string_to_utf8 (pb->name);
8204                         if (pb->get_method)
8205                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8206                         if (pb->set_method)
8207                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8208                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8209                         *property = *((MonoReflectionProperty *) obj)->property;
8210
8211                         if (property->get)
8212                                 property->get = inflate_mono_method (type, property->get, NULL);
8213                         if (property->set)
8214                                 property->set = inflate_mono_method (type, property->set, NULL);
8215                 } else
8216                         g_assert_not_reached ();
8217         }
8218
8219         for (i = 0; i < dgclass->count_events; i++) {
8220                 MonoObject *obj = mono_array_get (events, gpointer, i);
8221                 MonoEvent *event = &dgclass->events [i];
8222
8223                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8224                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8225
8226                         event->parent = klass;
8227                         event->attrs = eb->attrs;
8228                         event->name = mono_string_to_utf8 (eb->name);
8229                         if (eb->add_method)
8230                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8231                         if (eb->remove_method)
8232                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8233                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8234                         *event = *((MonoReflectionEvent *) obj)->event;
8235
8236                         if (event->add)
8237                                 event->add = inflate_mono_method (type, event->add, NULL);
8238                         if (event->remove)
8239                                 event->remove = inflate_mono_method (type, event->remove, NULL);
8240                 } else
8241                         g_assert_not_reached ();
8242         }
8243
8244         gclass->initialized = TRUE;
8245 }
8246
8247 static void
8248 ensure_runtime_vtable (MonoClass *klass)
8249 {
8250         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8251         int i, num, j, onum;
8252         MonoMethod **overrides;
8253
8254         if (!tb || klass->wastypebuilder)
8255                 return;
8256         if (klass->parent)
8257                 ensure_runtime_vtable (klass->parent);
8258
8259         num = tb->ctors? mono_array_length (tb->ctors): 0;
8260         num += tb->num_methods;
8261         klass->method.count = num;
8262         klass->methods = g_new (MonoMethod*, num);
8263         num = tb->ctors? mono_array_length (tb->ctors): 0;
8264         for (i = 0; i < num; ++i)
8265                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8266         num = tb->num_methods;
8267         j = i;
8268         for (i = 0; i < num; ++i)
8269                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8270
8271         if (tb->interfaces) {
8272                 klass->interface_count = mono_array_length (tb->interfaces);
8273                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8274                 for (i = 0; i < klass->interface_count; ++i) {
8275                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8276                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8277                 }
8278         }
8279
8280         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8281                 for (i = 0; i < klass->method.count; ++i)
8282                         klass->methods [i]->slot = i;
8283
8284         /* Overrides */
8285         onum = 0;
8286         if (tb->methods) {
8287                 for (i = 0; i < tb->num_methods; ++i) {
8288                         MonoReflectionMethodBuilder *mb = 
8289                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8290                         if (mb->override_method)
8291                                 onum ++;
8292                 }
8293         }
8294
8295         overrides = g_new0 (MonoMethod*, onum * 2);
8296
8297         if (tb->methods) {
8298                 onum = 0;
8299                 for (i = 0; i < tb->num_methods; ++i) {
8300                         MonoReflectionMethodBuilder *mb = 
8301                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8302                         if (mb->override_method) {
8303                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8304                                 overrides [onum * 2] = 
8305                                         mb->override_method->method;
8306                                 overrides [onum * 2 + 1] =
8307                                         mb->mhandle;
8308
8309                                 g_assert (mb->mhandle);
8310
8311                                 onum ++;
8312                         }
8313                 }
8314         }
8315
8316         mono_class_setup_vtable (klass, overrides, onum);
8317         g_free (overrides);
8318 }
8319
8320 static void
8321 typebuilder_setup_fields (MonoClass *klass)
8322 {
8323         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8324         MonoReflectionFieldBuilder *fb;
8325         MonoClassField *field;
8326         const char *p, *p2;
8327         int i;
8328         guint32 len, idx;
8329
8330         klass->field.count = tb->num_fields;
8331         klass->field.first = 0;
8332         klass->field.last = klass->field.count;
8333
8334         if (!klass->field.count)
8335                 return;
8336         
8337         klass->fields = g_new0 (MonoClassField, klass->field.count);
8338
8339         for (i = 0; i < klass->field.count; ++i) {
8340                 fb = mono_array_get (tb->fields, gpointer, i);
8341                 field = &klass->fields [i];
8342                 field->name = mono_string_to_utf8 (fb->name);
8343                 if (fb->attrs) {
8344                         /* FIXME: handle type modifiers */
8345                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
8346                         field->type->attrs = fb->attrs;
8347                 } else {
8348                         field->type = fb->type->type;
8349                 }
8350                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8351                         field->data = mono_array_addr (fb->rva_data, char, 0);
8352                 if (fb->offset != -1)
8353                         field->offset = fb->offset;
8354                 field->parent = klass;
8355                 fb->handle = field;
8356                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8357
8358                 if (fb->def_value) {
8359                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8360                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8361                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
8362                         /* Copy the data from the blob since it might get realloc-ed */
8363                         p = assembly->blob.data + idx;
8364                         len = mono_metadata_decode_blob_size (p, &p2);
8365                         len += p2 - p;
8366                         field->data = g_malloc (len);
8367                         memcpy ((gpointer)field->data, p, len);
8368                 }
8369         }
8370         mono_class_layout_fields (klass);
8371 }
8372
8373 static void
8374 typebuilder_setup_properties (MonoClass *klass)
8375 {
8376         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8377         MonoReflectionPropertyBuilder *pb;
8378         int i;
8379
8380         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8381         klass->property.first = 0;
8382         klass->property.last = klass->property.count;
8383
8384         klass->properties = g_new0 (MonoProperty, klass->property.count);
8385         for (i = 0; i < klass->property.count; ++i) {
8386                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8387                 klass->properties [i].parent = klass;
8388                 klass->properties [i].attrs = pb->attrs;
8389                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8390                 if (pb->get_method)
8391                         klass->properties [i].get = pb->get_method->mhandle;
8392                 if (pb->set_method)
8393                         klass->properties [i].set = pb->set_method->mhandle;
8394         }
8395 }
8396
8397 MonoReflectionEvent *
8398 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8399 {
8400         MonoEvent *event = g_new0 (MonoEvent, 1);
8401         MonoClass *klass;
8402         int j;
8403
8404         klass = my_mono_class_from_mono_type (tb->type.type);
8405
8406         event->parent = klass;
8407         event->attrs = eb->attrs;
8408         event->name = mono_string_to_utf8 (eb->name);
8409         if (eb->add_method)
8410                 event->add = eb->add_method->mhandle;
8411         if (eb->remove_method)
8412                 event->remove = eb->remove_method->mhandle;
8413         if (eb->raise_method)
8414                 event->raise = eb->raise_method->mhandle;
8415
8416         if (eb->other_methods) {
8417                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8418                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8419                         MonoReflectionMethodBuilder *mb = 
8420                                 mono_array_get (eb->other_methods,
8421                                                 MonoReflectionMethodBuilder*, j);
8422                         event->other [j] = mb->mhandle;
8423                 }
8424         }
8425
8426         return mono_event_get_object (mono_object_domain (tb), klass, event);
8427 }
8428
8429 static void
8430 typebuilder_setup_events (MonoClass *klass)
8431 {
8432         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8433         MonoReflectionEventBuilder *eb;
8434         int i, j;
8435
8436         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8437         klass->event.first = 0;
8438         klass->event.last = klass->event.count;
8439
8440         klass->events = g_new0 (MonoEvent, klass->event.count);
8441         for (i = 0; i < klass->event.count; ++i) {
8442                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8443                 klass->events [i].parent = klass;
8444                 klass->events [i].attrs = eb->attrs;
8445                 klass->events [i].name = mono_string_to_utf8 (eb->name);
8446                 if (eb->add_method)
8447                         klass->events [i].add = eb->add_method->mhandle;
8448                 if (eb->remove_method)
8449                         klass->events [i].remove = eb->remove_method->mhandle;
8450                 if (eb->raise_method)
8451                         klass->events [i].raise = eb->raise_method->mhandle;
8452
8453                 if (eb->other_methods) {
8454                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8455                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8456                                 MonoReflectionMethodBuilder *mb = 
8457                                         mono_array_get (eb->other_methods,
8458                                                                         MonoReflectionMethodBuilder*, j);
8459                                 klass->events [i].other [j] = mb->mhandle;
8460                         }
8461                 }
8462         }
8463 }
8464
8465 MonoReflectionType*
8466 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8467 {
8468         MonoClass *klass;
8469         MonoReflectionType* res;
8470         int i;
8471
8472         MONO_ARCH_SAVE_REGS;
8473
8474         klass = my_mono_class_from_mono_type (tb->type.type);
8475
8476         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8477
8478         /*
8479          * Fields to set in klass:
8480          * the various flags: delegate/unicode/contextbound etc.
8481          */
8482         klass->flags = tb->attrs;
8483
8484         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8485                 /* No need to fully construct the type */
8486                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8487
8488         /* enums are done right away */
8489         if (!klass->enumtype)
8490                 ensure_runtime_vtable (klass);
8491
8492         if (tb->subtypes) {
8493                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8494                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8495                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8496                 }
8497         }
8498
8499         /* fields and object layout */
8500         if (klass->parent) {
8501                 if (!klass->parent->size_inited)
8502                         mono_class_init (klass->parent);
8503                 klass->instance_size += klass->parent->instance_size;
8504                 klass->class_size += klass->parent->class_size;
8505                 klass->min_align = klass->parent->min_align;
8506         } else {
8507                 klass->instance_size = sizeof (MonoObject);
8508                 klass->min_align = 1;
8509         }
8510
8511         /* FIXME: handle packing_size and instance_size */
8512         typebuilder_setup_fields (klass);
8513
8514         typebuilder_setup_properties (klass);
8515
8516         typebuilder_setup_events (klass);
8517
8518         klass->wastypebuilder = TRUE;
8519
8520         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8521         g_assert (res != (MonoReflectionType*)tb);
8522         return res;
8523 }
8524
8525 void
8526 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8527 {
8528         MonoGenericParam *param;
8529         MonoImage *image;
8530
8531         MONO_ARCH_SAVE_REGS;
8532
8533         param = g_new0 (MonoGenericParam, 1);
8534
8535         if (gparam->mbuilder) {
8536                 if (!gparam->mbuilder->generic_container)
8537                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8538                 param->owner = gparam->mbuilder->generic_container;
8539         } else if (gparam->tbuilder) {
8540                 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8541                 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8542
8543                 while (nesting) {
8544                         int count;
8545
8546                         count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8547                         if (gparam->index >= count)
8548                                 break;
8549
8550                         container = nesting->generic_container;
8551                         nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8552                 }
8553
8554                 g_assert (container);
8555                 param->owner = container;
8556         }
8557
8558         param->method = NULL;
8559         param->name = mono_string_to_utf8 (gparam->name);
8560         param->num = gparam->index;
8561
8562         image = &gparam->tbuilder->module->dynamic_image->image;
8563         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8564
8565         param->pklass->reflection_info = gparam;
8566
8567         gparam->type.type = g_new0 (MonoType, 1);
8568         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8569         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8570         gparam->type.type->data.generic_param = param;
8571 }
8572
8573 MonoArray *
8574 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8575 {
8576         MonoDynamicImage *assembly = sig->module->dynamic_image;
8577         guint32 na = mono_array_length (sig->arguments);
8578         guint32 buflen, i;
8579         MonoArray *result;
8580         char *buf, *p;
8581
8582         MONO_ARCH_SAVE_REGS;
8583
8584         p = buf = g_malloc (10 + na * 10);
8585
8586         mono_metadata_encode_value (0x07, p, &p);
8587         mono_metadata_encode_value (na, p, &p);
8588         for (i = 0; i < na; ++i) {
8589                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8590                 encode_reflection_type (assembly, type, p, &p);
8591         }
8592
8593         buflen = p - buf;
8594         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8595         p = mono_array_addr (result, char, 0);
8596         memcpy (p, buf, buflen);
8597         g_free (buf);
8598
8599         return result;
8600 }
8601
8602 MonoArray *
8603 mono_reflection_sighelper_get_signature_field (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 (0x06, p, &p);
8616         for (i = 0; i < na; ++i) {
8617                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8618                 encode_reflection_type (assembly, type, p, &p);
8619         }
8620
8621         buflen = p - buf;
8622         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8623         p = mono_array_addr (result, char, 0);
8624         memcpy (p, buf, buflen);
8625         g_free (buf);
8626
8627         return result;
8628 }
8629
8630 void 
8631 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8632 {
8633         ReflectionMethodBuilder rmb;
8634         MonoMethodSignature *sig;
8635         int i;
8636
8637         sig = dynamic_method_to_signature (mb);
8638
8639         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8640
8641         /*
8642          * Resolve references.
8643          */
8644         rmb.nrefs = mb->nrefs;
8645         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8646         for (i = 0; i < mb->nrefs; ++i) {
8647                 gpointer ref = resolve_object (mb->module->image, 
8648                                                mono_array_get (mb->refs, MonoObject*, i));
8649                 if (!ref) {
8650                         g_free (rmb.refs);
8651                         mono_raise_exception (mono_get_exception_type_load (NULL));
8652                         return;
8653                 }
8654                 rmb.refs [i] = ref;
8655         }               
8656
8657         /* FIXME: class */
8658         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8659
8660         g_free (rmb.refs);
8661
8662         /* ilgen is no longer needed */
8663         mb->ilgen = NULL;
8664 }
8665
8666 /**
8667  * mono_reflection_lookup_dynamic_token:
8668  *
8669  * Finish the Builder object pointed to by TOKEN and return the corresponding
8670  * runtime structure.
8671  */
8672 gpointer
8673 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8674 {
8675         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8676         MonoObject *obj;
8677
8678         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8679         g_assert (obj);
8680
8681         return resolve_object (image, obj);
8682 }
8683
8684 static gpointer
8685 resolve_object (MonoImage *image, MonoObject *obj)
8686 {
8687         gpointer result = NULL;
8688
8689         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8690                 result = mono_string_intern ((MonoString*)obj);
8691                 g_assert (result);
8692         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8693                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8694                 result = mono_class_from_mono_type (tb->type);
8695                 g_assert (result);
8696         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8697                 result = ((MonoReflectionMethod*)obj)->method;
8698                 g_assert (result);
8699         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8700                 result = ((MonoReflectionMethod*)obj)->method;
8701                 g_assert (result);
8702         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8703                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8704                 result = mb->mhandle;
8705                 if (!result) {
8706                         /* Type is not yet created */
8707                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8708
8709                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8710
8711                         /*
8712                          * Hopefully this has been filled in by calling CreateType() on the
8713                          * TypeBuilder.
8714                          */
8715                         /*
8716                          * TODO: This won't work if the application finishes another 
8717                          * TypeBuilder instance instead of this one.
8718                          */
8719                         result = mb->mhandle;
8720                 }
8721         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8722                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8723
8724                 result = cb->mhandle;
8725                 if (!result) {
8726                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8727
8728                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8729                         result = cb->mhandle;
8730                 }
8731         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8732                 result = ((MonoReflectionField*)obj)->field;
8733                 g_assert (result);
8734         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8735                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8736                 result = fb->handle;
8737
8738                 if (!result) {
8739                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8740
8741                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8742                         result = fb->handle;
8743                 }
8744         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8745                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8746                 MonoClass *klass;
8747
8748                 klass = tb->type.type->data.klass;
8749                 if (klass->wastypebuilder) {
8750                         /* Already created */
8751                         result = klass;
8752                 }
8753                 else {
8754                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8755                         result = tb->type.type->data.klass;
8756                         g_assert (result);
8757                 }
8758         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8759                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8760                 MonoMethodSignature *sig;
8761                 int nargs, i;
8762
8763                 if (helper->arguments)
8764                         nargs = mono_array_length (helper->arguments);
8765                 else
8766                         nargs = 0;
8767
8768                 sig = mono_metadata_signature_alloc (image, nargs);
8769                 sig->explicit_this = helper->call_conv & 64;
8770                 sig->hasthis = helper->call_conv & 32;
8771
8772                 if (helper->call_conv == 0) /* unmanaged */
8773                         sig->call_convention = helper->unmanaged_call_conv - 1;
8774                 else
8775                         if (helper->call_conv & 0x02)
8776                                 sig->call_convention = MONO_CALL_VARARG;
8777                 else
8778                         sig->call_convention = MONO_CALL_DEFAULT;
8779
8780                 sig->param_count = nargs;
8781                 /* TODO: Copy type ? */
8782                 sig->ret = helper->return_type->type;
8783                 for (i = 0; i < nargs; ++i) {
8784                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8785                         sig->params [i] = rt->type;
8786                 }
8787
8788                 result = sig;
8789         } else {
8790                 g_print (obj->vtable->klass->name);
8791                 g_assert_not_reached ();
8792         }
8793         return result;
8794 }
8795
8796
8797 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8798 const static guint32 declsec_flags_map[] = {
8799         0x00000000,                                     /* empty */
8800         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
8801         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
8802         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
8803         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
8804         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
8805         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
8806         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
8807         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
8808         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
8809         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
8810         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
8811         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
8812         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
8813         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
8814         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
8815         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
8816         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
8817         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
8818 };
8819
8820 /*
8821  * Returns flags that includes all available security action associated to the handle.
8822  * @token: metadata token (either for a class or a method)
8823  * @image: image where resides the metadata.
8824  */
8825 static guint32
8826 mono_declsec_get_flags (MonoImage *image, guint32 token)
8827 {
8828         guint32 index = mono_metadata_declsec_from_index (image, token);
8829         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8830         guint32 result = 0;
8831         guint32 action;
8832         int i;
8833
8834         for (i = index; i < t->rows; i++) {
8835                 guint32 cols [MONO_DECL_SECURITY_SIZE];
8836
8837                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8838                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8839                         break;
8840
8841                 action = cols [MONO_DECL_SECURITY_ACTION];
8842                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8843                         result |= declsec_flags_map [action];
8844                 } else {
8845                         g_assert_not_reached ();
8846                 }
8847         }
8848         return result;
8849 }
8850
8851 /*
8852  * Get the security actions (in the form of flags) associated with the specified method.
8853  *
8854  * @method: The method for which we want the declarative security flags.
8855  * Return the declarative security flags for the method (only).
8856  *
8857  * Note: To keep MonoMethod size down we do not cache the declarative security flags
8858  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
8859  */
8860 guint32
8861 mono_declsec_flags_from_method (MonoMethod *method)
8862 {
8863         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8864                 /* FIXME: No cache (for the moment) */
8865                 guint32 idx = find_method_index (method);
8866                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8867                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8868                 return mono_declsec_get_flags (method->klass->image, idx);
8869         }
8870         return 0;
8871 }
8872
8873 /*
8874  * Get the security actions (in the form of flags) associated with the specified class.
8875  *
8876  * @klass: The class for which we want the declarative security flags.
8877  * Return the declarative security flags for the class.
8878  *
8879  * Note: We cache the flags inside the MonoClass structure as this will get 
8880  *       called very often (at least for each method).
8881  */
8882 guint32
8883 mono_declsec_flags_from_class (MonoClass *klass)
8884 {
8885         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8886                 if (!klass->declsec_flags) {
8887                         guint32 idx = mono_metadata_token_index (klass->type_token);
8888                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
8889                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8890                         /* we cache the flags on classes */
8891                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8892                 }
8893                 return klass->declsec_flags;
8894         }
8895         return 0;
8896 }
8897
8898 /*
8899  * Get the security actions (in the form of flags) associated with the specified assembly.
8900  *
8901  * @assembly: The assembly for which we want the declarative security flags.
8902  * Return the declarative security flags for the assembly.
8903  */
8904 guint32
8905 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8906 {
8907         guint32 idx = 1; /* there is only one assembly */
8908         idx <<= MONO_HAS_DECL_SECURITY_BITS;
8909         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8910         return mono_declsec_get_flags (assembly->image, idx);
8911 }