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