2004-12-03 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         CACHE_OBJECT (assembly, res, NULL);
5076         return res;
5077 }
5078
5079
5080
5081 MonoReflectionModule*   
5082 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5083 {
5084         static MonoClass *System_Reflection_Module;
5085         MonoReflectionModule *res;
5086         char* basename;
5087         
5088         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5089         if (!System_Reflection_Module)
5090                 System_Reflection_Module = mono_class_from_name (
5091                         mono_defaults.corlib, "System.Reflection", "Module");
5092         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5093
5094         res->image = image;
5095         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5096
5097         res->fqname    = mono_string_new (domain, image->name);
5098         res->name      = mono_string_new (domain, basename = g_path_get_basename (image->name));
5099         res->scopename = mono_string_new (domain, image->module_name);
5100         
5101         g_free (basename);
5102
5103         if (image->assembly->image == image) {
5104                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5105         } else {
5106                 int i;
5107                 g_assert (image->assembly->image->modules);
5108                 res->token = 0;
5109                 for (i = 0; i < image->assembly->image->module_count; i++) {
5110                         if (image->assembly->image->modules [i] == image)
5111                                 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5112                 }
5113                 g_assert (res->token);
5114         }
5115
5116         mono_image_addref (image);
5117
5118         CACHE_OBJECT (image, res, NULL);
5119         return res;
5120 }
5121
5122 MonoReflectionModule*   
5123 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5124 {
5125         static MonoClass *System_Reflection_Module;
5126         MonoReflectionModule *res;
5127         MonoTableInfo *table;
5128         guint32 cols [MONO_FILE_SIZE];
5129         const char *name;
5130         guint32 i, name_idx;
5131         const char *val;
5132         
5133         if (!System_Reflection_Module)
5134                 System_Reflection_Module = mono_class_from_name (
5135                         mono_defaults.corlib, "System.Reflection", "Module");
5136         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5137
5138         table = &image->tables [MONO_TABLE_FILE];
5139         g_assert (table_index < table->rows);
5140         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5141
5142         res->image = 0;
5143         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5144         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5145
5146         /* Check whenever the row has a corresponding row in the moduleref table */
5147         table = &image->tables [MONO_TABLE_MODULEREF];
5148         for (i = 0; i < table->rows; ++i) {
5149                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5150                 val = mono_metadata_string_heap (image, name_idx);
5151                 if (strcmp (val, name) == 0)
5152                         res->image = image->modules [i];
5153         }
5154
5155         res->fqname    = mono_string_new (domain, name);
5156         res->name      = mono_string_new (domain, name);
5157         res->scopename = mono_string_new (domain, name);
5158         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5159         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5160
5161         return res;
5162 }
5163
5164 static gboolean
5165 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5166 {
5167         if ((t1->type != t2->type) ||
5168             (t1->byref != t2->byref))
5169                 return FALSE;
5170
5171         switch (t1->type) {
5172         case MONO_TYPE_VOID:
5173         case MONO_TYPE_BOOLEAN:
5174         case MONO_TYPE_CHAR:
5175         case MONO_TYPE_I1:
5176         case MONO_TYPE_U1:
5177         case MONO_TYPE_I2:
5178         case MONO_TYPE_U2:
5179         case MONO_TYPE_I4:
5180         case MONO_TYPE_U4:
5181         case MONO_TYPE_I8:
5182         case MONO_TYPE_U8:
5183         case MONO_TYPE_R4:
5184         case MONO_TYPE_R8:
5185         case MONO_TYPE_STRING:
5186         case MONO_TYPE_I:
5187         case MONO_TYPE_U:
5188         case MONO_TYPE_OBJECT:
5189         case MONO_TYPE_TYPEDBYREF:
5190                 return TRUE;
5191         case MONO_TYPE_VALUETYPE:
5192         case MONO_TYPE_CLASS:
5193         case MONO_TYPE_SZARRAY:
5194                 return t1->data.klass == t2->data.klass;
5195         case MONO_TYPE_PTR:
5196                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5197         case MONO_TYPE_ARRAY:
5198                 if (t1->data.array->rank != t2->data.array->rank)
5199                         return FALSE;
5200                 return t1->data.array->eklass == t2->data.array->eklass;
5201         case MONO_TYPE_GENERICINST: {
5202                 int i;
5203                 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5204                         return FALSE;
5205                 if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
5206                         return FALSE;
5207                 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5208                         if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5209                                 return FALSE;
5210                 }
5211                 return TRUE;
5212         }
5213         case MONO_TYPE_VAR:
5214         case MONO_TYPE_MVAR:
5215                 return t1->data.generic_param == t2->data.generic_param;
5216         default:
5217                 g_error ("implement type compare for %0x!", t1->type);
5218                 return FALSE;
5219         }
5220
5221         return FALSE;
5222 }
5223
5224 static guint
5225 mymono_metadata_type_hash (MonoType *t1)
5226 {
5227         guint hash;
5228
5229         hash = t1->type;
5230
5231         hash |= t1->byref << 6; /* do not collide with t1->type values */
5232         switch (t1->type) {
5233         case MONO_TYPE_VALUETYPE:
5234         case MONO_TYPE_CLASS:
5235         case MONO_TYPE_SZARRAY:
5236                 /* check if the distribution is good enough */
5237                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5238         case MONO_TYPE_PTR:
5239                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5240         }
5241         return hash;
5242 }
5243
5244 static MonoReflectionGenericClass*
5245 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5246 {
5247         static MonoClass *System_Reflection_MonoGenericClass;
5248         MonoReflectionGenericClass *res;
5249         MonoGenericClass *gclass;
5250         MonoClass *gklass;
5251
5252         if (!System_Reflection_MonoGenericClass) {
5253                 System_Reflection_MonoGenericClass = mono_class_from_name (
5254                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5255                 g_assert (System_Reflection_MonoGenericClass);
5256         }
5257
5258         gclass = geninst->data.generic_class;
5259         gklass = mono_class_from_mono_type (gclass->generic_type);
5260
5261         mono_class_init (gclass->klass);
5262
5263         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5264
5265         res->type.type = geninst;
5266         if (gklass->wastypebuilder && gklass->reflection_info)
5267                 res->generic_type = gklass->reflection_info;
5268         else
5269                 res->generic_type = mono_type_get_object (domain, gclass->generic_type);
5270
5271         return res;
5272 }
5273
5274 /*
5275  * mono_type_get_object:
5276  * @domain: an app domain
5277  * @type: a type
5278  *
5279  * Return an System.MonoType object representing the type @type.
5280  */
5281 MonoReflectionType*
5282 mono_type_get_object (MonoDomain *domain, MonoType *type)
5283 {
5284         MonoReflectionType *res;
5285         MonoClass *klass = mono_class_from_mono_type (type);
5286
5287         mono_domain_lock (domain);
5288         if (!domain->type_hash)
5289                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
5290                                 (GCompareFunc)mymono_metadata_type_equal);
5291         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5292                 mono_domain_unlock (domain);
5293                 return res;
5294         }
5295         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5296                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5297                 mono_g_hash_table_insert (domain->type_hash, type, res);
5298                 mono_domain_unlock (domain);
5299                 return res;
5300         }
5301         if (klass->reflection_info && !klass->wastypebuilder) {
5302                 /* g_assert_not_reached (); */
5303                 /* should this be considered an error condition? */
5304                 if (!type->byref) {
5305                         mono_domain_unlock (domain);
5306                         return klass->reflection_info;
5307                 }
5308         }
5309         mono_class_init (klass);
5310         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5311         res->type = type;
5312         mono_g_hash_table_insert (domain->type_hash, type, res);
5313         mono_domain_unlock (domain);
5314         return res;
5315 }
5316
5317 /*
5318  * mono_method_get_object:
5319  * @domain: an app domain
5320  * @method: a method
5321  * @refclass: the reflected type (can be NULL)
5322  *
5323  * Return an System.Reflection.MonoMethod object representing the method @method.
5324  */
5325 MonoReflectionMethod*
5326 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5327 {
5328         /*
5329          * We use the same C representation for methods and constructors, but the type 
5330          * name in C# is different.
5331          */
5332         const char *cname;
5333         MonoClass *klass;
5334         MonoReflectionMethod *ret;
5335
5336         if (!refclass)
5337                 refclass = method->klass;
5338
5339         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5340         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5341                 cname = "MonoCMethod";
5342         else
5343                 cname = "MonoMethod";
5344         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5345
5346         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5347         ret->method = method;
5348         ret->name = mono_string_new (domain, method->name);
5349         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5350         CACHE_OBJECT (method, ret, refclass);
5351         return ret;
5352 }
5353
5354 /*
5355  * mono_field_get_object:
5356  * @domain: an app domain
5357  * @klass: a type
5358  * @field: a field
5359  *
5360  * Return an System.Reflection.MonoField object representing the field @field
5361  * in class @klass.
5362  */
5363 MonoReflectionField*
5364 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5365 {
5366         MonoReflectionField *res;
5367         MonoClass *oklass;
5368
5369         CHECK_OBJECT (MonoReflectionField *, field, klass);
5370         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5371         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5372         res->klass = klass;
5373         res->field = field;
5374         res->name = mono_string_new (domain, field->name);
5375         if (field->generic_info)
5376                 res->attrs = field->generic_info->generic_type->attrs;
5377         else
5378                 res->attrs = field->type->attrs;
5379         res->type = mono_type_get_object (domain, field->type);
5380         CACHE_OBJECT (field, res, klass);
5381         return res;
5382 }
5383
5384 /*
5385  * mono_property_get_object:
5386  * @domain: an app domain
5387  * @klass: a type
5388  * @property: a property
5389  *
5390  * Return an System.Reflection.MonoProperty object representing the property @property
5391  * in class @klass.
5392  */
5393 MonoReflectionProperty*
5394 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5395 {
5396         MonoReflectionProperty *res;
5397         MonoClass *oklass;
5398
5399         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5400         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5401         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5402         res->klass = klass;
5403         res->property = property;
5404         CACHE_OBJECT (property, res, klass);
5405         return res;
5406 }
5407
5408 /*
5409  * mono_event_get_object:
5410  * @domain: an app domain
5411  * @klass: a type
5412  * @event: a event
5413  *
5414  * Return an System.Reflection.MonoEvent object representing the event @event
5415  * in class @klass.
5416  */
5417 MonoReflectionEvent*
5418 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5419 {
5420         MonoReflectionEvent *res;
5421         MonoClass *oklass;
5422
5423         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5424         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5425         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5426         res->klass = klass;
5427         res->event = event;
5428         CACHE_OBJECT (event, res, klass);
5429         return res;
5430 }
5431
5432 /*
5433  * mono_param_get_objects:
5434  * @domain: an app domain
5435  * @method: a method
5436  *
5437  * Return an System.Reflection.ParameterInfo array object representing the parameters
5438  * in the method @method.
5439  */
5440 MonoArray*
5441 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5442 {
5443         static MonoClass *System_Reflection_ParameterInfo;
5444         MonoArray *res = NULL;
5445         MonoReflectionMethod *member = NULL;
5446         MonoReflectionParameter *param = NULL;
5447         char **names, **blobs = NULL;
5448         MonoObject *dbnull = mono_get_dbnull_object (domain);
5449         MonoMarshalSpec **mspecs;
5450         int i;
5451
5452         if (!System_Reflection_ParameterInfo)
5453                 System_Reflection_ParameterInfo = mono_class_from_name (
5454                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5455         
5456         if (!method->signature->param_count)
5457                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5458
5459         /* Note: the cache is based on the address of the signature into the method
5460          * since we already cache MethodInfos with the method as keys.
5461          */
5462         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5463
5464         member = mono_method_get_object (domain, method, NULL);
5465         names = g_new (char *, method->signature->param_count);
5466         mono_method_get_param_names (method, (const char **) names);
5467
5468         mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5469         mono_method_get_marshal_info (method, mspecs);
5470
5471         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5472         for (i = 0; i < method->signature->param_count; ++i) {
5473                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5474                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5475                 param->MemberImpl = (MonoObject*)member;
5476                 param->NameImpl = mono_string_new (domain, names [i]);
5477                 param->PositionImpl = i;
5478                 param->AttrsImpl = method->signature->params [i]->attrs;
5479
5480                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5481                         param->DefaultValueImpl = dbnull;
5482                 } else {
5483                         MonoType *type = param->ClassImpl->type;
5484
5485                         if (!blobs) {
5486                                 blobs = g_new0 (char *, method->signature->param_count);
5487                                 get_default_param_value_blobs (method, blobs); 
5488                         }
5489
5490                         param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5491
5492                         if (!param->DefaultValueImpl) {
5493                                 param->DefaultValueImpl = dbnull;
5494                         }
5495                 }
5496
5497                 if (mspecs [i + 1])
5498                         param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5499                 
5500                 mono_array_set (res, gpointer, i, param);
5501         }
5502         g_free (names);
5503         g_free (blobs);
5504
5505         for (i = method->signature->param_count; i >= 0; i--)
5506                 if (mspecs [i])
5507                         mono_metadata_free_marshal_spec (mspecs [i]);
5508         g_free (mspecs);
5509         
5510         CACHE_OBJECT (&(method->signature), res, NULL);
5511         return res;
5512 }
5513
5514 /*
5515  * mono_method_body_get_object:
5516  * @domain: an app domain
5517  * @method: a method
5518  *
5519  * Return an System.Reflection.MethodBody object representing the method @method.
5520  */
5521 MonoReflectionMethodBody*
5522 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5523 {
5524         static MonoClass *System_Reflection_MethodBody = NULL;
5525         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5526         MonoReflectionMethodBody *ret;
5527         MonoMethodNormal *mn;
5528         MonoMethodHeader *header;
5529         int i;
5530
5531         if (!System_Reflection_MethodBody)
5532                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5533         if (!System_Reflection_LocalVariableInfo)
5534                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5535
5536         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5537
5538         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5539             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5540                 return NULL;
5541         mn = (MonoMethodNormal *)method;
5542         header = mono_method_get_header (method);
5543
5544         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5545         /* FIXME: Other fields */
5546         ret->init_locals = header->init_locals;
5547         ret->max_stack = header->max_stack;
5548         ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5549         memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5550         ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5551         for (i = 0; i < header->num_locals; ++i) {
5552                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5553                 info->local_type = mono_type_get_object (domain, header->locals [i]);
5554                 info->is_pinned = header->locals [i]->pinned;
5555                 info->local_index = 0;
5556         }
5557                 
5558         CACHE_OBJECT (method, ret, NULL);
5559         return ret;
5560 }
5561
5562 MonoObject *
5563 mono_get_dbnull_object (MonoDomain *domain)
5564 {
5565         MonoObject *obj;
5566         MonoClass *klass;
5567         static MonoClassField *dbnull_value_field = NULL;
5568         
5569         if (!dbnull_value_field) {
5570                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5571                 mono_class_init (klass);
5572                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5573                 g_assert (dbnull_value_field);
5574         }
5575         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5576         g_assert (obj);
5577         return obj;
5578 }
5579
5580
5581 static void
5582 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5583 {
5584         guint32 param_index, i, lastp, crow = 0;
5585         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5586         gint32 idx = -1;
5587
5588         MonoClass *klass = method->klass;
5589         MonoImage *image = klass->image;
5590         MonoMethodSignature *methodsig = method->signature;
5591
5592         MonoTableInfo *constt;
5593         MonoTableInfo *methodt;
5594         MonoTableInfo *paramt;
5595
5596         if (!methodsig->param_count)
5597                 return;
5598
5599         if (klass->generic_class) {
5600                 return; /* FIXME - ??? */
5601         }
5602
5603         mono_class_init (klass);
5604
5605         if (klass->image->dynamic) {
5606                 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5607                 if (aux && aux->param_defaults)
5608                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5609                 return;
5610         }
5611
5612         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5613         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5614         constt = &image->tables [MONO_TABLE_CONSTANT];
5615
5616         for (i = 0; i < klass->method.count; ++i) {
5617                 if (method == klass->methods [i]) {
5618                         idx = klass->method.first + i;
5619                         break;
5620                 }
5621         }
5622
5623         g_assert (idx != -1);
5624
5625         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5626         if (idx + 1 < methodt->rows)
5627                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5628         else
5629                 lastp = paramt->rows + 1;
5630
5631         for (i = param_index; i < lastp; ++i) {
5632                 guint32 paramseq;
5633
5634                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5635                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5636
5637                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5638                         continue;
5639
5640                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5641                 if (!crow) {
5642                         continue;
5643                 }
5644         
5645                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5646                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5647         }
5648
5649         return;
5650 }
5651
5652 static MonoObject *
5653 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5654 {
5655         void *retval;
5656         MonoClass *klass;
5657         MonoObject *object;
5658
5659         if (!blob)
5660                 return NULL;
5661         
5662         klass = mono_class_from_mono_type (type);
5663         if (klass->valuetype) {
5664                 object = mono_object_new (domain, klass);
5665                 retval = ((gchar *) object + sizeof (MonoObject));
5666         } else {
5667                 retval = &object;
5668         }
5669                         
5670         if (!mono_get_constant_value_from_blob (domain, type->type,  blob, retval))
5671                 return object;
5672         else
5673                 return NULL;
5674 }
5675
5676 static int
5677 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5678         int found_sep;
5679         char *s;
5680
5681         memset (assembly, 0, sizeof (MonoAssemblyName));
5682         assembly->name = p;
5683         assembly->culture = "";
5684         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5685
5686         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5687                 p++;
5688         found_sep = 0;
5689         while (g_ascii_isspace (*p) || *p == ',') {
5690                 *p++ = 0;
5691                 found_sep = 1;
5692                 continue;
5693         }
5694         /* failed */
5695         if (!found_sep)
5696                 return 1;
5697         while (*p) {
5698                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5699                         p += 8;
5700                         assembly->major = strtoul (p, &s, 10);
5701                         if (s == p || *s != '.')
5702                                 return 1;
5703                         p = ++s;
5704                         assembly->minor = strtoul (p, &s, 10);
5705                         if (s == p || *s != '.')
5706                                 return 1;
5707                         p = ++s;
5708                         assembly->build = strtoul (p, &s, 10);
5709                         if (s == p || *s != '.')
5710                                 return 1;
5711                         p = ++s;
5712                         assembly->revision = strtoul (p, &s, 10);
5713                         if (s == p)
5714                                 return 1;
5715                         p = s;
5716                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5717                         p += 8;
5718                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5719                                 assembly->culture = "";
5720                                 p += 7;
5721                         } else {
5722                                 assembly->culture = p;
5723                                 while (*p && *p != ',') {
5724                                         p++;
5725                                 }
5726                         }
5727                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5728                         p += 15;
5729                         if (strncmp (p, "null", 4) == 0) {
5730                                 p += 4;
5731                         } else {
5732                                 int len;
5733                                 gchar *start = p;
5734                                 while (*p && *p != ',') {
5735                                         p++;
5736                                 }
5737                                 len = (p - start + 1);
5738                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5739                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5740                                 g_strlcpy (assembly->public_key_token, start, len);
5741                         }
5742                 } else {
5743                         while (*p && *p != ',')
5744                                 p++;
5745                 }
5746                 found_sep = 0;
5747                 while (g_ascii_isspace (*p) || *p == ',') {
5748                         *p++ = 0;
5749                         found_sep = 1;
5750                         continue;
5751                 }
5752                 /* failed */
5753                 if (!found_sep)
5754                         return 1;
5755         }
5756
5757         return 0;
5758 }
5759
5760 /*
5761  * mono_reflection_parse_type:
5762  * @name: type name
5763  *
5764  * Parse a type name as accepted by the GetType () method and output the info
5765  * extracted in the info structure.
5766  * the name param will be mangled, so, make a copy before passing it to this function.
5767  * The fields in info will be valid until the memory pointed to by name is valid.
5768  *
5769  * See also mono_type_get_name () below.
5770  *
5771  * Returns: 0 on parse error.
5772  */
5773 int
5774 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5775
5776         char *start, *p, *w, *last_point, *startn;
5777         int in_modifiers = 0;
5778         int isbyref = 0, rank;
5779
5780         start = p = w = name;
5781
5782         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5783         info->name = info->name_space = NULL;
5784         info->nested = NULL;
5785         info->modifiers = NULL;
5786
5787         /* last_point separates the namespace from the name */
5788         last_point = NULL;
5789
5790         while (*p) {
5791                 switch (*p) {
5792                 case '+':
5793                         *p = 0; /* NULL terminate the name */
5794                         startn = p + 1;
5795                         info->nested = g_list_append (info->nested, startn);
5796                         /* we have parsed the nesting namespace + name */
5797                         if (info->name)
5798                                 break;
5799                         if (last_point) {
5800                                 info->name_space = start;
5801                                 *last_point = 0;
5802                                 info->name = last_point + 1;
5803                         } else {
5804                                 info->name_space = (char *)"";
5805                                 info->name = start;
5806                         }
5807                         break;
5808                 case '.':
5809                         last_point = w;
5810                         break;
5811                 case '\\':
5812                         ++p;
5813                         break;
5814                 case '&':
5815                 case '*':
5816                 case '[':
5817                 case ',':
5818                         in_modifiers = 1;
5819                         break;
5820                 default:
5821                         break;
5822                 }
5823                 if (in_modifiers)
5824                         break;
5825                 *w++ = *p++;
5826         }
5827         
5828         if (!info->name) {
5829                 if (last_point) {
5830                         info->name_space = start;
5831                         *last_point = 0;
5832                         info->name = last_point + 1;
5833                 } else {
5834                         info->name_space = (char *)"";
5835                         info->name = start;
5836                 }
5837         }
5838         while (*p) {
5839                 switch (*p) {
5840                 case '&':
5841                         if (isbyref) /* only one level allowed by the spec */
5842                                 return 0;
5843                         isbyref = 1;
5844                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5845                         *p++ = 0;
5846                         break;
5847                 case '*':
5848                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5849                         *p++ = 0;
5850                         break;
5851                 case '[':
5852                         rank = 1;
5853                         *p++ = 0;
5854                         while (*p) {
5855                                 if (*p == ']')
5856                                         break;
5857                                 if (*p == ',')
5858                                         rank++;
5859                                 else if (*p != '*') /* '*' means unknown lower bound */
5860                                         return 0;
5861                                 ++p;
5862                         }
5863                         if (*p++ != ']')
5864                                 return 0;
5865                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5866                         break;
5867                 case ',':
5868                         *p++ = 0;
5869                         while (*p) {
5870                                 if (g_ascii_isspace (*p)) {
5871                                         ++p;
5872                                         continue;
5873                                 }
5874                                 break;
5875                         }
5876                         if (!*p)
5877                                 return 0; /* missing assembly name */
5878                         if (!assembly_name_to_aname (&info->assembly, p))
5879                                 return 0;
5880                         break;
5881                 default:
5882                         return 0;
5883                         break;
5884                 }
5885                 if (info->assembly.name)
5886                         break;
5887         }
5888         *w = 0; /* terminate class name */
5889         if (!info->name || !*info->name)
5890                 return 0;
5891         /* add other consistency checks */
5892         return 1;
5893 }
5894
5895 static MonoType*
5896 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5897 {
5898         MonoClass *klass;
5899         GList *mod;
5900         int modval;
5901         
5902         if (!image)
5903                 image = mono_defaults.corlib;
5904
5905         if (ignorecase)
5906                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5907         else
5908                 klass = mono_class_from_name (image, info->name_space, info->name);
5909         if (!klass)
5910                 return NULL;
5911         for (mod = info->nested; mod; mod = mod->next) {
5912                 GList *nested;
5913
5914                 mono_class_init (klass);
5915                 nested = klass->nested_classes;
5916                 klass = NULL;
5917                 while (nested) {
5918                         klass = nested->data;
5919                         if (ignorecase) {
5920                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5921                                         break;
5922                         } else {
5923                                 if (strcmp (klass->name, mod->data) == 0)
5924                                         break;
5925                         }
5926                         klass = NULL;
5927                         nested = nested->next;
5928                 }
5929                 if (!klass)
5930                         break;
5931         }
5932         if (!klass)
5933                 return NULL;
5934         mono_class_init (klass);
5935         for (mod = info->modifiers; mod; mod = mod->next) {
5936                 modval = GPOINTER_TO_UINT (mod->data);
5937                 if (!modval) { /* byref: must be last modifier */
5938                         return &klass->this_arg;
5939                 } else if (modval == -1) {
5940                         klass = mono_ptr_class_get (&klass->byval_arg);
5941                 } else { /* array rank */
5942                         klass = mono_array_class_get (klass, modval);
5943                 }
5944                 mono_class_init (klass);
5945         }
5946
5947         return &klass->byval_arg;
5948 }
5949
5950 /*
5951  * mono_reflection_get_type:
5952  * @image: a metadata context
5953  * @info: type description structure
5954  * @ignorecase: flag for case-insensitive string compares
5955  * @type_resolve: whenever type resolve was already tried
5956  *
5957  * Build a MonoType from the type description in @info.
5958  * 
5959  */
5960
5961 MonoType*
5962 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5963 {
5964         MonoType *type;
5965         MonoReflectionAssembly *assembly;
5966         GString *fullName;
5967         GList *mod;
5968
5969         type = mono_reflection_get_type_internal (image, info, ignorecase);
5970         if (type)
5971                 return type;
5972         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5973                 return NULL;
5974
5975         if (type_resolve) {
5976                 if (*type_resolve) 
5977                         return NULL;
5978                 else
5979                         *type_resolve = TRUE;
5980         }
5981         
5982         /* Reconstruct the type name */
5983         fullName = g_string_new ("");
5984         if (info->name_space && (info->name_space [0] != '\0'))
5985                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5986         else
5987                 g_string_printf (fullName, info->name);
5988         for (mod = info->nested; mod; mod = mod->next)
5989                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5990
5991         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5992         if (assembly) {
5993                 if (assembly->assembly->dynamic) {
5994                         /* Enumerate all modules */
5995                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5996                         int i;
5997
5998                         type = NULL;
5999                         if (abuilder->modules) {
6000                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6001                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6002                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6003                                         if (type)
6004                                                 break;
6005                                 }
6006                         }
6007
6008                         if (!type && abuilder->loaded_modules) {
6009                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6010                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6011                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6012                                         if (type)
6013                                                 break;
6014                                 }
6015                         }
6016                 }
6017                 else
6018                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
6019                                                                                                           info, ignorecase);
6020         }
6021         g_string_free (fullName, TRUE);
6022         return type;
6023 }
6024
6025 /*
6026  * mono_reflection_type_from_name:
6027  * @name: type name.
6028  * @image: a metadata context (can be NULL).
6029  *
6030  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6031  * it defaults to get the type from @image or, if @image is NULL or loading
6032  * from it fails, uses corlib.
6033  * 
6034  */
6035 MonoType*
6036 mono_reflection_type_from_name (char *name, MonoImage *image)
6037 {
6038         MonoType *type;
6039         MonoTypeNameParse info;
6040         MonoAssembly *assembly;
6041         char *tmp;
6042         gboolean type_resolve = FALSE;
6043
6044         /* Make a copy since parse_type modifies its argument */
6045         tmp = g_strdup (name);
6046         
6047         /*g_print ("requested type %s\n", str);*/
6048         if (!mono_reflection_parse_type (tmp, &info)) {
6049                 g_free (tmp);
6050                 g_list_free (info.modifiers);
6051                 g_list_free (info.nested);
6052                 return NULL;
6053         }
6054
6055         if (info.assembly.name) {
6056                 assembly = mono_assembly_loaded (&info.assembly);
6057                 if (!assembly) {
6058                         /* then we must load the assembly ourselve - see #60439 */
6059                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6060                         if (!assembly) {
6061                                 g_free (tmp);
6062                                 g_list_free (info.modifiers);
6063                                 g_list_free (info.nested);
6064                                 return NULL;
6065                         }
6066                 }
6067                 image = assembly->image;
6068         } else if (image == NULL) {
6069                 image = mono_defaults.corlib;
6070         }
6071
6072         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6073         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6074                 image = mono_defaults.corlib;
6075                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6076         }
6077
6078         g_free (tmp);
6079         g_list_free (info.modifiers);
6080         g_list_free (info.nested);
6081         return type;
6082 }
6083
6084 /*
6085  * mono_reflection_get_token:
6086  *
6087  *   Return the metadata token of OBJ which should be an object
6088  * representing a metadata element.
6089  */
6090 guint32
6091 mono_reflection_get_token (MonoObject *obj)
6092 {
6093         MonoClass *klass;
6094         guint32 token = 0;
6095
6096         klass = obj->vtable->klass;
6097
6098         if (strcmp (klass->name, "MethodBuilder") == 0) {
6099                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6100
6101                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6102         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6103                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6104
6105                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6106         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6107                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6108                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6109                 if (tb->generic_params) {
6110                         g_assert_not_reached ();
6111                 } else {
6112                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6113                 }
6114         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6115                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6116                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6117         } else if (strcmp (klass->name, "MonoType") == 0) {
6118                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6119                 token = mono_class_from_mono_type (tb->type)->type_token;
6120         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6121                         strcmp (klass->name, "MonoMethod") == 0) {
6122                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6123                 if (m->method->signature->is_inflated) {
6124                         g_assert_not_reached ();
6125                 } else if (m->method->signature->generic_param_count) {
6126                         g_assert_not_reached ();
6127                 } else if (m->method->klass->generic_class) {
6128                         g_assert_not_reached ();
6129                 } else {
6130                         token = m->method->token;
6131                 }
6132         } else if (strcmp (klass->name, "MonoField") == 0) {
6133                 MonoReflectionField *f = (MonoReflectionField*)obj;
6134
6135                 token = mono_class_get_field_token (f->field);
6136         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6137                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6138
6139                 token = mono_class_get_property_token (p->property);
6140         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6141                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6142
6143                 token = mono_class_get_event_token (p->event);
6144         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6145                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6146
6147                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6148         } else if (strcmp (klass->name, "Module") == 0) {
6149                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6150
6151                 token = m->token;
6152         } else if (strcmp (klass->name, "Assembly") == 0) {
6153                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6154         } else {
6155                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6156                 MonoException *ex = mono_get_exception_not_implemented (msg);
6157                 g_free (msg);
6158                 mono_raise_exception (ex);
6159         }
6160
6161         return token;
6162 }
6163
6164 static void*
6165 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6166 {
6167         int slen, type = t->type;
6168 handle_enum:
6169         switch (type) {
6170         case MONO_TYPE_U1:
6171         case MONO_TYPE_I1:
6172         case MONO_TYPE_BOOLEAN: {
6173                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6174                 *bval = *p;
6175                 *end = p + 1;
6176                 return bval;
6177         }
6178         case MONO_TYPE_CHAR:
6179         case MONO_TYPE_U2:
6180         case MONO_TYPE_I2: {
6181                 guint16 *val = g_malloc (sizeof (guint16));
6182                 *val = read16 (p);
6183                 *end = p + 2;
6184                 return val;
6185         }
6186 #if SIZEOF_VOID_P == 4
6187         case MONO_TYPE_U:
6188         case MONO_TYPE_I:
6189 #endif
6190         case MONO_TYPE_R4:
6191         case MONO_TYPE_U4:
6192         case MONO_TYPE_I4: {
6193                 guint32 *val = g_malloc (sizeof (guint32));
6194                 *val = read32 (p);
6195                 *end = p + 4;
6196                 return val;
6197         }
6198 #if SIZEOF_VOID_P == 8
6199         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6200         case MONO_TYPE_I:
6201 #endif
6202         case MONO_TYPE_R8:
6203         case MONO_TYPE_U8:
6204         case MONO_TYPE_I8: {
6205                 guint64 *val = g_malloc (sizeof (guint64));
6206                 *val = read64 (p);
6207                 *end = p + 8;
6208                 return val;
6209         }
6210         case MONO_TYPE_VALUETYPE:
6211                 if (t->data.klass->enumtype) {
6212                         type = t->data.klass->enum_basetype->type;
6213                         goto handle_enum;
6214                 } else {
6215                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6216                 }
6217                 break;
6218         case MONO_TYPE_STRING:
6219                 if (*p == (char)0xFF) {
6220                         *end = p + 1;
6221                         return NULL;
6222                 }
6223                 slen = mono_metadata_decode_value (p, &p);
6224                 *end = p + slen;
6225                 return mono_string_new_len (mono_domain_get (), p, slen);
6226         case MONO_TYPE_CLASS: {
6227                 char *n;
6228                 MonoType *t;
6229                 if (*p == (char)0xFF) {
6230                         *end = p + 1;
6231                         return NULL;
6232                 }
6233 handle_type:
6234                 slen = mono_metadata_decode_value (p, &p);
6235                 n = g_memdup (p, slen + 1);
6236                 n [slen] = 0;
6237                 t = mono_reflection_type_from_name (n, image);
6238                 if (!t)
6239                         g_warning ("Cannot load type '%s'", n);
6240                 g_free (n);
6241                 *end = p + slen;
6242                 if (t)
6243                         return mono_type_get_object (mono_domain_get (), t);
6244                 else
6245                         return NULL;
6246         }
6247         case MONO_TYPE_OBJECT: {
6248                 char subt = *p++;
6249                 MonoObject *obj;
6250                 MonoClass *subc = NULL;
6251                 void *val;
6252
6253                 if (subt == 0x50) {
6254                         goto handle_type;
6255                 } else if (subt == 0x0E) {
6256                         type = MONO_TYPE_STRING;
6257                         goto handle_enum;
6258                 } else if (subt == 0x55) {
6259                         char *n;
6260                         MonoType *t;
6261                         slen = mono_metadata_decode_value (p, &p);
6262                         n = g_memdup (p, slen + 1);
6263                         n [slen] = 0;
6264                         t = mono_reflection_type_from_name (n, image);
6265                         if (!t)
6266                                 g_warning ("Cannot load type '%s'", n);
6267                         g_free (n);
6268                         p += slen;
6269                         subc = mono_class_from_mono_type (t);
6270                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6271                         MonoType simple_type = {{0}};
6272                         simple_type.type = subt;
6273                         subc = mono_class_from_mono_type (&simple_type);
6274                 } else {
6275                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6276                 }
6277                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6278                 obj = mono_object_new (mono_domain_get (), subc);
6279                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6280                 g_free (val);
6281                 return obj;
6282         }
6283         case MONO_TYPE_SZARRAY: {
6284                 MonoArray *arr;
6285                 guint32 i, alen, basetype;
6286                 alen = read32 (p);
6287                 p += 4;
6288                 if (alen == 0xffffffff) {
6289                         *end = p;
6290                         return NULL;
6291                 }
6292                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6293                 basetype = t->data.klass->byval_arg.type;
6294                 switch (basetype)
6295                 {
6296                         case MONO_TYPE_U1:
6297                         case MONO_TYPE_I1:
6298                         case MONO_TYPE_BOOLEAN:
6299                                 for (i = 0; i < alen; i++) {
6300                                         MonoBoolean val = *p++;
6301                                         mono_array_set (arr, MonoBoolean, i, val);
6302                                 }
6303                                 break;
6304                         case MONO_TYPE_CHAR:
6305                         case MONO_TYPE_U2:
6306                         case MONO_TYPE_I2:
6307                                 for (i = 0; i < alen; i++) {
6308                                         guint16 val = read16 (p);
6309                                         mono_array_set (arr, guint16, i, val);
6310                                         p += 2;
6311                                 }
6312                                 break;
6313                         case MONO_TYPE_R4:
6314                         case MONO_TYPE_U4:
6315                         case MONO_TYPE_I4:
6316                                 for (i = 0; i < alen; i++) {
6317                                         guint32 val = read32 (p);
6318                                         mono_array_set (arr, guint32, i, val);
6319                                         p += 4;
6320                                 }
6321                                 break;
6322                         case MONO_TYPE_R8:
6323                         case MONO_TYPE_U8:
6324                         case MONO_TYPE_I8:
6325                                 for (i = 0; i < alen; i++) {
6326                                         guint64 val = read64 (p);
6327                                         mono_array_set (arr, guint64, i, val);
6328                                         p += 8;
6329                                 }
6330                                 break;
6331                         case MONO_TYPE_CLASS:
6332                         case MONO_TYPE_OBJECT:
6333                         case MONO_TYPE_STRING:
6334                                 for (i = 0; i < alen; i++) {
6335                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6336                                         mono_array_set (arr, gpointer, i, item);
6337                                 }
6338                                 break;
6339                         default:
6340                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6341                 }
6342                 *end=p;
6343                 return arr;
6344         }
6345         default:
6346                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6347         }
6348         return NULL;
6349 }
6350
6351 static gboolean
6352 type_is_reference (MonoType *type)
6353 {
6354         switch (type->type) {
6355         case MONO_TYPE_BOOLEAN:
6356         case MONO_TYPE_CHAR:
6357         case MONO_TYPE_U:
6358         case MONO_TYPE_I:
6359         case MONO_TYPE_U1:
6360         case MONO_TYPE_I1:
6361         case MONO_TYPE_U2:
6362         case MONO_TYPE_I2:
6363         case MONO_TYPE_U4:
6364         case MONO_TYPE_I4:
6365         case MONO_TYPE_U8:
6366         case MONO_TYPE_I8:
6367         case MONO_TYPE_R8:
6368         case MONO_TYPE_R4:
6369         case MONO_TYPE_VALUETYPE:
6370                 return FALSE;
6371         default:
6372                 return TRUE;
6373         }
6374 }
6375
6376 static void
6377 free_param_data (MonoMethodSignature *sig, void **params) {
6378         int i;
6379         for (i = 0; i < sig->param_count; ++i) {
6380                 if (!type_is_reference (sig->params [i]))
6381                         g_free (params [i]);
6382         }
6383 }
6384
6385 /*
6386  * Find the method index in the metadata methodDef table.
6387  * Later put these three helper methods in metadata and export them.
6388  */
6389 static guint32
6390 find_method_index (MonoMethod *method) {
6391         MonoClass *klass = method->klass;
6392         int i;
6393
6394         for (i = 0; i < klass->method.count; ++i) {
6395                 if (method == klass->methods [i])
6396                         return klass->method.first + 1 + i;
6397         }
6398         return 0;
6399 }
6400
6401 /*
6402  * Find the field index in the metadata FieldDef table.
6403  */
6404 static guint32
6405 find_field_index (MonoClass *klass, MonoClassField *field) {
6406         int i;
6407
6408         for (i = 0; i < klass->field.count; ++i) {
6409                 if (field == &klass->fields [i])
6410                         return klass->field.first + 1 + i;
6411         }
6412         return 0;
6413 }
6414
6415 /*
6416  * Find the property index in the metadata Property table.
6417  */
6418 static guint32
6419 find_property_index (MonoClass *klass, MonoProperty *property) {
6420         int i;
6421
6422         for (i = 0; i < klass->property.count; ++i) {
6423                 if (property == &klass->properties [i])
6424                         return klass->property.first + 1 + i;
6425         }
6426         return 0;
6427 }
6428
6429 /*
6430  * Find the event index in the metadata Event table.
6431  */
6432 static guint32
6433 find_event_index (MonoClass *klass, MonoEvent *event) {
6434         int i;
6435
6436         for (i = 0; i < klass->event.count; ++i) {
6437                 if (event == &klass->events [i])
6438                         return klass->event.first + 1 + i;
6439         }
6440         return 0;
6441 }
6442
6443 static MonoObject*
6444 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6445 {
6446         const char *p = data;
6447         const char *named;
6448         guint32 i, j, num_named;
6449         MonoObject *attr;
6450         void **params;
6451
6452         mono_class_init (method->klass);
6453
6454         if (len == 0) {
6455                 attr = mono_object_new (mono_domain_get (), method->klass);
6456                 mono_runtime_invoke (method, attr, NULL, NULL);
6457                 return attr;
6458         }
6459
6460         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6461                 return NULL;
6462
6463         /*g_print ("got attr %s\n", method->klass->name);*/
6464         
6465         params = g_new (void*, method->signature->param_count);
6466
6467         /* skip prolog */
6468         p += 2;
6469         for (i = 0; i < method->signature->param_count; ++i) {
6470                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6471         }
6472
6473         named = p;
6474         attr = mono_object_new (mono_domain_get (), method->klass);
6475         mono_runtime_invoke (method, attr, params, NULL);
6476         free_param_data (method->signature, params);
6477         g_free (params);
6478         num_named = read16 (named);
6479         named += 2;
6480         for (j = 0; j < num_named; j++) {
6481                 gint name_len;
6482                 char *name, named_type, data_type;
6483                 named_type = *named++;
6484                 data_type = *named++; /* type of data */
6485                 if (data_type == 0x55) {
6486                         gint type_len;
6487                         char *type_name;
6488                         type_len = mono_metadata_decode_blob_size (named, &named);
6489                         type_name = g_malloc (type_len + 1);
6490                         memcpy (type_name, named, type_len);
6491                         type_name [type_len] = 0;
6492                         named += type_len;
6493                         /* FIXME: lookup the type and check type consistency */
6494                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6495                         /* this seems to be the type of the element of the array */
6496                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6497                         named++;
6498                 }
6499                 name_len = mono_metadata_decode_blob_size (named, &named);
6500                 name = g_malloc (name_len + 1);
6501                 memcpy (name, named, name_len);
6502                 name [name_len] = 0;
6503                 named += name_len;
6504                 if (named_type == 0x53) {
6505                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6506                         void *val = load_cattr_value (image, field->type, named, &named);
6507                         mono_field_set_value (attr, field, val);
6508                         if (!type_is_reference (field->type))
6509                                 g_free (val);
6510                 } else if (named_type == 0x54) {
6511                         MonoProperty *prop;
6512                         void *pparams [1];
6513                         MonoType *prop_type;
6514
6515                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6516                         /* can we have more that 1 arg in a custom attr named property? */
6517                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6518                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6519                         mono_property_set_value (prop, attr, pparams, NULL);
6520                         if (!type_is_reference (prop_type))
6521                                 g_free (pparams [0]);
6522                 }
6523                 g_free (name);
6524         }
6525
6526         return attr;
6527 }
6528
6529 MonoArray*
6530 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6531 {
6532         MonoArray *result;
6533         MonoClass *klass;
6534         MonoObject *attr;
6535         int i;
6536
6537         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6538         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6539         for (i = 0; i < cinfo->num_attrs; ++i) {
6540                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6541                 mono_array_set (result, gpointer, i, attr);
6542         }
6543         return result;
6544 }
6545
6546 MonoCustomAttrInfo*
6547 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6548 {
6549         guint32 mtoken, i, len;
6550         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6551         MonoTableInfo *ca;
6552         MonoCustomAttrInfo *ainfo;
6553         GList *tmp, *list = NULL;
6554         const char *data;
6555
6556         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6557
6558         i = mono_metadata_custom_attrs_from_index (image, idx);
6559         if (!i)
6560                 return NULL;
6561         i --;
6562         while (i < ca->rows) {
6563                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6564                         break;
6565                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6566                 ++i;
6567         }
6568         len = g_list_length (list);
6569         if (!len)
6570                 return NULL;
6571         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6572         ainfo->num_attrs = len;
6573         ainfo->image = image;
6574         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6575                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6576                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6577                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6578                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6579                         mtoken |= MONO_TOKEN_METHOD_DEF;
6580                         break;
6581                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6582                         mtoken |= MONO_TOKEN_MEMBER_REF;
6583                         break;
6584                 default:
6585                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6586                         break;
6587                 }
6588                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6589                 if (!ainfo->attrs [i].ctor)
6590                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6591                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6592                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6593                 ainfo->attrs [i].data = data;
6594         }
6595         g_list_free (list);
6596
6597         return ainfo;
6598 }
6599
6600 MonoCustomAttrInfo*
6601 mono_custom_attrs_from_method (MonoMethod *method)
6602 {
6603         MonoCustomAttrInfo *cinfo;
6604         guint32 idx;
6605         
6606         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6607                 return cinfo;
6608         idx = find_method_index (method);
6609         idx <<= MONO_CUSTOM_ATTR_BITS;
6610         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6611         return mono_custom_attrs_from_index (method->klass->image, idx);
6612 }
6613
6614 MonoCustomAttrInfo*
6615 mono_custom_attrs_from_class (MonoClass *klass)
6616 {
6617         MonoCustomAttrInfo *cinfo;
6618         guint32 idx;
6619         
6620         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6621                 return cinfo;
6622         idx = mono_metadata_token_index (klass->type_token);
6623         idx <<= MONO_CUSTOM_ATTR_BITS;
6624         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6625         return mono_custom_attrs_from_index (klass->image, idx);
6626 }
6627
6628 MonoCustomAttrInfo*
6629 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6630 {
6631         MonoCustomAttrInfo *cinfo;
6632         guint32 idx;
6633         
6634         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6635                 return cinfo;
6636         idx = 1; /* there is only one assembly */
6637         idx <<= MONO_CUSTOM_ATTR_BITS;
6638         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6639         return mono_custom_attrs_from_index (assembly->image, idx);
6640 }
6641
6642 static MonoCustomAttrInfo*
6643 mono_custom_attrs_from_module (MonoImage *image)
6644 {
6645         MonoCustomAttrInfo *cinfo;
6646         guint32 idx;
6647         
6648         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6649                 return cinfo;
6650         idx = 1; /* there is only one module */
6651         idx <<= MONO_CUSTOM_ATTR_BITS;
6652         idx |= MONO_CUSTOM_ATTR_MODULE;
6653         return mono_custom_attrs_from_index (image, idx);
6654 }
6655
6656 MonoCustomAttrInfo*
6657 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6658 {
6659         MonoCustomAttrInfo *cinfo;
6660         guint32 idx;
6661         
6662         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6663                 return cinfo;
6664         idx = find_property_index (klass, property);
6665         idx <<= MONO_CUSTOM_ATTR_BITS;
6666         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6667         return mono_custom_attrs_from_index (klass->image, idx);
6668 }
6669
6670 MonoCustomAttrInfo*
6671 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6672 {
6673         MonoCustomAttrInfo *cinfo;
6674         guint32 idx;
6675         
6676         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6677                 return cinfo;
6678         idx = find_event_index (klass, event);
6679         idx <<= MONO_CUSTOM_ATTR_BITS;
6680         idx |= MONO_CUSTOM_ATTR_EVENT;
6681         return mono_custom_attrs_from_index (klass->image, idx);
6682 }
6683
6684 MonoCustomAttrInfo*
6685 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6686 {
6687         MonoCustomAttrInfo *cinfo;
6688         guint32 idx;
6689         
6690         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6691                 return cinfo;
6692         idx = find_field_index (klass, field);
6693         idx <<= MONO_CUSTOM_ATTR_BITS;
6694         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6695         return mono_custom_attrs_from_index (klass->image, idx);
6696 }
6697
6698 MonoCustomAttrInfo*
6699 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6700 {
6701         MonoTableInfo *ca;
6702         guint32 i, idx, method_index;
6703         guint32 param_list, param_last, param_pos, found;
6704         MonoImage *image;
6705         MonoReflectionMethodAux *aux;
6706
6707         if (method->klass->image->dynamic) {
6708                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6709                 if (!aux || !aux->param_cattr)
6710                         return NULL;
6711                 return aux->param_cattr [param];
6712         }
6713
6714         image = method->klass->image;
6715         method_index = find_method_index (method);
6716         ca = &image->tables [MONO_TABLE_METHOD];
6717
6718         if (method->klass->generic_class || method->klass->generic_container ||
6719             method->signature->generic_param_count) {
6720                 /* FIXME FIXME FIXME */
6721                 return NULL;
6722         }
6723
6724         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6725         if (method_index == ca->rows) {
6726                 ca = &image->tables [MONO_TABLE_PARAM];
6727                 param_last = ca->rows + 1;
6728         } else {
6729                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6730                 ca = &image->tables [MONO_TABLE_PARAM];
6731         }
6732         found = FALSE;
6733         for (i = param_list; i < param_last; ++i) {
6734                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6735                 if (param_pos == param) {
6736                         found = TRUE;
6737                         break;
6738                 }
6739         }
6740         if (!found)
6741                 return NULL;
6742         idx = i;
6743         idx <<= MONO_CUSTOM_ATTR_BITS;
6744         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6745         return mono_custom_attrs_from_index (image, idx);
6746 }
6747
6748 /*
6749  * mono_reflection_get_custom_attrs:
6750  * @obj: a reflection object handle
6751  *
6752  * Return an array with all the custom attributes defined of the
6753  * reflection handle @obj. The objects are fully build.
6754  */
6755 MonoArray*
6756 mono_reflection_get_custom_attrs (MonoObject *obj)
6757 {
6758         MonoClass *klass;
6759         MonoArray *result;
6760         MonoCustomAttrInfo *cinfo = NULL;
6761         
6762         MONO_ARCH_SAVE_REGS;
6763
6764         klass = obj->vtable->klass;
6765         if (klass == mono_defaults.monotype_class) {
6766                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6767                 klass = mono_class_from_mono_type (rtype->type);
6768                 cinfo = mono_custom_attrs_from_class (klass);
6769         } else if (strcmp ("Assembly", klass->name) == 0) {
6770                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6771                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6772         } else if (strcmp ("Module", klass->name) == 0) {
6773                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6774                 cinfo = mono_custom_attrs_from_module (module->image);
6775         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6776                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6777                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6778         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6779                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6780                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6781         } else if (strcmp ("MonoField", klass->name) == 0) {
6782                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6783                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6784         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6785                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6786                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6787         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6788                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6789                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6790                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6791         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6792                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6793                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6794         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6795                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6796                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6797         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6798                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6799                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6800         } else { /* handle other types here... */
6801                 g_error ("get custom attrs not yet supported for %s", klass->name);
6802         }
6803
6804         if (cinfo) {
6805                 result = mono_custom_attrs_construct (cinfo);
6806                 if (!cinfo->cached)
6807                         mono_custom_attrs_free (cinfo);
6808         } else {
6809                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6810                 result = mono_array_new (mono_domain_get (), klass, 0);
6811         }
6812
6813         return result;
6814 }
6815
6816 static MonoMethodSignature*
6817 parameters_to_signature (MonoArray *parameters) {
6818         MonoMethodSignature *sig;
6819         int count, i;
6820
6821         count = parameters? mono_array_length (parameters): 0;
6822
6823         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6824         sig->param_count = count;
6825         sig->sentinelpos = -1; /* FIXME */
6826         for (i = 0; i < count; ++i) {
6827                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6828                 sig->params [i] = pt->type;
6829         }
6830         return sig;
6831 }
6832
6833 static MonoMethodSignature*
6834 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6835         MonoMethodSignature *sig;
6836
6837         sig = parameters_to_signature (ctor->parameters);
6838         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6839         sig->ret = &mono_defaults.void_class->byval_arg;
6840         return sig;
6841 }
6842
6843 static MonoMethodSignature*
6844 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6845         MonoMethodSignature *sig;
6846
6847         sig = parameters_to_signature (method->parameters);
6848         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6849         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6850         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6851         return sig;
6852 }
6853
6854 static MonoMethodSignature*
6855 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6856         MonoMethodSignature *sig;
6857
6858         sig = parameters_to_signature (method->parameters);
6859         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6860         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6861         sig->generic_param_count = 0;
6862         return sig;
6863 }
6864
6865 static void
6866 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6867 {
6868         MonoClass *klass = mono_object_class (prop);
6869         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6870                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6871                 *name = mono_string_to_utf8 (pb->name);
6872                 *type = pb->type->type;
6873         } else {
6874                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6875                 *name = g_strdup (p->property->name);
6876                 if (p->property->get)
6877                         *type = p->property->get->signature->ret;
6878                 else
6879                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6880         }
6881 }
6882
6883 static void
6884 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6885 {
6886         MonoClass *klass = mono_object_class (field);
6887         if (strcmp (klass->name, "FieldBuilder") == 0) {
6888                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6889                 *name = mono_string_to_utf8 (fb->name);
6890                 *type = fb->type->type;
6891         } else {
6892                 MonoReflectionField *f = (MonoReflectionField *)field;
6893                 *name = g_strdup (f->field->name);
6894                 *type = f->field->type;
6895         }
6896 }
6897
6898 /*
6899  * Encode a value in a custom attribute stream of bytes.
6900  * The value to encode is either supplied as an object in argument val
6901  * (valuetypes are boxed), or as a pointer to the data in the
6902  * argument argval.
6903  * @type represents the type of the value
6904  * @buffer is the start of the buffer
6905  * @p the current position in the buffer
6906  * @buflen contains the size of the buffer and is used to return the new buffer size
6907  * if this needs to be realloced.
6908  * @retbuffer and @retp return the start and the position of the buffer
6909  */
6910 static void
6911 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6912 {
6913         MonoTypeEnum simple_type;
6914         
6915         if ((p-buffer) + 10 >= *buflen) {
6916                 char *newbuf;
6917                 *buflen *= 2;
6918                 newbuf = g_realloc (buffer, *buflen);
6919                 p = newbuf + (p-buffer);
6920                 buffer = newbuf;
6921         }
6922         if (!argval)
6923                 argval = ((char*)arg + sizeof (MonoObject));
6924         simple_type = type->type;
6925 handle_enum:
6926         switch (simple_type) {
6927         case MONO_TYPE_BOOLEAN:
6928         case MONO_TYPE_U1:
6929         case MONO_TYPE_I1:
6930                 *p++ = *argval;
6931                 break;
6932         case MONO_TYPE_CHAR:
6933         case MONO_TYPE_U2:
6934         case MONO_TYPE_I2:
6935                 swap_with_size (p, argval, 2, 1);
6936                 p += 2;
6937                 break;
6938         case MONO_TYPE_U4:
6939         case MONO_TYPE_I4:
6940         case MONO_TYPE_R4:
6941                 swap_with_size (p, argval, 4, 1);
6942                 p += 4;
6943                 break;
6944         case MONO_TYPE_U8:
6945         case MONO_TYPE_I8:
6946         case MONO_TYPE_R8:
6947                 swap_with_size (p, argval, 8, 1);
6948                 p += 8;
6949                 break;
6950         case MONO_TYPE_VALUETYPE:
6951                 if (type->data.klass->enumtype) {
6952                         simple_type = type->data.klass->enum_basetype->type;
6953                         goto handle_enum;
6954                 } else {
6955                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6956                 }
6957                 break;
6958         case MONO_TYPE_STRING: {
6959                 char *str;
6960                 guint32 slen;
6961                 if (!arg) {
6962                         *p++ = 0xFF;
6963                         break;
6964                 }
6965                 str = mono_string_to_utf8 ((MonoString*)arg);
6966                 slen = strlen (str);
6967                 if ((p-buffer) + 10 + slen >= *buflen) {
6968                         char *newbuf;
6969                         *buflen *= 2;
6970                         *buflen += slen;
6971                         newbuf = g_realloc (buffer, *buflen);
6972                         p = newbuf + (p-buffer);
6973                         buffer = newbuf;
6974                 }
6975                 mono_metadata_encode_value (slen, p, &p);
6976                 memcpy (p, str, slen);
6977                 p += slen;
6978                 g_free (str);
6979                 break;
6980         }
6981         case MONO_TYPE_CLASS: {
6982                 char *str;
6983                 guint32 slen;
6984                 MonoClass *k;
6985                 if (!arg) {
6986                         *p++ = 0xFF;
6987                         break;
6988                 }
6989                 k = mono_object_class (arg);
6990                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6991                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6992                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6993 handle_type:
6994                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6995                 slen = strlen (str);
6996                 if ((p-buffer) + 10 + slen >= *buflen) {
6997                         char *newbuf;
6998                         *buflen *= 2;
6999                         *buflen += slen;
7000                         newbuf = g_realloc (buffer, *buflen);
7001                         p = newbuf + (p-buffer);
7002                         buffer = newbuf;
7003                 }
7004                 mono_metadata_encode_value (slen, p, &p);
7005                 memcpy (p, str, slen);
7006                 p += slen;
7007                 g_free (str);
7008                 break;
7009         }
7010         case MONO_TYPE_SZARRAY: {
7011                 int len, i;
7012                 MonoClass *eclass, *arg_eclass;
7013
7014                 if (!arg) {
7015                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7016                         break;
7017                 }
7018                 len = mono_array_length ((MonoArray*)arg);
7019                 *p++ = len & 0xff;
7020                 *p++ = (len >> 8) & 0xff;
7021                 *p++ = (len >> 16) & 0xff;
7022                 *p++ = (len >> 24) & 0xff;
7023                 *retp = p;
7024                 *retbuffer = buffer;
7025                 eclass = type->data.klass;
7026                 arg_eclass = mono_object_class (arg)->element_class;
7027                 if (eclass->valuetype && arg_eclass->valuetype) {
7028                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7029                         int elsize = mono_class_array_element_size (eclass);
7030                         for (i = 0; i < len; ++i) {
7031                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7032                                 elptr += elsize;
7033                         }
7034                 } else {
7035                         for (i = 0; i < len; ++i) {
7036                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7037                         }
7038                 }
7039                 break;
7040         }
7041         /* it may be a boxed value or a Type */
7042         case MONO_TYPE_OBJECT: {
7043                 MonoClass *klass = mono_object_class (arg);
7044                 char *str;
7045                 guint32 slen;
7046                 
7047                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7048                         *p++ = 0x50;
7049                         goto handle_type;
7050                 } else if (klass->enumtype) {
7051                         *p++ = 0x55;
7052                 } else if (klass == mono_defaults.string_class) {
7053                         simple_type = MONO_TYPE_STRING;
7054                         *p++ = 0x0E;
7055                         goto handle_enum;
7056                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7057                         *p++ = simple_type = klass->byval_arg.type;
7058                         goto handle_enum;
7059                 } else {
7060                         g_error ("unhandled type in custom attr");
7061                 }
7062                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7063                 slen = strlen (str);
7064                 if ((p-buffer) + 10 + slen >= *buflen) {
7065                         char *newbuf;
7066                         *buflen *= 2;
7067                         *buflen += slen;
7068                         newbuf = g_realloc (buffer, *buflen);
7069                         p = newbuf + (p-buffer);
7070                         buffer = newbuf;
7071                 }
7072                 mono_metadata_encode_value (slen, p, &p);
7073                 memcpy (p, str, slen);
7074                 p += slen;
7075                 g_free (str);
7076                 simple_type = klass->enum_basetype->type;
7077                 goto handle_enum;
7078         }
7079         default:
7080                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7081         }
7082         *retp = p;
7083         *retbuffer = buffer;
7084 }
7085
7086 /*
7087  * mono_reflection_get_custom_attrs_blob:
7088  * @ctor: custom attribute constructor
7089  * @ctorArgs: arguments o the constructor
7090  * @properties:
7091  * @propValues:
7092  * @fields:
7093  * @fieldValues:
7094  * 
7095  * Creates the blob of data that needs to be saved in the metadata and that represents
7096  * the custom attributed described by @ctor, @ctorArgs etc.
7097  * Returns: a Byte array representing the blob of data.
7098  */
7099 MonoArray*
7100 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
7101 {
7102         MonoArray *result;
7103         MonoMethodSignature *sig;
7104         MonoObject *arg;
7105         char *buffer, *p;
7106         guint32 buflen, i;
7107
7108         MONO_ARCH_SAVE_REGS;
7109
7110         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7111                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7112         } else {
7113                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7114         }
7115         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7116         buflen = 256;
7117         p = buffer = g_malloc (buflen);
7118         /* write the prolog */
7119         *p++ = 1;
7120         *p++ = 0;
7121         for (i = 0; i < sig->param_count; ++i) {
7122                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7123                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7124         }
7125         i = 0;
7126         if (properties)
7127                 i += mono_array_length (properties);
7128         if (fields)
7129                 i += mono_array_length (fields);
7130         *p++ = i & 0xff;
7131         *p++ = (i >> 8) & 0xff;
7132         if (properties) {
7133                 MonoObject *prop;
7134                 for (i = 0; i < mono_array_length (properties); ++i) {
7135                         MonoType *ptype;
7136                         char *pname;
7137                         int len;
7138                         
7139                         prop = mono_array_get (properties, gpointer, i);
7140                         get_prop_name_and_type (prop, &pname, &ptype);
7141                         *p++ = 0x54; /* PROPERTY signature */
7142
7143                         /* Preallocate a large enough buffer */
7144                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7145                                 char *str = type_get_qualified_name (ptype, NULL);
7146                                 len = strlen (str);
7147                                 g_free (str);
7148                         }
7149                         else
7150                                 len = 0;
7151                         len += strlen (pname);
7152
7153                         if ((p-buffer) + 20 + len >= buflen) {
7154                                 char *newbuf;
7155                                 buflen *= 2;
7156                                 buflen += len;
7157                                 newbuf = g_realloc (buffer, buflen);
7158                                 p = newbuf + (p-buffer);
7159                                 buffer = newbuf;
7160                         }
7161
7162                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7163                                 char *str = type_get_qualified_name (ptype, NULL);
7164                                 int slen = strlen (str);
7165
7166                                 *p++ = 0x55;
7167                                 /*
7168                                  * This seems to be optional...
7169                                  * *p++ = 0x80;
7170                                  */
7171                                 mono_metadata_encode_value (slen, p, &p);
7172                                 memcpy (p, str, slen);
7173                                 p += slen;
7174                                 g_free (str);
7175                         } else {
7176                                 mono_metadata_encode_value (ptype->type, p, &p);
7177                                 if (ptype->type == MONO_TYPE_SZARRAY)
7178                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7179                         }
7180                         len = strlen (pname);
7181                         mono_metadata_encode_value (len, p, &p);
7182                         memcpy (p, pname, len);
7183                         p += len;
7184                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7185                         g_free (pname);
7186                 }
7187         }
7188
7189         if (fields) {
7190                 MonoObject *field;
7191                 for (i = 0; i < mono_array_length (fields); ++i) {
7192                         MonoType *ftype;
7193                         char *fname;
7194                         int len;
7195                         
7196                         field = mono_array_get (fields, gpointer, i);
7197                         get_field_name_and_type (field, &fname, &ftype);
7198                         *p++ = 0x53; /* FIELD signature */
7199                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7200                                 char *str = type_get_qualified_name (ftype, NULL);
7201                                 int slen = strlen (str);
7202                                 if ((p-buffer) + 10 + slen >= buflen) {
7203                                         char *newbuf;
7204                                         buflen *= 2;
7205                                         buflen += slen;
7206                                         newbuf = g_realloc (buffer, buflen);
7207                                         p = newbuf + (p-buffer);
7208                                         buffer = newbuf;
7209                                 }
7210                                 *p++ = 0x55;
7211                                 /*
7212                                  * This seems to be optional...
7213                                  * *p++ = 0x80;
7214                                  */
7215                                 mono_metadata_encode_value (slen, p, &p);
7216                                 memcpy (p, str, slen);
7217                                 p += slen;
7218                                 g_free (str);
7219                         } else {
7220                                 mono_metadata_encode_value (ftype->type, p, &p);
7221                                 if (ftype->type == MONO_TYPE_SZARRAY)
7222                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7223                         }
7224                         len = strlen (fname);
7225                         mono_metadata_encode_value (len, p, &p);
7226                         memcpy (p, fname, len);
7227                         p += len;
7228                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7229                         g_free (fname);
7230                 }
7231         }
7232
7233         g_assert (p - buffer <= buflen);
7234         buflen = p - buffer;
7235         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7236         p = mono_array_addr (result, char, 0);
7237         memcpy (p, buffer, buflen);
7238         g_free (buffer);
7239         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7240                 g_free (sig);
7241         return result;
7242 }
7243
7244 /*
7245  * mono_reflection_setup_internal_class:
7246  * @tb: a TypeBuilder object
7247  *
7248  * Creates a MonoClass that represents the TypeBuilder.
7249  * This is a trick that lets us simplify a lot of reflection code
7250  * (and will allow us to support Build and Run assemblies easier).
7251  */
7252 void
7253 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7254 {
7255         MonoClass *klass, *parent;
7256
7257         MONO_ARCH_SAVE_REGS;
7258
7259         if (tb->parent) {
7260                 /* check so we can compile corlib correctly */
7261                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7262                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7263                         parent = tb->parent->type->data.klass;
7264                 } else {
7265                         parent = my_mono_class_from_mono_type (tb->parent->type);
7266                 }
7267         } else {
7268                 parent = NULL;
7269         }
7270         
7271         /* the type has already being created: it means we just have to change the parent */
7272         if (tb->type.type) {
7273                 klass = mono_class_from_mono_type (tb->type.type);
7274                 klass->parent = NULL;
7275                 /* fool mono_class_setup_parent */
7276                 g_free (klass->supertypes);
7277                 klass->supertypes = NULL;
7278                 mono_class_setup_parent (klass, parent);
7279                 mono_class_setup_mono_type (klass);
7280                 return;
7281         }
7282         
7283         klass = g_new0 (MonoClass, 1);
7284
7285         klass->image = &tb->module->dynamic_image->image;
7286
7287         klass->inited = 1; /* we lie to the runtime */
7288         klass->name = mono_string_to_utf8 (tb->name);
7289         klass->name_space = mono_string_to_utf8 (tb->nspace);
7290         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7291         klass->flags = tb->attrs;
7292
7293         klass->element_class = klass;
7294         klass->reflection_info = tb; /* need to pin. */
7295
7296         /* Put into cache so mono_class_get () will find it */
7297         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7298
7299         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7300                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7301
7302         if (parent != NULL) {
7303                 mono_class_setup_parent (klass, parent);
7304         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7305                 const char *old_n = klass->name;
7306                 /* trick to get relative numbering right when compiling corlib */
7307                 klass->name = "BuildingObject";
7308                 mono_class_setup_parent (klass, mono_defaults.object_class);
7309                 klass->name = old_n;
7310         }
7311
7312         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7313                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7314                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7315                 klass->instance_size = sizeof (MonoObject);
7316                 klass->size_inited = 1;
7317                 mono_class_setup_vtable (klass, NULL, 0);
7318         }
7319
7320         mono_class_setup_mono_type (klass);
7321
7322         mono_class_setup_supertypes (klass);
7323
7324         /*
7325          * FIXME: handle interfaces.
7326          */
7327
7328         tb->type.type = &klass->byval_arg;
7329
7330         if (tb->nesting_type) {
7331                 g_assert (tb->nesting_type->type);
7332                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7333         }
7334
7335         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7336 }
7337
7338 /*
7339  * mono_reflection_setup_generic_class:
7340  * @tb: a TypeBuilder object
7341  *
7342  * Setup the generic class before adding the first generic parameter.
7343  */
7344 void
7345 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7346 {
7347         MonoClass *klass;
7348
7349         MONO_ARCH_SAVE_REGS;
7350
7351         klass = my_mono_class_from_mono_type (tb->type.type);
7352         if (tb->generic_container)
7353                 return;
7354
7355         tb->generic_container = g_new0 (MonoGenericContainer, 1);
7356         tb->generic_container->klass = klass;
7357
7358         tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7359         tb->generic_container->context->container = tb->generic_container;
7360 }
7361
7362 /*
7363  * mono_reflection_create_generic_class:
7364  * @tb: a TypeBuilder object
7365  *
7366  * Creates the generic class after all generic parameters have been added.
7367  */
7368 void
7369 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7370 {
7371         MonoClass *klass;
7372         int count, i;
7373
7374         MONO_ARCH_SAVE_REGS;
7375
7376         klass = my_mono_class_from_mono_type (tb->type.type);
7377
7378         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7379
7380         if (klass->generic_container || (count == 0))
7381                 return;
7382
7383         g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7384
7385         klass->generic_container = tb->generic_container;
7386
7387         klass->generic_container->type_argc = count;
7388         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7389
7390         for (i = 0; i < count; i++) {
7391                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7392                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7393                 g_assert (klass->generic_container->type_params [i].owner);
7394         }
7395 }
7396
7397 /*
7398  * mono_reflection_create_internal_class:
7399  * @tb: a TypeBuilder object
7400  *
7401  * Actually create the MonoClass that is associated with the TypeBuilder.
7402  */
7403 void
7404 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7405 {
7406         MonoClass *klass;
7407
7408         MONO_ARCH_SAVE_REGS;
7409
7410         klass = my_mono_class_from_mono_type (tb->type.type);
7411
7412         if (klass->enumtype && klass->enum_basetype == NULL) {
7413                 MonoReflectionFieldBuilder *fb;
7414                 MonoClass *ec;
7415
7416                 g_assert (tb->fields != NULL);
7417                 g_assert (mono_array_length (tb->fields) >= 1);
7418
7419                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7420
7421                 klass->enum_basetype = fb->type->type;
7422                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7423                 if (!klass->element_class)
7424                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7425
7426                 /*
7427                  * get the element_class from the current corlib.
7428                  */
7429                 ec = default_class_from_mono_type (klass->enum_basetype);
7430                 klass->instance_size = ec->instance_size;
7431                 klass->size_inited = 1;
7432                 /* 
7433                  * this is almost safe to do with enums and it's needed to be able
7434                  * to create objects of the enum type (for use in SetConstant).
7435                  */
7436                 /* FIXME: Does this mean enums can't have method overrides ? */
7437                 mono_class_setup_vtable (klass, NULL, 0);
7438         }
7439 }
7440
7441 static MonoMarshalSpec*
7442 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7443                                                                 MonoReflectionMarshal *minfo)
7444 {
7445         MonoMarshalSpec *res;
7446
7447         res = g_new0 (MonoMarshalSpec, 1);
7448         res->native = minfo->type;
7449
7450         switch (minfo->type) {
7451         case MONO_NATIVE_LPARRAY:
7452                 res->data.array_data.elem_type = minfo->eltype;
7453                 res->data.array_data.param_num = 0; /* Not yet */
7454                 res->data.array_data.num_elem = minfo->count;
7455                 break;
7456
7457         case MONO_NATIVE_BYVALTSTR:
7458         case MONO_NATIVE_BYVALARRAY:
7459                 res->data.array_data.num_elem = minfo->count;
7460                 break;
7461
7462         case MONO_NATIVE_CUSTOM:
7463                 if (minfo->marshaltyperef)
7464                         res->data.custom_data.custom_name =
7465                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7466                 if (minfo->mcookie)
7467                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7468                 break;
7469
7470         default:
7471                 break;
7472         }
7473
7474         return res;
7475 }
7476
7477 MonoReflectionMarshal*
7478 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7479                                                                                    MonoMarshalSpec *spec)
7480 {
7481         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7482         MonoReflectionMarshal *minfo;
7483         MonoType *mtype;
7484
7485         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7486                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7487                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7488                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7489         }
7490
7491         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7492         minfo->type = spec->native;
7493
7494         switch (minfo->type) {
7495         case MONO_NATIVE_LPARRAY:
7496                 minfo->eltype = spec->data.array_data.elem_type;
7497                 minfo->count = spec->data.array_data.num_elem;
7498                 break;
7499
7500         case MONO_NATIVE_BYVALTSTR:
7501         case MONO_NATIVE_BYVALARRAY:
7502                 minfo->count = spec->data.array_data.num_elem;
7503                 break;
7504
7505         case MONO_NATIVE_CUSTOM:
7506                 if (spec->data.custom_data.custom_name) {
7507                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7508                         if (mtype)
7509                                 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7510
7511                         minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7512                 }
7513                 if (spec->data.custom_data.cookie)
7514                         minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7515                 break;
7516
7517         default:
7518                 break;
7519         }
7520
7521         return minfo;
7522 }
7523
7524 static MonoMethod*
7525 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7526                                          ReflectionMethodBuilder *rmb,
7527                                          MonoMethodSignature *sig)
7528 {
7529         MonoMethod *m;
7530         MonoMethodNormal *pm;
7531         MonoMarshalSpec **specs;
7532         MonoReflectionMethodAux *method_aux;
7533         int i;
7534
7535         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7536                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7537                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7538         else if (rmb->refs)
7539                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7540         else
7541                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7542
7543         pm = (MonoMethodNormal*)m;
7544
7545         m->slot = -1;
7546         m->flags = rmb->attrs;
7547         m->iflags = rmb->iattrs;
7548         m->name = mono_string_to_utf8 (rmb->name);
7549         m->klass = klass;
7550         m->signature = sig;
7551         if (rmb->table_idx)
7552                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7553
7554         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7555                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7556                         m->string_ctor = 1;
7557
7558                 m->signature->pinvoke = 1;
7559         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7560                 m->signature->pinvoke = 1;
7561
7562                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7563
7564                 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7565                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7566                 
7567                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7568
7569                 if (klass->image->dynamic)
7570                         mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7571
7572                 return m;
7573         } else if (!m->klass->dummy && 
7574                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7575                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7576                 MonoMethodHeader *header;
7577                 guint32 code_size;
7578                 gint32 max_stack, i;
7579                 gint32 num_locals = 0;
7580                 gint32 num_clauses = 0;
7581                 guint8 *code;
7582
7583                 if (rmb->ilgen) {
7584                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7585                         code_size = rmb->ilgen->code_len;
7586                         max_stack = rmb->ilgen->max_stack;
7587                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7588                         if (rmb->ilgen->ex_handlers)
7589                                 num_clauses = method_count_clauses (rmb->ilgen);
7590                 } else {
7591                         if (rmb->code) {
7592                                 code = mono_array_addr (rmb->code, guint8, 0);
7593                                 code_size = mono_array_length (rmb->code);
7594                                 /* we probably need to run a verifier on the code... */
7595                                 max_stack = 8; 
7596                         }
7597                         else {
7598                                 code = NULL;
7599                                 code_size = 0;
7600                                 max_stack = 8;
7601                         }
7602                 }
7603
7604                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7605                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7606                 header->code_size = code_size;
7607                 header->code = g_malloc (code_size);
7608                 memcpy ((char*)header->code, code, code_size);
7609                 header->max_stack = max_stack;
7610                 header->init_locals = rmb->init_locals;
7611                 header->num_locals = num_locals;
7612
7613                 for (i = 0; i < num_locals; ++i) {
7614                         MonoReflectionLocalBuilder *lb = 
7615                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7616
7617                         header->locals [i] = g_new0 (MonoType, 1);
7618                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7619                 }
7620
7621                 header->num_clauses = num_clauses;
7622                 if (num_clauses) {
7623                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7624                                  rmb->ilgen, num_clauses);
7625                 }
7626
7627                 pm->header = header;
7628         }
7629
7630         if (rmb->generic_params) {
7631                 int count = mono_array_length (rmb->generic_params);
7632                 MonoGenericContainer *container;
7633
7634                 pm->generic_container = container = rmb->generic_container;
7635                 container->type_argc = count;
7636                 container->type_params = g_new0 (MonoGenericParam, count);
7637
7638                 for (i = 0; i < count; i++) {
7639                         MonoReflectionGenericParam *gp =
7640                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7641
7642                         container->type_params [i] = *gp->type.type->data.generic_param;
7643                 }
7644         }
7645
7646         if (rmb->refs) {
7647                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7648                 int i;
7649
7650                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7651
7652                 for (i = 0; i < rmb->nrefs; ++i)
7653                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7654         }
7655
7656         method_aux = NULL;
7657
7658         /* Parameter info */
7659         if (rmb->pinfo) {
7660                 if (!method_aux)
7661                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7662                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7663                 for (i = 0; i <= m->signature->param_count; ++i) {
7664                         MonoReflectionParamBuilder *pb;
7665                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7666                                 if (i > 0)
7667                                         m->signature->params [i - 1]->attrs = pb->attrs;
7668
7669                                 if (pb->def_value) {
7670                                         MonoDynamicImage *assembly;
7671                                         guint32 idx, def_type, len;
7672                                         char *p;
7673                                         const char *p2;
7674
7675                                         if (!method_aux->param_defaults)
7676                                                 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7677                                         assembly = (MonoDynamicImage*)klass->image;
7678                                         idx = encode_constant (assembly, pb->def_value, &def_type);
7679                                         /* Copy the data from the blob since it might get realloc-ed */
7680                                         p = assembly->blob.data + idx;
7681                                         len = mono_metadata_decode_blob_size (p, &p2);
7682                                         len += p2 - p;
7683                                         method_aux->param_defaults [i] = g_malloc (len);
7684                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7685                                 }
7686
7687                                 if (pb->name)
7688                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7689                                 if (pb->cattrs) {
7690                                         if (!method_aux->param_cattr)
7691                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7692                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7693                                 }
7694                         }
7695                 }
7696         }
7697
7698         /* Parameter marshalling */
7699         specs = NULL;
7700         if (rmb->pinfo)         
7701                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7702                         MonoReflectionParamBuilder *pb;
7703                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7704                                 if (pb->marshal_info) {
7705                                         if (specs == NULL)
7706                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7707                                         specs [pb->position] = 
7708                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7709                                 }
7710                         }
7711                 }
7712         if (specs != NULL) {
7713                 if (!method_aux)
7714                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7715                 method_aux->param_marshall = specs;
7716         }
7717
7718         if (klass->image->dynamic && method_aux)
7719                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7720
7721         return m;
7722 }       
7723
7724 static MonoMethod*
7725 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7726 {
7727         ReflectionMethodBuilder rmb;
7728         MonoMethodSignature *sig;
7729
7730         sig = ctor_builder_to_signature (mb);
7731
7732         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7733
7734         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7735         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7736
7737         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7738                 /* ilgen is no longer needed */
7739                 mb->ilgen = NULL;
7740         }
7741
7742         return mb->mhandle;
7743 }
7744
7745 static MonoMethod*
7746 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7747 {
7748         ReflectionMethodBuilder rmb;
7749         MonoMethodSignature *sig;
7750
7751         sig = method_builder_to_signature (mb);
7752
7753         reflection_methodbuilder_from_method_builder (&rmb, mb);
7754
7755         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7756         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7757
7758         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7759                 /* ilgen is no longer needed */
7760                 mb->ilgen = NULL;
7761         }
7762         return mb->mhandle;
7763 }
7764
7765 static MonoClassField*
7766 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7767 {
7768         MonoClassField *field;
7769         const char *p, *p2;
7770         guint32 len, idx;
7771
7772         if (fb->handle)
7773                 return fb->handle;
7774
7775         field = g_new0 (MonoClassField, 1);
7776
7777         field->name = mono_string_to_utf8 (fb->name);
7778         if (fb->attrs) {
7779                 /* FIXME: handle type modifiers */
7780                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7781                 field->type->attrs = fb->attrs;
7782         } else {
7783                 field->type = fb->type->type;
7784         }
7785         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7786                 field->data = mono_array_addr (fb->rva_data, char, 0);
7787         if (fb->offset != -1)
7788                 field->offset = fb->offset;
7789         field->parent = klass;
7790         fb->handle = field;
7791         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7792
7793         if (fb->def_value) {
7794                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7795                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7796                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7797                 /* Copy the data from the blob since it might get realloc-ed */
7798                 p = assembly->blob.data + idx;
7799                 len = mono_metadata_decode_blob_size (p, &p2);
7800                 len += p2 - p;
7801                 field->data = g_malloc (len);
7802                 memcpy ((gpointer)field->data, p, len);
7803         }
7804
7805         return field;
7806 }
7807
7808 static MonoType*
7809 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7810                                             MonoType *parent)
7811 {
7812         MonoClass *klass, *gklass;
7813         MonoReflectionTypeBuilder *tb = NULL;
7814         MonoGenericClass *gclass, *cached;
7815         MonoDomain *domain;
7816         MonoType *geninst;
7817         int icount, i;
7818
7819         klass = mono_class_from_mono_type (type->type);
7820         if (!klass->generic_container && !klass->generic_class &&
7821             !(klass->nested_in && klass->nested_in->generic_container))
7822                 return NULL;
7823
7824         mono_loader_lock ();
7825
7826         domain = mono_object_domain (type);
7827
7828         gclass = g_new0 (MonoGenericClass, 1);
7829         gclass->inst = g_new0 (MonoGenericInst, 1);
7830
7831         gclass->inst->type_argc = type_argc;
7832         gclass->inst->type_argv = types;
7833
7834         for (i = 0; i < gclass->inst->type_argc; ++i) {
7835                 if (!gclass->inst->is_open)
7836                         gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7837         }
7838
7839         gclass->generic_type = &klass->byval_arg;
7840
7841         if (klass->generic_class) {
7842                 MonoGenericClass *kgclass = klass->generic_class;
7843                 MonoGenericClass *ogclass = gclass;
7844
7845                 ogclass->context = g_new0 (MonoGenericContext, 1);
7846                 ogclass->context->gclass = ogclass;
7847
7848                 gclass = g_new0 (MonoGenericClass, 1);
7849                 gclass->inst = g_new0 (MonoGenericInst, 1);
7850
7851                 gclass->inst->type_argc = kgclass->inst->type_argc;
7852                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7853
7854                 for (i = 0; i < gclass->inst->type_argc; i++) {
7855                         MonoType *t = kgclass->inst->type_argv [i];
7856
7857                         t = mono_class_inflate_generic_type (t, ogclass->context);
7858
7859                         if (!gclass->inst->is_open)
7860                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7861
7862                         gclass->inst->type_argv [i] = t;
7863                 }
7864
7865                 gclass->generic_type = kgclass->generic_type;
7866         }
7867
7868         geninst = g_new0 (MonoType, 1);
7869         geninst->type = MONO_TYPE_GENERICINST;
7870
7871         cached = mono_metadata_lookup_generic_class (gclass);
7872         if (cached) {
7873                 g_free (gclass);
7874                 mono_loader_unlock ();
7875                 geninst->data.generic_class = cached;
7876                 return geninst;
7877         }
7878
7879         gklass = mono_class_from_mono_type (gclass->generic_type);
7880         g_assert ((gclass->container = gklass->generic_container) != NULL);
7881
7882         geninst->data.generic_class = gclass;
7883
7884         gclass->parent = parent;
7885
7886         gclass->context = g_new0 (MonoGenericContext, 1);
7887         gclass->context->gclass = gclass;
7888
7889         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7890                 tb = (MonoReflectionTypeBuilder *) type;
7891
7892                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7893                 gclass->is_dynamic = TRUE;
7894         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7895                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7896                 MonoReflectionType *rgt = rgi->generic_type;
7897
7898                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7899                 tb = (MonoReflectionTypeBuilder *) rgt;
7900
7901                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7902                 gclass->is_dynamic = TRUE;
7903         } else {
7904                 icount = klass->interface_count;
7905         }
7906
7907         gclass->ifaces = g_new0 (MonoType *, icount);
7908         gclass->count_ifaces = icount;
7909
7910         for (i = 0; i < icount; i++) {
7911                 MonoReflectionType *itype;
7912
7913                 if (tb)
7914                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7915                 else
7916                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7917                 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7918                 if (!gclass->ifaces [i])
7919                         gclass->ifaces [i] = itype->type;
7920         }
7921
7922         mono_class_create_generic (gclass);
7923         mono_class_create_generic_2 (gclass);
7924
7925         mono_loader_unlock ();
7926
7927         return geninst;
7928 }
7929
7930 MonoType*
7931 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7932 {
7933         MonoClass *klass, *pklass = NULL;
7934         MonoReflectionType *parent = NULL;
7935         MonoType *the_parent = NULL, *geninst;
7936         MonoReflectionTypeBuilder *tb = NULL;
7937         MonoGenericClass *gclass;
7938         MonoDomain *domain;
7939
7940         domain = mono_object_domain (type);
7941         klass = mono_class_from_mono_type (type->type);
7942
7943         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7944                 tb = (MonoReflectionTypeBuilder *) type;
7945
7946                 if (tb->parent) {
7947                         parent = tb->parent;
7948                         pklass = mono_class_from_mono_type (parent->type);
7949                 }
7950         } else {
7951                 pklass = klass->parent;
7952                 if (pklass)
7953                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7954                 else if (klass->generic_class && klass->generic_class->parent) {
7955                         parent = mono_type_get_object (domain, klass->generic_class->parent);
7956                         pklass = mono_class_from_mono_type (klass->generic_class->parent);
7957                 }
7958         }
7959
7960         if (pklass && pklass->generic_class)
7961                 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7962
7963         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7964         if (!geninst)
7965                 return NULL;
7966
7967         gclass = geninst->data.generic_class;
7968
7969         return geninst;
7970 }
7971
7972 static MonoType*
7973 dup_type (const MonoType *original)
7974 {
7975         MonoType *r = g_new0 (MonoType, 1);
7976         *r = *original;
7977         r->attrs = original->attrs;
7978         r->byref = original->byref;
7979         mono_stats.generics_metadata_size += sizeof (MonoType);
7980         return r;
7981 }
7982
7983 MonoReflectionMethod*
7984 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7985 {
7986         MonoMethod *method, *inflated;
7987         MonoReflectionMethodBuilder *mb = NULL;
7988         MonoGenericContainer *container;
7989         MonoGenericMethod *gmethod;
7990         MonoGenericContext *context;
7991         MonoGenericInst *ginst;
7992         int count, i;
7993
7994         MONO_ARCH_SAVE_REGS;
7995         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7996                 MonoReflectionTypeBuilder *tb;
7997                 MonoClass *klass;
7998
7999                 mb = (MonoReflectionMethodBuilder *) rmethod;
8000                 tb = (MonoReflectionTypeBuilder *) mb->type;
8001                 klass = mono_class_from_mono_type (tb->type.type);
8002
8003                 method = methodbuilder_to_mono_method (klass, mb);
8004         } else {
8005                 method = rmethod->method;
8006         }
8007
8008         count = method->signature->generic_param_count;
8009         if (count != mono_array_length (types))
8010                 return NULL;
8011
8012         container = ((MonoMethodNormal*) method)->generic_container;
8013         g_assert (container);
8014
8015         if (!container->method_hash)
8016                 container->method_hash = g_hash_table_new (
8017                         (GHashFunc) mono_metadata_generic_method_hash,
8018                         (GCompareFunc) mono_metadata_generic_method_equal);
8019
8020         ginst = g_new0 (MonoGenericInst,1 );
8021         ginst->type_argc = count;
8022         ginst->type_argv = g_new0 (MonoType *, count);
8023         for (i = 0; i < count; i++) {
8024                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8025                 ginst->type_argv [i] = dup_type (garg->type);
8026
8027                 if (!ginst->is_open)
8028                         ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8029         }
8030         ginst = mono_metadata_lookup_generic_inst (ginst);
8031
8032         gmethod = g_new0 (MonoGenericMethod, 1);
8033         gmethod->inst = ginst;
8034
8035         inflated = g_hash_table_lookup (container->method_hash, gmethod);
8036         if (inflated) {
8037                 g_free (gmethod);
8038
8039                 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8040         }
8041
8042         gmethod->reflection_info = rmethod;
8043
8044         context = g_new0 (MonoGenericContext, 1);
8045         context->gclass = method->klass->generic_class;
8046         context->gmethod = gmethod;
8047
8048         inflated = mono_class_inflate_generic_method (method, context, NULL);
8049         g_hash_table_insert (container->method_hash, gmethod, inflated);
8050
8051         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8052 }
8053
8054 static MonoMethod *
8055 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8056 {
8057         MonoGenericMethod *gmethod;
8058         MonoGenericClass *gclass;
8059         MonoGenericContext *context;
8060         int i;
8061
8062         gclass = type->type.type->data.generic_class;
8063
8064         gmethod = g_new0 (MonoGenericMethod, 1);
8065         gmethod->inst = g_new0 (MonoGenericInst, 1);
8066         gmethod->reflection_info = obj;
8067
8068         gmethod->inst->type_argc = method->signature->generic_param_count;
8069         gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8070
8071         for (i = 0; i < gmethod->inst->type_argc; i++) {
8072                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8073                 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8074
8075                 g_assert (gparam->pklass);
8076                 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8077         }
8078
8079         context = g_new0 (MonoGenericContext, 1);
8080         context->gclass = gclass;
8081         context->gmethod = gmethod;
8082
8083         return mono_class_inflate_generic_method (method, context, gclass->klass);
8084 }
8085
8086 static MonoMethod *
8087 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8088 {
8089         MonoMethod *method;
8090         MonoClass *klass;
8091
8092         klass = mono_class_from_mono_type (type->type.type);
8093
8094         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8095                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8096         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8097                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8098         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8099                 method = ((MonoReflectionMethod *) obj)->method;
8100         else {
8101                 method = NULL; /* prevent compiler warning */
8102                 g_assert_not_reached ();
8103         }
8104
8105         return inflate_mono_method (type, method, obj);
8106 }
8107
8108 void
8109 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
8110                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8111                                           MonoArray *events)
8112 {
8113         MonoGenericClass *gclass;
8114         MonoDynamicGenericClass *dgclass;
8115         MonoClass *klass, *gklass, *pklass;
8116         int i;
8117
8118         MONO_ARCH_SAVE_REGS;
8119
8120         klass = mono_class_from_mono_type (type->type.type);
8121         gclass = type->type.type->data.generic_class;
8122
8123         if (gclass->initialized)
8124                 return;
8125
8126         dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
8127
8128         gklass = mono_class_from_mono_type (gclass->generic_type);
8129         mono_class_init (gklass);
8130
8131         if (gclass->parent)
8132                 pklass = mono_class_from_mono_type (gclass->parent);
8133         else
8134                 pklass = gklass->parent;
8135
8136         mono_class_setup_parent (klass, pklass);
8137
8138         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8139         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8140         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8141         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8142         dgclass->count_events = events ? mono_array_length (events) : 0;
8143
8144         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8145         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8146         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8147         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8148         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8149
8150         for (i = 0; i < dgclass->count_methods; i++) {
8151                 MonoObject *obj = mono_array_get (methods, gpointer, i);
8152
8153                 dgclass->methods [i] = inflate_method (type, obj);
8154         }
8155
8156         for (i = 0; i < dgclass->count_ctors; i++) {
8157                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8158
8159                 dgclass->ctors [i] = inflate_method (type, obj);
8160         }
8161
8162         for (i = 0; i < dgclass->count_fields; i++) {
8163                 MonoObject *obj = mono_array_get (fields, gpointer, i);
8164                 MonoClassField *field;
8165                 MonoInflatedField *ifield;
8166
8167                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8168                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8169                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8170                         field = ((MonoReflectionField *) obj)->field;
8171                 else {
8172                         field = NULL; /* prevent compiler warning */
8173                         g_assert_not_reached ();
8174                 }
8175
8176                 ifield = g_new0 (MonoInflatedField, 1);
8177                 ifield->generic_type = field->type;
8178                 ifield->reflection_info = obj;
8179
8180                 dgclass->fields [i] = *field;
8181                 dgclass->fields [i].generic_info = ifield;
8182                 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8183         }
8184
8185         for (i = 0; i < dgclass->count_properties; i++) {
8186                 MonoObject *obj = mono_array_get (properties, gpointer, i);
8187                 MonoProperty *property = &dgclass->properties [i];
8188
8189                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8190                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8191
8192                         property->parent = klass;
8193                         property->attrs = pb->attrs;
8194                         property->name = mono_string_to_utf8 (pb->name);
8195                         if (pb->get_method)
8196                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8197                         if (pb->set_method)
8198                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8199                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8200                         *property = *((MonoReflectionProperty *) obj)->property;
8201
8202                         if (property->get)
8203                                 property->get = inflate_mono_method (type, property->get, NULL);
8204                         if (property->set)
8205                                 property->set = inflate_mono_method (type, property->set, NULL);
8206                 } else
8207                         g_assert_not_reached ();
8208         }
8209
8210         for (i = 0; i < dgclass->count_events; i++) {
8211                 MonoObject *obj = mono_array_get (events, gpointer, i);
8212                 MonoEvent *event = &dgclass->events [i];
8213
8214                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8215                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8216
8217                         event->parent = klass;
8218                         event->attrs = eb->attrs;
8219                         event->name = mono_string_to_utf8 (eb->name);
8220                         if (eb->add_method)
8221                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8222                         if (eb->remove_method)
8223                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8224                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8225                         *event = *((MonoReflectionEvent *) obj)->event;
8226
8227                         if (event->add)
8228                                 event->add = inflate_mono_method (type, event->add, NULL);
8229                         if (event->remove)
8230                                 event->remove = inflate_mono_method (type, event->remove, NULL);
8231                 } else
8232                         g_assert_not_reached ();
8233         }
8234
8235         gclass->initialized = TRUE;
8236 }
8237
8238 static void
8239 ensure_runtime_vtable (MonoClass *klass)
8240 {
8241         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8242         int i, num, j, onum;
8243         MonoMethod **overrides;
8244
8245         if (!tb || klass->wastypebuilder)
8246                 return;
8247         if (klass->parent)
8248                 ensure_runtime_vtable (klass->parent);
8249
8250         num = tb->ctors? mono_array_length (tb->ctors): 0;
8251         num += tb->num_methods;
8252         klass->method.count = num;
8253         klass->methods = g_new (MonoMethod*, num);
8254         num = tb->ctors? mono_array_length (tb->ctors): 0;
8255         for (i = 0; i < num; ++i)
8256                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8257         num = tb->num_methods;
8258         j = i;
8259         for (i = 0; i < num; ++i)
8260                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8261
8262         if (tb->interfaces) {
8263                 klass->interface_count = mono_array_length (tb->interfaces);
8264                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8265                 for (i = 0; i < klass->interface_count; ++i) {
8266                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8267                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8268                 }
8269         }
8270
8271         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8272                 for (i = 0; i < klass->method.count; ++i)
8273                         klass->methods [i]->slot = i;
8274
8275         /* Overrides */
8276         onum = 0;
8277         if (tb->methods) {
8278                 for (i = 0; i < tb->num_methods; ++i) {
8279                         MonoReflectionMethodBuilder *mb = 
8280                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8281                         if (mb->override_method)
8282                                 onum ++;
8283                 }
8284         }
8285
8286         overrides = g_new0 (MonoMethod*, onum * 2);
8287
8288         if (tb->methods) {
8289                 onum = 0;
8290                 for (i = 0; i < tb->num_methods; ++i) {
8291                         MonoReflectionMethodBuilder *mb = 
8292                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8293                         if (mb->override_method) {
8294                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8295                                 overrides [onum * 2] = 
8296                                         mb->override_method->method;
8297                                 overrides [onum * 2 + 1] =
8298                                         mb->mhandle;
8299
8300                                 g_assert (mb->mhandle);
8301
8302                                 onum ++;
8303                         }
8304                 }
8305         }
8306
8307         mono_class_setup_vtable (klass, overrides, onum);
8308         g_free (overrides);
8309 }
8310
8311 static void
8312 typebuilder_setup_fields (MonoClass *klass)
8313 {
8314         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8315         MonoReflectionFieldBuilder *fb;
8316         MonoClassField *field;
8317         const char *p, *p2;
8318         int i;
8319         guint32 len, idx;
8320
8321         klass->field.count = tb->num_fields;
8322         klass->field.first = 0;
8323         klass->field.last = klass->field.count;
8324
8325         if (!klass->field.count)
8326                 return;
8327         
8328         klass->fields = g_new0 (MonoClassField, klass->field.count);
8329
8330         for (i = 0; i < klass->field.count; ++i) {
8331                 fb = mono_array_get (tb->fields, gpointer, i);
8332                 field = &klass->fields [i];
8333                 field->name = mono_string_to_utf8 (fb->name);
8334                 if (fb->attrs) {
8335                         /* FIXME: handle type modifiers */
8336                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
8337                         field->type->attrs = fb->attrs;
8338                 } else {
8339                         field->type = fb->type->type;
8340                 }
8341                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8342                         field->data = mono_array_addr (fb->rva_data, char, 0);
8343                 if (fb->offset != -1)
8344                         field->offset = fb->offset;
8345                 field->parent = klass;
8346                 fb->handle = field;
8347                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8348
8349                 if (fb->def_value) {
8350                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8351                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8352                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
8353                         /* Copy the data from the blob since it might get realloc-ed */
8354                         p = assembly->blob.data + idx;
8355                         len = mono_metadata_decode_blob_size (p, &p2);
8356                         len += p2 - p;
8357                         field->data = g_malloc (len);
8358                         memcpy ((gpointer)field->data, p, len);
8359                 }
8360         }
8361         mono_class_layout_fields (klass);
8362 }
8363
8364 static void
8365 typebuilder_setup_properties (MonoClass *klass)
8366 {
8367         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8368         MonoReflectionPropertyBuilder *pb;
8369         int i;
8370
8371         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8372         klass->property.first = 0;
8373         klass->property.last = klass->property.count;
8374
8375         klass->properties = g_new0 (MonoProperty, klass->property.count);
8376         for (i = 0; i < klass->property.count; ++i) {
8377                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8378                 klass->properties [i].parent = klass;
8379                 klass->properties [i].attrs = pb->attrs;
8380                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8381                 if (pb->get_method)
8382                         klass->properties [i].get = pb->get_method->mhandle;
8383                 if (pb->set_method)
8384                         klass->properties [i].set = pb->set_method->mhandle;
8385         }
8386 }
8387
8388 MonoReflectionEvent *
8389 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8390 {
8391         MonoEvent *event = g_new0 (MonoEvent, 1);
8392         MonoClass *klass;
8393         int j;
8394
8395         klass = my_mono_class_from_mono_type (tb->type.type);
8396
8397         event->parent = klass;
8398         event->attrs = eb->attrs;
8399         event->name = mono_string_to_utf8 (eb->name);
8400         if (eb->add_method)
8401                 event->add = eb->add_method->mhandle;
8402         if (eb->remove_method)
8403                 event->remove = eb->remove_method->mhandle;
8404         if (eb->raise_method)
8405                 event->raise = eb->raise_method->mhandle;
8406
8407         if (eb->other_methods) {
8408                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8409                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8410                         MonoReflectionMethodBuilder *mb = 
8411                                 mono_array_get (eb->other_methods,
8412                                                 MonoReflectionMethodBuilder*, j);
8413                         event->other [j] = mb->mhandle;
8414                 }
8415         }
8416
8417         return mono_event_get_object (mono_object_domain (tb), klass, event);
8418 }
8419
8420 static void
8421 typebuilder_setup_events (MonoClass *klass)
8422 {
8423         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8424         MonoReflectionEventBuilder *eb;
8425         int i, j;
8426
8427         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8428         klass->event.first = 0;
8429         klass->event.last = klass->event.count;
8430
8431         klass->events = g_new0 (MonoEvent, klass->event.count);
8432         for (i = 0; i < klass->event.count; ++i) {
8433                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8434                 klass->events [i].parent = klass;
8435                 klass->events [i].attrs = eb->attrs;
8436                 klass->events [i].name = mono_string_to_utf8 (eb->name);
8437                 if (eb->add_method)
8438                         klass->events [i].add = eb->add_method->mhandle;
8439                 if (eb->remove_method)
8440                         klass->events [i].remove = eb->remove_method->mhandle;
8441                 if (eb->raise_method)
8442                         klass->events [i].raise = eb->raise_method->mhandle;
8443
8444                 if (eb->other_methods) {
8445                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8446                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8447                                 MonoReflectionMethodBuilder *mb = 
8448                                         mono_array_get (eb->other_methods,
8449                                                                         MonoReflectionMethodBuilder*, j);
8450                                 klass->events [i].other [j] = mb->mhandle;
8451                         }
8452                 }
8453         }
8454 }
8455
8456 MonoReflectionType*
8457 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8458 {
8459         MonoClass *klass;
8460         MonoReflectionType* res;
8461         int i;
8462
8463         MONO_ARCH_SAVE_REGS;
8464
8465         klass = my_mono_class_from_mono_type (tb->type.type);
8466
8467         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8468
8469         /*
8470          * Fields to set in klass:
8471          * the various flags: delegate/unicode/contextbound etc.
8472          */
8473         klass->flags = tb->attrs;
8474
8475         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8476                 /* No need to fully construct the type */
8477                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8478
8479         /* enums are done right away */
8480         if (!klass->enumtype)
8481                 ensure_runtime_vtable (klass);
8482
8483         if (tb->subtypes) {
8484                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8485                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8486                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8487                 }
8488         }
8489
8490         /* fields and object layout */
8491         if (klass->parent) {
8492                 if (!klass->parent->size_inited)
8493                         mono_class_init (klass->parent);
8494                 klass->instance_size += klass->parent->instance_size;
8495                 klass->class_size += klass->parent->class_size;
8496                 klass->min_align = klass->parent->min_align;
8497         } else {
8498                 klass->instance_size = sizeof (MonoObject);
8499                 klass->min_align = 1;
8500         }
8501
8502         /* FIXME: handle packing_size and instance_size */
8503         typebuilder_setup_fields (klass);
8504
8505         typebuilder_setup_properties (klass);
8506
8507         typebuilder_setup_events (klass);
8508
8509         klass->wastypebuilder = TRUE;
8510
8511         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8512         g_assert (res != (MonoReflectionType*)tb);
8513         return res;
8514 }
8515
8516 void
8517 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8518 {
8519         MonoGenericParam *param;
8520         MonoImage *image;
8521
8522         MONO_ARCH_SAVE_REGS;
8523
8524         param = g_new0 (MonoGenericParam, 1);
8525
8526         if (gparam->mbuilder) {
8527                 if (!gparam->mbuilder->generic_container)
8528                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8529                 param->owner = gparam->mbuilder->generic_container;
8530         } else if (gparam->tbuilder) {
8531                 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8532                 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8533
8534                 while (nesting) {
8535                         int count;
8536
8537                         count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8538                         if (gparam->index >= count)
8539                                 break;
8540
8541                         container = nesting->generic_container;
8542                         nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8543                 }
8544
8545                 g_assert (container);
8546                 param->owner = container;
8547         }
8548
8549         param->method = NULL;
8550         param->name = mono_string_to_utf8 (gparam->name);
8551         param->num = gparam->index;
8552
8553         image = &gparam->tbuilder->module->dynamic_image->image;
8554         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8555
8556         param->pklass->reflection_info = gparam;
8557
8558         gparam->type.type = g_new0 (MonoType, 1);
8559         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8560         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8561         gparam->type.type->data.generic_param = param;
8562 }
8563
8564 MonoArray *
8565 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8566 {
8567         MonoDynamicImage *assembly = sig->module->dynamic_image;
8568         guint32 na = mono_array_length (sig->arguments);
8569         guint32 buflen, i;
8570         MonoArray *result;
8571         char *buf, *p;
8572
8573         MONO_ARCH_SAVE_REGS;
8574
8575         p = buf = g_malloc (10 + na * 10);
8576
8577         mono_metadata_encode_value (0x07, p, &p);
8578         mono_metadata_encode_value (na, p, &p);
8579         for (i = 0; i < na; ++i) {
8580                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8581                 encode_reflection_type (assembly, type, p, &p);
8582         }
8583
8584         buflen = p - buf;
8585         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8586         p = mono_array_addr (result, char, 0);
8587         memcpy (p, buf, buflen);
8588         g_free (buf);
8589
8590         return result;
8591 }
8592
8593 MonoArray *
8594 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8595 {
8596         MonoDynamicImage *assembly = sig->module->dynamic_image;
8597         guint32 na = mono_array_length (sig->arguments);
8598         guint32 buflen, i;
8599         MonoArray *result;
8600         char *buf, *p;
8601
8602         MONO_ARCH_SAVE_REGS;
8603
8604         p = buf = g_malloc (10 + na * 10);
8605
8606         mono_metadata_encode_value (0x06, p, &p);
8607         for (i = 0; i < na; ++i) {
8608                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8609                 encode_reflection_type (assembly, type, p, &p);
8610         }
8611
8612         buflen = p - buf;
8613         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8614         p = mono_array_addr (result, char, 0);
8615         memcpy (p, buf, buflen);
8616         g_free (buf);
8617
8618         return result;
8619 }
8620
8621 void 
8622 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8623 {
8624         ReflectionMethodBuilder rmb;
8625         MonoMethodSignature *sig;
8626         int i;
8627
8628         sig = dynamic_method_to_signature (mb);
8629
8630         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8631
8632         /*
8633          * Resolve references.
8634          */
8635         rmb.nrefs = mb->nrefs;
8636         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8637         for (i = 0; i < mb->nrefs; ++i) {
8638                 gpointer ref = resolve_object (mb->module->image, 
8639                                                mono_array_get (mb->refs, MonoObject*, i));
8640                 if (!ref) {
8641                         g_free (rmb.refs);
8642                         mono_raise_exception (mono_get_exception_type_load (NULL));
8643                         return;
8644                 }
8645                 rmb.refs [i] = ref;
8646         }               
8647
8648         /* FIXME: class */
8649         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8650
8651         g_free (rmb.refs);
8652
8653         /* ilgen is no longer needed */
8654         mb->ilgen = NULL;
8655 }
8656
8657 /**
8658  * mono_reflection_lookup_dynamic_token:
8659  *
8660  * Finish the Builder object pointed to by TOKEN and return the corresponding
8661  * runtime structure.
8662  */
8663 gpointer
8664 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8665 {
8666         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8667         MonoObject *obj;
8668
8669         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8670         g_assert (obj);
8671
8672         return resolve_object (image, obj);
8673 }
8674
8675 static gpointer
8676 resolve_object (MonoImage *image, MonoObject *obj)
8677 {
8678         gpointer result = NULL;
8679
8680         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8681                 result = mono_string_intern ((MonoString*)obj);
8682                 g_assert (result);
8683         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8684                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8685                 result = mono_class_from_mono_type (tb->type);
8686                 g_assert (result);
8687         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8688                 result = ((MonoReflectionMethod*)obj)->method;
8689                 g_assert (result);
8690         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8691                 result = ((MonoReflectionMethod*)obj)->method;
8692                 g_assert (result);
8693         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8694                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8695                 result = mb->mhandle;
8696                 if (!result) {
8697                         /* Type is not yet created */
8698                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8699
8700                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8701
8702                         /*
8703                          * Hopefully this has been filled in by calling CreateType() on the
8704                          * TypeBuilder.
8705                          */
8706                         /*
8707                          * TODO: This won't work if the application finishes another 
8708                          * TypeBuilder instance instead of this one.
8709                          */
8710                         result = mb->mhandle;
8711                 }
8712         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8713                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8714
8715                 result = cb->mhandle;
8716                 if (!result) {
8717                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8718
8719                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8720                         result = cb->mhandle;
8721                 }
8722         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8723                 result = ((MonoReflectionField*)obj)->field;
8724                 g_assert (result);
8725         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8726                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8727                 result = fb->handle;
8728
8729                 if (!result) {
8730                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8731
8732                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8733                         result = fb->handle;
8734                 }
8735         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8736                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8737                 MonoClass *klass;
8738
8739                 klass = tb->type.type->data.klass;
8740                 if (klass->wastypebuilder) {
8741                         /* Already created */
8742                         result = klass;
8743                 }
8744                 else {
8745                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8746                         result = tb->type.type->data.klass;
8747                         g_assert (result);
8748                 }
8749         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8750                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8751                 MonoMethodSignature *sig;
8752                 int nargs, i;
8753
8754                 if (helper->arguments)
8755                         nargs = mono_array_length (helper->arguments);
8756                 else
8757                         nargs = 0;
8758
8759                 sig = mono_metadata_signature_alloc (image, nargs);
8760                 sig->explicit_this = helper->call_conv & 64;
8761                 sig->hasthis = helper->call_conv & 32;
8762
8763                 if (helper->call_conv == 0) /* unmanaged */
8764                         sig->call_convention = helper->unmanaged_call_conv - 1;
8765                 else
8766                         if (helper->call_conv & 0x02)
8767                                 sig->call_convention = MONO_CALL_VARARG;
8768                 else
8769                         sig->call_convention = MONO_CALL_DEFAULT;
8770
8771                 sig->param_count = nargs;
8772                 /* TODO: Copy type ? */
8773                 sig->ret = helper->return_type->type;
8774                 for (i = 0; i < nargs; ++i) {
8775                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8776                         sig->params [i] = rt->type;
8777                 }
8778
8779                 result = sig;
8780         } else {
8781                 g_print (obj->vtable->klass->name);
8782                 g_assert_not_reached ();
8783         }
8784         return result;
8785 }
8786
8787
8788 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8789 const static guint32 declsec_flags_map[] = {
8790         0x00000000,                                     /* empty */
8791         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
8792         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
8793         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
8794         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
8795         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
8796         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
8797         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
8798         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
8799         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
8800         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
8801         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
8802         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
8803         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
8804         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
8805         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
8806         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
8807         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
8808         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
8809 };
8810
8811 /*
8812  * Returns flags that includes all available security action associated to the handle.
8813  * @token: metadata token (either for a class or a method)
8814  * @image: image where resides the metadata.
8815  */
8816 static guint32
8817 mono_declsec_get_flags (MonoImage *image, guint32 token)
8818 {
8819         guint32 index = mono_metadata_declsec_from_index (image, token);
8820         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8821         guint32 result = 0;
8822         guint32 action;
8823         int i;
8824
8825         for (i = index; i < t->rows; i++) {
8826                 guint32 cols [MONO_DECL_SECURITY_SIZE];
8827
8828                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8829                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8830                         break;
8831
8832                 action = cols [MONO_DECL_SECURITY_ACTION];
8833                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8834                         result |= declsec_flags_map [action];
8835                 } else {
8836                         g_assert_not_reached ();
8837                 }
8838         }
8839         return result;
8840 }
8841
8842 /*
8843  * Get the security actions (in the form of flags) associated with the specified method.
8844  *
8845  * @method: The method for which we want the declarative security flags.
8846  * Return the declarative security flags for the method (only).
8847  *
8848  * Note: To keep MonoMethod size down we do not cache the declarative security flags
8849  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
8850  */
8851 guint32
8852 mono_declsec_flags_from_method (MonoMethod *method)
8853 {
8854         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8855                 /* FIXME: No cache (for the moment) */
8856                 guint32 idx = find_method_index (method);
8857                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8858                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8859                 return mono_declsec_get_flags (method->klass->image, idx);
8860         }
8861         return 0;
8862 }
8863
8864 /*
8865  * Get the security actions (in the form of flags) associated with the specified class.
8866  *
8867  * @klass: The class for which we want the declarative security flags.
8868  * Return the declarative security flags for the class.
8869  *
8870  * Note: We cache the flags inside the MonoClass structure as this will get 
8871  *       called very often (at least for each method).
8872  */
8873 guint32
8874 mono_declsec_flags_from_class (MonoClass *klass)
8875 {
8876         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8877                 if (!klass->declsec_flags) {
8878                         guint32 idx = mono_metadata_token_index (klass->type_token);
8879                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
8880                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8881                         /* we cache the flags on classes */
8882                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8883                 }
8884                 return klass->declsec_flags;
8885         }
8886         return 0;
8887 }
8888
8889 /*
8890  * Get the security actions (in the form of flags) associated with the specified assembly.
8891  *
8892  * @assembly: The assembly for which we want the declarative security flags.
8893  * Return the declarative security flags for the assembly.
8894  */
8895 guint32
8896 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8897 {
8898         guint32 idx = 1; /* there is only one assembly */
8899         idx <<= MONO_HAS_DECL_SECURITY_BITS;
8900         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8901         return mono_declsec_get_flags (assembly->image, idx);
8902 }