2004-11-28 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include "image.h"
29 #include "cil-coff.h"
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
32 #include "private.h"
33 #include <mono/os/gc_wrapper.h>
34
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA  0x00002000
40
41 typedef struct {
42         MonoReflectionILGen *ilgen;
43         MonoReflectionType *rtype;
44         MonoArray *parameters;
45         MonoArray *generic_params;
46         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_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
458 {
459         int i;
460
461         if (!ginst) {
462                 g_assert_not_reached ();
463                 return;
464         }
465
466         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
467         encode_type (assembly, ginst->generic_type, p, &p);
468         mono_metadata_encode_value (ginst->type_argc, p, &p);
469         for (i = 0; i < ginst->type_argc; ++i)
470                 encode_type (assembly, ginst->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_inst (assembly, type->data.generic_inst, 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_inst_get_signature_size (MonoGenericInst *ginst)
590 {
591         guint32 size = 0;
592         int i;
593
594         if (!ginst) {
595                 g_assert_not_reached ();
596         }
597
598         size += 1 + type_get_signature_size (ginst->generic_type);
599         size += 4;
600         for (i = 0; i < ginst->type_argc; ++i)
601                 size += type_get_signature_size (ginst->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_inst_get_signature_size (type->data.generic_inst);
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_inst)
2196                         return 0;
2197                 encode_generic_inst (assembly, k->generic_inst, 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->mtype_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->mtype_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_inst);
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, "MonoGenericInst") == 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_inst) {
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_inst->type_argc != t2->data.generic_inst->type_argc)
5198                         return FALSE;
5199                 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5200                         return FALSE;
5201                 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5202                         if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_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 MonoReflectionGenericInst*
5239 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5240 {
5241         static MonoClass *System_Reflection_MonoGenericInst;
5242         MonoReflectionGenericInst *res;
5243         MonoGenericInst *ginst;
5244         MonoClass *gklass;
5245
5246         if (!System_Reflection_MonoGenericInst) {
5247                 System_Reflection_MonoGenericInst = mono_class_from_name (
5248                         mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5249                 g_assert (System_Reflection_MonoGenericInst);
5250         }
5251
5252         ginst = geninst->data.generic_inst;
5253         gklass = mono_class_from_mono_type (ginst->generic_type);
5254
5255         mono_class_init (ginst->klass);
5256
5257         res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
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, ginst->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_inst->is_dynamic) {
5290                 res = (MonoReflectionType *)mono_generic_inst_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_inst) {
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  * Returns 0 on parse error.
5763  * See also mono_type_get_name () below.
5764  */
5765 int
5766 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5767
5768         char *start, *p, *w, *last_point, *startn;
5769         int in_modifiers = 0;
5770         int isbyref = 0, rank;
5771
5772         start = p = w = name;
5773
5774         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5775         info->name = info->name_space = NULL;
5776         info->nested = NULL;
5777         info->modifiers = NULL;
5778
5779         /* last_point separates the namespace from the name */
5780         last_point = NULL;
5781
5782         while (*p) {
5783                 switch (*p) {
5784                 case '+':
5785                         *p = 0; /* NULL terminate the name */
5786                         startn = p + 1;
5787                         info->nested = g_list_append (info->nested, startn);
5788                         /* we have parsed the nesting namespace + name */
5789                         if (info->name)
5790                                 break;
5791                         if (last_point) {
5792                                 info->name_space = start;
5793                                 *last_point = 0;
5794                                 info->name = last_point + 1;
5795                         } else {
5796                                 info->name_space = (char *)"";
5797                                 info->name = start;
5798                         }
5799                         break;
5800                 case '.':
5801                         last_point = w;
5802                         break;
5803                 case '\\':
5804                         ++p;
5805                         break;
5806                 case '&':
5807                 case '*':
5808                 case '[':
5809                 case ',':
5810                         in_modifiers = 1;
5811                         break;
5812                 default:
5813                         break;
5814                 }
5815                 if (in_modifiers)
5816                         break;
5817                 *w++ = *p++;
5818         }
5819         
5820         if (!info->name) {
5821                 if (last_point) {
5822                         info->name_space = start;
5823                         *last_point = 0;
5824                         info->name = last_point + 1;
5825                 } else {
5826                         info->name_space = (char *)"";
5827                         info->name = start;
5828                 }
5829         }
5830         while (*p) {
5831                 switch (*p) {
5832                 case '&':
5833                         if (isbyref) /* only one level allowed by the spec */
5834                                 return 0;
5835                         isbyref = 1;
5836                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5837                         *p++ = 0;
5838                         break;
5839                 case '*':
5840                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5841                         *p++ = 0;
5842                         break;
5843                 case '[':
5844                         rank = 1;
5845                         *p++ = 0;
5846                         while (*p) {
5847                                 if (*p == ']')
5848                                         break;
5849                                 if (*p == ',')
5850                                         rank++;
5851                                 else if (*p != '*') /* '*' means unknown lower bound */
5852                                         return 0;
5853                                 ++p;
5854                         }
5855                         if (*p++ != ']')
5856                                 return 0;
5857                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5858                         break;
5859                 case ',':
5860                         *p++ = 0;
5861                         while (*p) {
5862                                 if (g_ascii_isspace (*p)) {
5863                                         ++p;
5864                                         continue;
5865                                 }
5866                                 break;
5867                         }
5868                         if (!*p)
5869                                 return 0; /* missing assembly name */
5870                         if (!assembly_name_to_aname (&info->assembly, p))
5871                                 return 0;
5872                         break;
5873                 default:
5874                         return 0;
5875                         break;
5876                 }
5877                 if (info->assembly.name)
5878                         break;
5879         }
5880         *w = 0; /* terminate class name */
5881         if (!info->name || !*info->name)
5882                 return 0;
5883         /* add other consistency checks */
5884         return 1;
5885 }
5886
5887 static MonoType*
5888 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5889 {
5890         MonoClass *klass;
5891         GList *mod;
5892         int modval;
5893         
5894         if (!image)
5895                 image = mono_defaults.corlib;
5896
5897         if (ignorecase)
5898                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5899         else
5900                 klass = mono_class_from_name (image, info->name_space, info->name);
5901         if (!klass)
5902                 return NULL;
5903         for (mod = info->nested; mod; mod = mod->next) {
5904                 GList *nested;
5905
5906                 mono_class_init (klass);
5907                 nested = klass->nested_classes;
5908                 klass = NULL;
5909                 while (nested) {
5910                         klass = nested->data;
5911                         if (ignorecase) {
5912                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5913                                         break;
5914                         } else {
5915                                 if (strcmp (klass->name, mod->data) == 0)
5916                                         break;
5917                         }
5918                         klass = NULL;
5919                         nested = nested->next;
5920                 }
5921                 if (!klass)
5922                         break;
5923         }
5924         if (!klass)
5925                 return NULL;
5926         mono_class_init (klass);
5927         for (mod = info->modifiers; mod; mod = mod->next) {
5928                 modval = GPOINTER_TO_UINT (mod->data);
5929                 if (!modval) { /* byref: must be last modifier */
5930                         return &klass->this_arg;
5931                 } else if (modval == -1) {
5932                         klass = mono_ptr_class_get (&klass->byval_arg);
5933                 } else { /* array rank */
5934                         klass = mono_array_class_get (klass, modval);
5935                 }
5936                 mono_class_init (klass);
5937         }
5938
5939         return &klass->byval_arg;
5940 }
5941
5942 /*
5943  * mono_reflection_get_type:
5944  * @image: a metadata context
5945  * @info: type description structure
5946  * @ignorecase: flag for case-insensitive string compares
5947  * @type_resolve: whenever type resolve was already tried
5948  *
5949  * Build a MonoType from the type description in @info.
5950  * 
5951  */
5952
5953 MonoType*
5954 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5955 {
5956         MonoType *type;
5957         MonoReflectionAssembly *assembly;
5958         GString *fullName;
5959         GList *mod;
5960
5961         type = mono_reflection_get_type_internal (image, info, ignorecase);
5962         if (type)
5963                 return type;
5964         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5965                 return NULL;
5966
5967         if (type_resolve) {
5968                 if (*type_resolve) 
5969                         return NULL;
5970                 else
5971                         *type_resolve = TRUE;
5972         }
5973         
5974         /* Reconstruct the type name */
5975         fullName = g_string_new ("");
5976         if (info->name_space && (info->name_space [0] != '\0'))
5977                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5978         else
5979                 g_string_printf (fullName, info->name);
5980         for (mod = info->nested; mod; mod = mod->next)
5981                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5982
5983         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5984         if (assembly) {
5985                 if (assembly->assembly->dynamic) {
5986                         /* Enumerate all modules */
5987                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5988                         int i;
5989
5990                         type = NULL;
5991                         if (abuilder->modules) {
5992                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5993                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5994                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5995                                         if (type)
5996                                                 break;
5997                                 }
5998                         }
5999
6000                         if (!type && abuilder->loaded_modules) {
6001                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6002                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6003                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6004                                         if (type)
6005                                                 break;
6006                                 }
6007                         }
6008                 }
6009                 else
6010                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
6011                                                                                                           info, ignorecase);
6012         }
6013         g_string_free (fullName, TRUE);
6014         return type;
6015 }
6016
6017 /*
6018  * mono_reflection_type_from_name:
6019  * @name: type name.
6020  * @image: a metadata context (can be NULL).
6021  *
6022  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6023  * it defaults to get the type from @image or, if @image is NULL or loading
6024  * from it fails, uses corlib.
6025  * 
6026  */
6027 MonoType*
6028 mono_reflection_type_from_name (char *name, MonoImage *image)
6029 {
6030         MonoType *type;
6031         MonoTypeNameParse info;
6032         MonoAssembly *assembly;
6033         char *tmp;
6034         gboolean type_resolve = FALSE;
6035
6036         /* Make a copy since parse_type modifies its argument */
6037         tmp = g_strdup (name);
6038         
6039         /*g_print ("requested type %s\n", str);*/
6040         if (!mono_reflection_parse_type (tmp, &info)) {
6041                 g_free (tmp);
6042                 g_list_free (info.modifiers);
6043                 g_list_free (info.nested);
6044                 return NULL;
6045         }
6046
6047         if (info.assembly.name) {
6048                 assembly = mono_assembly_loaded (&info.assembly);
6049                 if (!assembly) {
6050                         /* then we must load the assembly ourselve - see #60439 */
6051                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6052                         if (!assembly) {
6053                                 g_free (tmp);
6054                                 g_list_free (info.modifiers);
6055                                 g_list_free (info.nested);
6056                                 return NULL;
6057                         }
6058                 }
6059                 image = assembly->image;
6060         } else if (image == NULL) {
6061                 image = mono_defaults.corlib;
6062         }
6063
6064         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6065         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6066                 image = mono_defaults.corlib;
6067                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6068         }
6069
6070         g_free (tmp);
6071         g_list_free (info.modifiers);
6072         g_list_free (info.nested);
6073         return type;
6074 }
6075
6076 /*
6077  * mono_reflection_get_token:
6078  *
6079  *   Return the metadata token of OBJ which should be an object
6080  * representing a metadata element.
6081  */
6082 guint32
6083 mono_reflection_get_token (MonoObject *obj)
6084 {
6085         MonoClass *klass;
6086         guint32 token = 0;
6087
6088         klass = obj->vtable->klass;
6089
6090         if (strcmp (klass->name, "MethodBuilder") == 0) {
6091                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6092
6093                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6094         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6095                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6096
6097                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6098         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6099                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6100                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6101                 if (tb->generic_params) {
6102                         g_assert_not_reached ();
6103                 } else {
6104                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6105                 }
6106         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6107                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6108                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6109         } else if (strcmp (klass->name, "MonoType") == 0) {
6110                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6111                 token = mono_class_from_mono_type (tb->type)->type_token;
6112         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6113                         strcmp (klass->name, "MonoMethod") == 0) {
6114                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6115                 if (m->method->signature->is_inflated) {
6116                         g_assert_not_reached ();
6117                 } else if (m->method->signature->generic_param_count) {
6118                         g_assert_not_reached ();
6119                 } else if (m->method->klass->generic_inst) {
6120                         g_assert_not_reached ();
6121                 } else {
6122                         token = m->method->token;
6123                 }
6124         } else if (strcmp (klass->name, "MonoField") == 0) {
6125                 MonoReflectionField *f = (MonoReflectionField*)obj;
6126
6127                 token = mono_class_get_field_token (f->field);
6128         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6129                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6130
6131                 token = mono_class_get_property_token (p->property);
6132         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6133                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6134
6135                 token = mono_class_get_event_token (p->event);
6136         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6137                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6138
6139                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6140         } else if (strcmp (klass->name, "Module") == 0) {
6141                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6142
6143                 token = m->token;
6144         } else if (strcmp (klass->name, "Assembly") == 0) {
6145                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6146         } else {
6147                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6148                 MonoException *ex = mono_get_exception_not_implemented (msg);
6149                 g_free (msg);
6150                 mono_raise_exception (ex);
6151         }
6152
6153         return token;
6154 }
6155
6156 static void*
6157 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6158 {
6159         int slen, type = t->type;
6160 handle_enum:
6161         switch (type) {
6162         case MONO_TYPE_U1:
6163         case MONO_TYPE_I1:
6164         case MONO_TYPE_BOOLEAN: {
6165                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6166                 *bval = *p;
6167                 *end = p + 1;
6168                 return bval;
6169         }
6170         case MONO_TYPE_CHAR:
6171         case MONO_TYPE_U2:
6172         case MONO_TYPE_I2: {
6173                 guint16 *val = g_malloc (sizeof (guint16));
6174                 *val = read16 (p);
6175                 *end = p + 2;
6176                 return val;
6177         }
6178 #if SIZEOF_VOID_P == 4
6179         case MONO_TYPE_U:
6180         case MONO_TYPE_I:
6181 #endif
6182         case MONO_TYPE_R4:
6183         case MONO_TYPE_U4:
6184         case MONO_TYPE_I4: {
6185                 guint32 *val = g_malloc (sizeof (guint32));
6186                 *val = read32 (p);
6187                 *end = p + 4;
6188                 return val;
6189         }
6190 #if SIZEOF_VOID_P == 8
6191         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6192         case MONO_TYPE_I:
6193 #endif
6194         case MONO_TYPE_R8:
6195         case MONO_TYPE_U8:
6196         case MONO_TYPE_I8: {
6197                 guint64 *val = g_malloc (sizeof (guint64));
6198                 *val = read64 (p);
6199                 *end = p + 8;
6200                 return val;
6201         }
6202         case MONO_TYPE_VALUETYPE:
6203                 if (t->data.klass->enumtype) {
6204                         type = t->data.klass->enum_basetype->type;
6205                         goto handle_enum;
6206                 } else {
6207                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6208                 }
6209                 break;
6210         case MONO_TYPE_STRING:
6211                 if (*p == (char)0xFF) {
6212                         *end = p + 1;
6213                         return NULL;
6214                 }
6215                 slen = mono_metadata_decode_value (p, &p);
6216                 *end = p + slen;
6217                 return mono_string_new_len (mono_domain_get (), p, slen);
6218         case MONO_TYPE_CLASS: {
6219                 char *n;
6220                 MonoType *t;
6221                 if (*p == (char)0xFF) {
6222                         *end = p + 1;
6223                         return NULL;
6224                 }
6225 handle_type:
6226                 slen = mono_metadata_decode_value (p, &p);
6227                 n = g_memdup (p, slen + 1);
6228                 n [slen] = 0;
6229                 t = mono_reflection_type_from_name (n, image);
6230                 if (!t)
6231                         g_warning ("Cannot load type '%s'", n);
6232                 g_free (n);
6233                 *end = p + slen;
6234                 if (t)
6235                         return mono_type_get_object (mono_domain_get (), t);
6236                 else
6237                         return NULL;
6238         }
6239         case MONO_TYPE_OBJECT: {
6240                 char subt = *p++;
6241                 MonoObject *obj;
6242                 MonoClass *subc = NULL;
6243                 void *val;
6244
6245                 if (subt == 0x50) {
6246                         goto handle_type;
6247                 } else if (subt == 0x0E) {
6248                         type = MONO_TYPE_STRING;
6249                         goto handle_enum;
6250                 } else if (subt == 0x55) {
6251                         char *n;
6252                         MonoType *t;
6253                         slen = mono_metadata_decode_value (p, &p);
6254                         n = g_memdup (p, slen + 1);
6255                         n [slen] = 0;
6256                         t = mono_reflection_type_from_name (n, image);
6257                         if (!t)
6258                                 g_warning ("Cannot load type '%s'", n);
6259                         g_free (n);
6260                         p += slen;
6261                         subc = mono_class_from_mono_type (t);
6262                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6263                         MonoType simple_type = {{0}};
6264                         simple_type.type = subt;
6265                         subc = mono_class_from_mono_type (&simple_type);
6266                 } else {
6267                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6268                 }
6269                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6270                 obj = mono_object_new (mono_domain_get (), subc);
6271                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6272                 g_free (val);
6273                 return obj;
6274         }
6275         case MONO_TYPE_SZARRAY: {
6276                 MonoArray *arr;
6277                 guint32 i, alen, basetype;
6278                 alen = read32 (p);
6279                 p += 4;
6280                 if (alen == 0xffffffff) {
6281                         *end = p;
6282                         return NULL;
6283                 }
6284                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6285                 basetype = t->data.klass->byval_arg.type;
6286                 switch (basetype)
6287                 {
6288                         case MONO_TYPE_U1:
6289                         case MONO_TYPE_I1:
6290                         case MONO_TYPE_BOOLEAN:
6291                                 for (i = 0; i < alen; i++) {
6292                                         MonoBoolean val = *p++;
6293                                         mono_array_set (arr, MonoBoolean, i, val);
6294                                 }
6295                                 break;
6296                         case MONO_TYPE_CHAR:
6297                         case MONO_TYPE_U2:
6298                         case MONO_TYPE_I2:
6299                                 for (i = 0; i < alen; i++) {
6300                                         guint16 val = read16 (p);
6301                                         mono_array_set (arr, guint16, i, val);
6302                                         p += 2;
6303                                 }
6304                                 break;
6305                         case MONO_TYPE_R4:
6306                         case MONO_TYPE_U4:
6307                         case MONO_TYPE_I4:
6308                                 for (i = 0; i < alen; i++) {
6309                                         guint32 val = read32 (p);
6310                                         mono_array_set (arr, guint32, i, val);
6311                                         p += 4;
6312                                 }
6313                                 break;
6314                         case MONO_TYPE_R8:
6315                         case MONO_TYPE_U8:
6316                         case MONO_TYPE_I8:
6317                                 for (i = 0; i < alen; i++) {
6318                                         guint64 val = read64 (p);
6319                                         mono_array_set (arr, guint64, i, val);
6320                                         p += 8;
6321                                 }
6322                                 break;
6323                         case MONO_TYPE_CLASS:
6324                         case MONO_TYPE_OBJECT:
6325                         case MONO_TYPE_STRING:
6326                                 for (i = 0; i < alen; i++) {
6327                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6328                                         mono_array_set (arr, gpointer, i, item);
6329                                 }
6330                                 break;
6331                         default:
6332                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6333                 }
6334                 *end=p;
6335                 return arr;
6336         }
6337         default:
6338                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6339         }
6340         return NULL;
6341 }
6342
6343 static gboolean
6344 type_is_reference (MonoType *type)
6345 {
6346         switch (type->type) {
6347         case MONO_TYPE_BOOLEAN:
6348         case MONO_TYPE_CHAR:
6349         case MONO_TYPE_U:
6350         case MONO_TYPE_I:
6351         case MONO_TYPE_U1:
6352         case MONO_TYPE_I1:
6353         case MONO_TYPE_U2:
6354         case MONO_TYPE_I2:
6355         case MONO_TYPE_U4:
6356         case MONO_TYPE_I4:
6357         case MONO_TYPE_U8:
6358         case MONO_TYPE_I8:
6359         case MONO_TYPE_R8:
6360         case MONO_TYPE_R4:
6361         case MONO_TYPE_VALUETYPE:
6362                 return FALSE;
6363         default:
6364                 return TRUE;
6365         }
6366 }
6367
6368 static void
6369 free_param_data (MonoMethodSignature *sig, void **params) {
6370         int i;
6371         for (i = 0; i < sig->param_count; ++i) {
6372                 if (!type_is_reference (sig->params [i]))
6373                         g_free (params [i]);
6374         }
6375 }
6376
6377 /*
6378  * Find the method index in the metadata methodDef table.
6379  * Later put these three helper methods in metadata and export them.
6380  */
6381 static guint32
6382 find_method_index (MonoMethod *method) {
6383         MonoClass *klass = method->klass;
6384         int i;
6385
6386         for (i = 0; i < klass->method.count; ++i) {
6387                 if (method == klass->methods [i])
6388                         return klass->method.first + 1 + i;
6389         }
6390         return 0;
6391 }
6392
6393 /*
6394  * Find the field index in the metadata FieldDef table.
6395  */
6396 static guint32
6397 find_field_index (MonoClass *klass, MonoClassField *field) {
6398         int i;
6399
6400         for (i = 0; i < klass->field.count; ++i) {
6401                 if (field == &klass->fields [i])
6402                         return klass->field.first + 1 + i;
6403         }
6404         return 0;
6405 }
6406
6407 /*
6408  * Find the property index in the metadata Property table.
6409  */
6410 static guint32
6411 find_property_index (MonoClass *klass, MonoProperty *property) {
6412         int i;
6413
6414         for (i = 0; i < klass->property.count; ++i) {
6415                 if (property == &klass->properties [i])
6416                         return klass->property.first + 1 + i;
6417         }
6418         return 0;
6419 }
6420
6421 /*
6422  * Find the event index in the metadata Event table.
6423  */
6424 static guint32
6425 find_event_index (MonoClass *klass, MonoEvent *event) {
6426         int i;
6427
6428         for (i = 0; i < klass->event.count; ++i) {
6429                 if (event == &klass->events [i])
6430                         return klass->event.first + 1 + i;
6431         }
6432         return 0;
6433 }
6434
6435 static MonoObject*
6436 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6437 {
6438         const char *p = data;
6439         const char *named;
6440         guint32 i, j, num_named;
6441         MonoObject *attr;
6442         void **params;
6443
6444         mono_class_init (method->klass);
6445
6446         if (len == 0) {
6447                 attr = mono_object_new (mono_domain_get (), method->klass);
6448                 mono_runtime_invoke (method, attr, NULL, NULL);
6449                 return attr;
6450         }
6451
6452         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6453                 return NULL;
6454
6455         /*g_print ("got attr %s\n", method->klass->name);*/
6456         
6457         params = g_new (void*, method->signature->param_count);
6458
6459         /* skip prolog */
6460         p += 2;
6461         for (i = 0; i < method->signature->param_count; ++i) {
6462                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6463         }
6464
6465         named = p;
6466         attr = mono_object_new (mono_domain_get (), method->klass);
6467         mono_runtime_invoke (method, attr, params, NULL);
6468         free_param_data (method->signature, params);
6469         g_free (params);
6470         num_named = read16 (named);
6471         named += 2;
6472         for (j = 0; j < num_named; j++) {
6473                 gint name_len;
6474                 char *name, named_type, data_type;
6475                 named_type = *named++;
6476                 data_type = *named++; /* type of data */
6477                 if (data_type == 0x55) {
6478                         gint type_len;
6479                         char *type_name;
6480                         type_len = mono_metadata_decode_blob_size (named, &named);
6481                         type_name = g_malloc (type_len + 1);
6482                         memcpy (type_name, named, type_len);
6483                         type_name [type_len] = 0;
6484                         named += type_len;
6485                         /* FIXME: lookup the type and check type consistency */
6486                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6487                         /* this seems to be the type of the element of the array */
6488                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6489                         named++;
6490                 }
6491                 name_len = mono_metadata_decode_blob_size (named, &named);
6492                 name = g_malloc (name_len + 1);
6493                 memcpy (name, named, name_len);
6494                 name [name_len] = 0;
6495                 named += name_len;
6496                 if (named_type == 0x53) {
6497                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6498                         void *val = load_cattr_value (image, field->type, named, &named);
6499                         mono_field_set_value (attr, field, val);
6500                         if (!type_is_reference (field->type))
6501                                 g_free (val);
6502                 } else if (named_type == 0x54) {
6503                         MonoProperty *prop;
6504                         void *pparams [1];
6505                         MonoType *prop_type;
6506
6507                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6508                         /* can we have more that 1 arg in a custom attr named property? */
6509                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6510                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6511                         mono_property_set_value (prop, attr, pparams, NULL);
6512                         if (!type_is_reference (prop_type))
6513                                 g_free (pparams [0]);
6514                 }
6515                 g_free (name);
6516         }
6517
6518         return attr;
6519 }
6520
6521 MonoArray*
6522 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6523 {
6524         MonoArray *result;
6525         MonoClass *klass;
6526         MonoObject *attr;
6527         int i;
6528
6529         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6530         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6531         for (i = 0; i < cinfo->num_attrs; ++i) {
6532                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6533                 mono_array_set (result, gpointer, i, attr);
6534         }
6535         return result;
6536 }
6537
6538 MonoCustomAttrInfo*
6539 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6540 {
6541         guint32 mtoken, i, len;
6542         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6543         MonoTableInfo *ca;
6544         MonoCustomAttrInfo *ainfo;
6545         GList *tmp, *list = NULL;
6546         const char *data;
6547
6548         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6549
6550         i = mono_metadata_custom_attrs_from_index (image, idx);
6551         if (!i)
6552                 return NULL;
6553         i --;
6554         while (i < ca->rows) {
6555                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6556                         break;
6557                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6558                 ++i;
6559         }
6560         len = g_list_length (list);
6561         if (!len)
6562                 return NULL;
6563         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6564         ainfo->num_attrs = len;
6565         ainfo->image = image;
6566         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6567                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6568                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6569                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6570                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6571                         mtoken |= MONO_TOKEN_METHOD_DEF;
6572                         break;
6573                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6574                         mtoken |= MONO_TOKEN_MEMBER_REF;
6575                         break;
6576                 default:
6577                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6578                         break;
6579                 }
6580                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6581                 if (!ainfo->attrs [i].ctor)
6582                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6583                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6584                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6585                 ainfo->attrs [i].data = data;
6586         }
6587         g_list_free (list);
6588
6589         return ainfo;
6590 }
6591
6592 MonoCustomAttrInfo*
6593 mono_custom_attrs_from_method (MonoMethod *method)
6594 {
6595         MonoCustomAttrInfo *cinfo;
6596         guint32 idx;
6597         
6598         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6599                 return cinfo;
6600         idx = find_method_index (method);
6601         idx <<= MONO_CUSTOM_ATTR_BITS;
6602         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6603         return mono_custom_attrs_from_index (method->klass->image, idx);
6604 }
6605
6606 MonoCustomAttrInfo*
6607 mono_custom_attrs_from_class (MonoClass *klass)
6608 {
6609         MonoCustomAttrInfo *cinfo;
6610         guint32 idx;
6611         
6612         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6613                 return cinfo;
6614         idx = mono_metadata_token_index (klass->type_token);
6615         idx <<= MONO_CUSTOM_ATTR_BITS;
6616         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6617         return mono_custom_attrs_from_index (klass->image, idx);
6618 }
6619
6620 MonoCustomAttrInfo*
6621 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6622 {
6623         MonoCustomAttrInfo *cinfo;
6624         guint32 idx;
6625         
6626         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6627                 return cinfo;
6628         idx = 1; /* there is only one assembly */
6629         idx <<= MONO_CUSTOM_ATTR_BITS;
6630         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6631         return mono_custom_attrs_from_index (assembly->image, idx);
6632 }
6633
6634 static MonoCustomAttrInfo*
6635 mono_custom_attrs_from_module (MonoImage *image)
6636 {
6637         MonoCustomAttrInfo *cinfo;
6638         guint32 idx;
6639         
6640         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6641                 return cinfo;
6642         idx = 1; /* there is only one module */
6643         idx <<= MONO_CUSTOM_ATTR_BITS;
6644         idx |= MONO_CUSTOM_ATTR_MODULE;
6645         return mono_custom_attrs_from_index (image, idx);
6646 }
6647
6648 MonoCustomAttrInfo*
6649 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6650 {
6651         MonoCustomAttrInfo *cinfo;
6652         guint32 idx;
6653         
6654         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6655                 return cinfo;
6656         idx = find_property_index (klass, property);
6657         idx <<= MONO_CUSTOM_ATTR_BITS;
6658         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6659         return mono_custom_attrs_from_index (klass->image, idx);
6660 }
6661
6662 MonoCustomAttrInfo*
6663 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6664 {
6665         MonoCustomAttrInfo *cinfo;
6666         guint32 idx;
6667         
6668         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6669                 return cinfo;
6670         idx = find_event_index (klass, event);
6671         idx <<= MONO_CUSTOM_ATTR_BITS;
6672         idx |= MONO_CUSTOM_ATTR_EVENT;
6673         return mono_custom_attrs_from_index (klass->image, idx);
6674 }
6675
6676 MonoCustomAttrInfo*
6677 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6678 {
6679         MonoCustomAttrInfo *cinfo;
6680         guint32 idx;
6681         
6682         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6683                 return cinfo;
6684         idx = find_field_index (klass, field);
6685         idx <<= MONO_CUSTOM_ATTR_BITS;
6686         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6687         return mono_custom_attrs_from_index (klass->image, idx);
6688 }
6689
6690 MonoCustomAttrInfo*
6691 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6692 {
6693         MonoTableInfo *ca;
6694         guint32 i, idx, method_index;
6695         guint32 param_list, param_last, param_pos, found;
6696         MonoImage *image;
6697         MonoReflectionMethodAux *aux;
6698
6699         if (method->klass->image->dynamic) {
6700                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6701                 if (!aux || !aux->param_cattr)
6702                         return NULL;
6703                 return aux->param_cattr [param];
6704         }
6705
6706         image = method->klass->image;
6707         method_index = find_method_index (method);
6708         ca = &image->tables [MONO_TABLE_METHOD];
6709
6710         if (method->klass->generic_inst || method->klass->generic_container ||
6711             method->signature->generic_param_count) {
6712                 /* FIXME FIXME FIXME */
6713                 return NULL;
6714         }
6715
6716         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6717         if (method_index == ca->rows) {
6718                 ca = &image->tables [MONO_TABLE_PARAM];
6719                 param_last = ca->rows + 1;
6720         } else {
6721                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6722                 ca = &image->tables [MONO_TABLE_PARAM];
6723         }
6724         found = FALSE;
6725         for (i = param_list; i < param_last; ++i) {
6726                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6727                 if (param_pos == param) {
6728                         found = TRUE;
6729                         break;
6730                 }
6731         }
6732         if (!found)
6733                 return NULL;
6734         idx = i;
6735         idx <<= MONO_CUSTOM_ATTR_BITS;
6736         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6737         return mono_custom_attrs_from_index (image, idx);
6738 }
6739
6740 /*
6741  * mono_reflection_get_custom_attrs:
6742  * @obj: a reflection object handle
6743  *
6744  * Return an array with all the custom attributes defined of the
6745  * reflection handle @obj. The objects are fully build.
6746  */
6747 MonoArray*
6748 mono_reflection_get_custom_attrs (MonoObject *obj)
6749 {
6750         MonoClass *klass;
6751         MonoArray *result;
6752         MonoCustomAttrInfo *cinfo = NULL;
6753         
6754         MONO_ARCH_SAVE_REGS;
6755
6756         klass = obj->vtable->klass;
6757         if (klass == mono_defaults.monotype_class) {
6758                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6759                 klass = mono_class_from_mono_type (rtype->type);
6760                 cinfo = mono_custom_attrs_from_class (klass);
6761         } else if (strcmp ("Assembly", klass->name) == 0) {
6762                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6763                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6764         } else if (strcmp ("Module", klass->name) == 0) {
6765                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6766                 cinfo = mono_custom_attrs_from_module (module->image);
6767         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6768                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6769                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6770         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6771                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6772                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6773         } else if (strcmp ("MonoField", klass->name) == 0) {
6774                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6775                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6776         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6777                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6778                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6779         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6780                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6781                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6782                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6783         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6784                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6785                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6786         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6787                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6788                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6789         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6790                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6791                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6792         } else { /* handle other types here... */
6793                 g_error ("get custom attrs not yet supported for %s", klass->name);
6794         }
6795
6796         if (cinfo) {
6797                 result = mono_custom_attrs_construct (cinfo);
6798                 if (!cinfo->cached)
6799                         mono_custom_attrs_free (cinfo);
6800         } else {
6801                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6802                 result = mono_array_new (mono_domain_get (), klass, 0);
6803         }
6804
6805         return result;
6806 }
6807
6808 static MonoMethodSignature*
6809 parameters_to_signature (MonoArray *parameters) {
6810         MonoMethodSignature *sig;
6811         int count, i;
6812
6813         count = parameters? mono_array_length (parameters): 0;
6814
6815         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6816         sig->param_count = count;
6817         sig->sentinelpos = -1; /* FIXME */
6818         for (i = 0; i < count; ++i) {
6819                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6820                 sig->params [i] = pt->type;
6821         }
6822         return sig;
6823 }
6824
6825 static MonoMethodSignature*
6826 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6827         MonoMethodSignature *sig;
6828
6829         sig = parameters_to_signature (ctor->parameters);
6830         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6831         sig->ret = &mono_defaults.void_class->byval_arg;
6832         return sig;
6833 }
6834
6835 static MonoMethodSignature*
6836 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6837         MonoMethodSignature *sig;
6838
6839         sig = parameters_to_signature (method->parameters);
6840         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6841         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6842         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6843         return sig;
6844 }
6845
6846 static MonoMethodSignature*
6847 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6848         MonoMethodSignature *sig;
6849
6850         sig = parameters_to_signature (method->parameters);
6851         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6852         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6853         sig->generic_param_count = 0;
6854         return sig;
6855 }
6856
6857 static void
6858 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6859 {
6860         MonoClass *klass = mono_object_class (prop);
6861         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6862                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6863                 *name = mono_string_to_utf8 (pb->name);
6864                 *type = pb->type->type;
6865         } else {
6866                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6867                 *name = g_strdup (p->property->name);
6868                 if (p->property->get)
6869                         *type = p->property->get->signature->ret;
6870                 else
6871                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6872         }
6873 }
6874
6875 static void
6876 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6877 {
6878         MonoClass *klass = mono_object_class (field);
6879         if (strcmp (klass->name, "FieldBuilder") == 0) {
6880                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6881                 *name = mono_string_to_utf8 (fb->name);
6882                 *type = fb->type->type;
6883         } else {
6884                 MonoReflectionField *f = (MonoReflectionField *)field;
6885                 *name = g_strdup (f->field->name);
6886                 *type = f->field->type;
6887         }
6888 }
6889
6890 /*
6891  * Encode a value in a custom attribute stream of bytes.
6892  * The value to encode is either supplied as an object in argument val
6893  * (valuetypes are boxed), or as a pointer to the data in the
6894  * argument argval.
6895  * @type represents the type of the value
6896  * @buffer is the start of the buffer
6897  * @p the current position in the buffer
6898  * @buflen contains the size of the buffer and is used to return the new buffer size
6899  * if this needs to be realloced.
6900  * @retbuffer and @retp return the start and the position of the buffer
6901  */
6902 static void
6903 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6904 {
6905         MonoTypeEnum simple_type;
6906         
6907         if ((p-buffer) + 10 >= *buflen) {
6908                 char *newbuf;
6909                 *buflen *= 2;
6910                 newbuf = g_realloc (buffer, *buflen);
6911                 p = newbuf + (p-buffer);
6912                 buffer = newbuf;
6913         }
6914         if (!argval)
6915                 argval = ((char*)arg + sizeof (MonoObject));
6916         simple_type = type->type;
6917 handle_enum:
6918         switch (simple_type) {
6919         case MONO_TYPE_BOOLEAN:
6920         case MONO_TYPE_U1:
6921         case MONO_TYPE_I1:
6922                 *p++ = *argval;
6923                 break;
6924         case MONO_TYPE_CHAR:
6925         case MONO_TYPE_U2:
6926         case MONO_TYPE_I2:
6927                 swap_with_size (p, argval, 2, 1);
6928                 p += 2;
6929                 break;
6930         case MONO_TYPE_U4:
6931         case MONO_TYPE_I4:
6932         case MONO_TYPE_R4:
6933                 swap_with_size (p, argval, 4, 1);
6934                 p += 4;
6935                 break;
6936         case MONO_TYPE_U8:
6937         case MONO_TYPE_I8:
6938         case MONO_TYPE_R8:
6939                 swap_with_size (p, argval, 8, 1);
6940                 p += 8;
6941                 break;
6942         case MONO_TYPE_VALUETYPE:
6943                 if (type->data.klass->enumtype) {
6944                         simple_type = type->data.klass->enum_basetype->type;
6945                         goto handle_enum;
6946                 } else {
6947                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6948                 }
6949                 break;
6950         case MONO_TYPE_STRING: {
6951                 char *str;
6952                 guint32 slen;
6953                 if (!arg) {
6954                         *p++ = 0xFF;
6955                         break;
6956                 }
6957                 str = mono_string_to_utf8 ((MonoString*)arg);
6958                 slen = strlen (str);
6959                 if ((p-buffer) + 10 + slen >= *buflen) {
6960                         char *newbuf;
6961                         *buflen *= 2;
6962                         *buflen += slen;
6963                         newbuf = g_realloc (buffer, *buflen);
6964                         p = newbuf + (p-buffer);
6965                         buffer = newbuf;
6966                 }
6967                 mono_metadata_encode_value (slen, p, &p);
6968                 memcpy (p, str, slen);
6969                 p += slen;
6970                 g_free (str);
6971                 break;
6972         }
6973         case MONO_TYPE_CLASS: {
6974                 char *str;
6975                 guint32 slen;
6976                 MonoClass *k;
6977                 if (!arg) {
6978                         *p++ = 0xFF;
6979                         break;
6980                 }
6981                 k = mono_object_class (arg);
6982                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6983                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6984                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6985 handle_type:
6986                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6987                 slen = strlen (str);
6988                 if ((p-buffer) + 10 + slen >= *buflen) {
6989                         char *newbuf;
6990                         *buflen *= 2;
6991                         *buflen += slen;
6992                         newbuf = g_realloc (buffer, *buflen);
6993                         p = newbuf + (p-buffer);
6994                         buffer = newbuf;
6995                 }
6996                 mono_metadata_encode_value (slen, p, &p);
6997                 memcpy (p, str, slen);
6998                 p += slen;
6999                 g_free (str);
7000                 break;
7001         }
7002         case MONO_TYPE_SZARRAY: {
7003                 int len, i;
7004                 MonoClass *eclass, *arg_eclass;
7005
7006                 if (!arg) {
7007                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7008                         break;
7009                 }
7010                 len = mono_array_length ((MonoArray*)arg);
7011                 *p++ = len & 0xff;
7012                 *p++ = (len >> 8) & 0xff;
7013                 *p++ = (len >> 16) & 0xff;
7014                 *p++ = (len >> 24) & 0xff;
7015                 *retp = p;
7016                 *retbuffer = buffer;
7017                 eclass = type->data.klass;
7018                 arg_eclass = mono_object_class (arg)->element_class;
7019                 if (eclass->valuetype && arg_eclass->valuetype) {
7020                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7021                         int elsize = mono_class_array_element_size (eclass);
7022                         for (i = 0; i < len; ++i) {
7023                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7024                                 elptr += elsize;
7025                         }
7026                 } else {
7027                         for (i = 0; i < len; ++i) {
7028                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7029                         }
7030                 }
7031                 break;
7032         }
7033         /* it may be a boxed value or a Type */
7034         case MONO_TYPE_OBJECT: {
7035                 MonoClass *klass = mono_object_class (arg);
7036                 char *str;
7037                 guint32 slen;
7038                 
7039                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7040                         *p++ = 0x50;
7041                         goto handle_type;
7042                 } else if (klass->enumtype) {
7043                         *p++ = 0x55;
7044                 } else if (klass == mono_defaults.string_class) {
7045                         simple_type = MONO_TYPE_STRING;
7046                         *p++ = 0x0E;
7047                         goto handle_enum;
7048                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7049                         *p++ = simple_type = klass->byval_arg.type;
7050                         goto handle_enum;
7051                 } else {
7052                         g_error ("unhandled type in custom attr");
7053                 }
7054                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7055                 slen = strlen (str);
7056                 if ((p-buffer) + 10 + slen >= *buflen) {
7057                         char *newbuf;
7058                         *buflen *= 2;
7059                         *buflen += slen;
7060                         newbuf = g_realloc (buffer, *buflen);
7061                         p = newbuf + (p-buffer);
7062                         buffer = newbuf;
7063                 }
7064                 mono_metadata_encode_value (slen, p, &p);
7065                 memcpy (p, str, slen);
7066                 p += slen;
7067                 g_free (str);
7068                 simple_type = klass->enum_basetype->type;
7069                 goto handle_enum;
7070         }
7071         default:
7072                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7073         }
7074         *retp = p;
7075         *retbuffer = buffer;
7076 }
7077
7078 /*
7079  * mono_reflection_get_custom_attrs_blob:
7080  * @ctor: custom attribute constructor
7081  * @ctorArgs: arguments o the constructor
7082  * @properties:
7083  * @propValues:
7084  * @fields:
7085  * @fieldValues:
7086  * 
7087  * Creates the blob of data that needs to be saved in the metadata and that represents
7088  * the custom attributed described by @ctor, @ctorArgs etc.
7089  * Returns: a Byte array representing the blob of data.
7090  */
7091 MonoArray*
7092 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
7093 {
7094         MonoArray *result;
7095         MonoMethodSignature *sig;
7096         MonoObject *arg;
7097         char *buffer, *p;
7098         guint32 buflen, i;
7099
7100         MONO_ARCH_SAVE_REGS;
7101
7102         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7103                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7104         } else {
7105                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7106         }
7107         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7108         buflen = 256;
7109         p = buffer = g_malloc (buflen);
7110         /* write the prolog */
7111         *p++ = 1;
7112         *p++ = 0;
7113         for (i = 0; i < sig->param_count; ++i) {
7114                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7115                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7116         }
7117         i = 0;
7118         if (properties)
7119                 i += mono_array_length (properties);
7120         if (fields)
7121                 i += mono_array_length (fields);
7122         *p++ = i & 0xff;
7123         *p++ = (i >> 8) & 0xff;
7124         if (properties) {
7125                 MonoObject *prop;
7126                 for (i = 0; i < mono_array_length (properties); ++i) {
7127                         MonoType *ptype;
7128                         char *pname;
7129                         int len;
7130                         
7131                         prop = mono_array_get (properties, gpointer, i);
7132                         get_prop_name_and_type (prop, &pname, &ptype);
7133                         *p++ = 0x54; /* PROPERTY signature */
7134
7135                         /* Preallocate a large enough buffer */
7136                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7137                                 char *str = type_get_qualified_name (ptype, NULL);
7138                                 len = strlen (str);
7139                                 g_free (str);
7140                         }
7141                         else
7142                                 len = 0;
7143                         len += strlen (pname);
7144
7145                         if ((p-buffer) + 20 + len >= buflen) {
7146                                 char *newbuf;
7147                                 buflen *= 2;
7148                                 buflen += len;
7149                                 newbuf = g_realloc (buffer, buflen);
7150                                 p = newbuf + (p-buffer);
7151                                 buffer = newbuf;
7152                         }
7153
7154                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7155                                 char *str = type_get_qualified_name (ptype, NULL);
7156                                 int slen = strlen (str);
7157
7158                                 *p++ = 0x55;
7159                                 /*
7160                                  * This seems to be optional...
7161                                  * *p++ = 0x80;
7162                                  */
7163                                 mono_metadata_encode_value (slen, p, &p);
7164                                 memcpy (p, str, slen);
7165                                 p += slen;
7166                                 g_free (str);
7167                         } else {
7168                                 mono_metadata_encode_value (ptype->type, p, &p);
7169                                 if (ptype->type == MONO_TYPE_SZARRAY)
7170                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7171                         }
7172                         len = strlen (pname);
7173                         mono_metadata_encode_value (len, p, &p);
7174                         memcpy (p, pname, len);
7175                         p += len;
7176                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7177                         g_free (pname);
7178                 }
7179         }
7180
7181         if (fields) {
7182                 MonoObject *field;
7183                 for (i = 0; i < mono_array_length (fields); ++i) {
7184                         MonoType *ftype;
7185                         char *fname;
7186                         int len;
7187                         
7188                         field = mono_array_get (fields, gpointer, i);
7189                         get_field_name_and_type (field, &fname, &ftype);
7190                         *p++ = 0x53; /* FIELD signature */
7191                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7192                                 char *str = type_get_qualified_name (ftype, NULL);
7193                                 int slen = strlen (str);
7194                                 if ((p-buffer) + 10 + slen >= buflen) {
7195                                         char *newbuf;
7196                                         buflen *= 2;
7197                                         buflen += slen;
7198                                         newbuf = g_realloc (buffer, buflen);
7199                                         p = newbuf + (p-buffer);
7200                                         buffer = newbuf;
7201                                 }
7202                                 *p++ = 0x55;
7203                                 /*
7204                                  * This seems to be optional...
7205                                  * *p++ = 0x80;
7206                                  */
7207                                 mono_metadata_encode_value (slen, p, &p);
7208                                 memcpy (p, str, slen);
7209                                 p += slen;
7210                                 g_free (str);
7211                         } else {
7212                                 mono_metadata_encode_value (ftype->type, p, &p);
7213                                 if (ftype->type == MONO_TYPE_SZARRAY)
7214                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7215                         }
7216                         len = strlen (fname);
7217                         mono_metadata_encode_value (len, p, &p);
7218                         memcpy (p, fname, len);
7219                         p += len;
7220                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7221                         g_free (fname);
7222                 }
7223         }
7224
7225         g_assert (p - buffer <= buflen);
7226         buflen = p - buffer;
7227         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7228         p = mono_array_addr (result, char, 0);
7229         memcpy (p, buffer, buflen);
7230         g_free (buffer);
7231         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7232                 g_free (sig);
7233         return result;
7234 }
7235
7236 /*
7237  * mono_reflection_setup_internal_class:
7238  * @tb: a TypeBuilder object
7239  *
7240  * Creates a MonoClass that represents the TypeBuilder.
7241  * This is a trick that lets us simplify a lot of reflection code
7242  * (and will allow us to support Build and Run assemblies easier).
7243  */
7244 void
7245 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7246 {
7247         MonoClass *klass, *parent;
7248
7249         MONO_ARCH_SAVE_REGS;
7250
7251         if (tb->parent) {
7252                 /* check so we can compile corlib correctly */
7253                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7254                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7255                         parent = tb->parent->type->data.klass;
7256                 } else {
7257                         parent = my_mono_class_from_mono_type (tb->parent->type);
7258                 }
7259         } else {
7260                 parent = NULL;
7261         }
7262         
7263         /* the type has already being created: it means we just have to change the parent */
7264         if (tb->type.type) {
7265                 klass = mono_class_from_mono_type (tb->type.type);
7266                 klass->parent = NULL;
7267                 /* fool mono_class_setup_parent */
7268                 g_free (klass->supertypes);
7269                 klass->supertypes = NULL;
7270                 mono_class_setup_parent (klass, parent);
7271                 mono_class_setup_mono_type (klass);
7272                 return;
7273         }
7274         
7275         klass = g_new0 (MonoClass, 1);
7276
7277         klass->image = &tb->module->dynamic_image->image;
7278
7279         klass->inited = 1; /* we lie to the runtime */
7280         klass->name = mono_string_to_utf8 (tb->name);
7281         klass->name_space = mono_string_to_utf8 (tb->nspace);
7282         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7283         klass->flags = tb->attrs;
7284
7285         klass->element_class = klass;
7286         klass->reflection_info = tb; /* need to pin. */
7287
7288         /* Put into cache so mono_class_get () will find it */
7289         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7290
7291         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7292                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7293
7294         if (parent != NULL) {
7295                 mono_class_setup_parent (klass, parent);
7296         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7297                 const char *old_n = klass->name;
7298                 /* trick to get relative numbering right when compiling corlib */
7299                 klass->name = "BuildingObject";
7300                 mono_class_setup_parent (klass, mono_defaults.object_class);
7301                 klass->name = old_n;
7302         }
7303
7304         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7305                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7306                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7307                 klass->instance_size = sizeof (MonoObject);
7308                 klass->size_inited = 1;
7309                 mono_class_setup_vtable (klass, NULL, 0);
7310         }
7311
7312         mono_class_setup_mono_type (klass);
7313
7314         mono_class_setup_supertypes (klass);
7315
7316         /*
7317          * FIXME: handle interfaces.
7318          */
7319
7320         tb->type.type = &klass->byval_arg;
7321
7322         if (tb->nesting_type) {
7323                 g_assert (tb->nesting_type->type);
7324                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7325         }
7326
7327         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7328 }
7329
7330 /*
7331  * mono_reflection_setup_generic_class:
7332  * @tb: a TypeBuilder object
7333  *
7334  * Setup the generic class before adding the first generic parameter.
7335  */
7336 void
7337 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7338 {
7339         MonoClass *klass;
7340
7341         MONO_ARCH_SAVE_REGS;
7342
7343         klass = my_mono_class_from_mono_type (tb->type.type);
7344         if (tb->generic_container)
7345                 return;
7346
7347         tb->generic_container = g_new0 (MonoGenericContainer, 1);
7348         tb->generic_container->klass = klass;
7349
7350         tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7351         tb->generic_container->context->container = tb->generic_container;
7352 }
7353
7354 /*
7355  * mono_reflection_create_generic_class:
7356  * @tb: a TypeBuilder object
7357  *
7358  * Creates the generic class after all generic parameters have been added.
7359  */
7360 void
7361 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7362 {
7363         MonoClass *klass;
7364         int count, i;
7365
7366         MONO_ARCH_SAVE_REGS;
7367
7368         klass = my_mono_class_from_mono_type (tb->type.type);
7369
7370         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7371
7372         if (klass->generic_container || (count == 0))
7373                 return;
7374
7375         g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7376
7377         klass->generic_container = tb->generic_container;
7378
7379         klass->generic_container->type_argc = count;
7380         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7381
7382         for (i = 0; i < count; i++) {
7383                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7384                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7385                 g_assert (klass->generic_container->type_params [i].owner);
7386         }
7387 }
7388
7389 /*
7390  * mono_reflection_create_internal_class:
7391  * @tb: a TypeBuilder object
7392  *
7393  * Actually create the MonoClass that is associated with the TypeBuilder.
7394  */
7395 void
7396 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7397 {
7398         MonoClass *klass;
7399
7400         MONO_ARCH_SAVE_REGS;
7401
7402         klass = my_mono_class_from_mono_type (tb->type.type);
7403
7404         if (klass->enumtype && klass->enum_basetype == NULL) {
7405                 MonoReflectionFieldBuilder *fb;
7406                 MonoClass *ec;
7407
7408                 g_assert (tb->fields != NULL);
7409                 g_assert (mono_array_length (tb->fields) >= 1);
7410
7411                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7412
7413                 klass->enum_basetype = fb->type->type;
7414                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7415                 if (!klass->element_class)
7416                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7417
7418                 /*
7419                  * get the element_class from the current corlib.
7420                  */
7421                 ec = default_class_from_mono_type (klass->enum_basetype);
7422                 klass->instance_size = ec->instance_size;
7423                 klass->size_inited = 1;
7424                 /* 
7425                  * this is almost safe to do with enums and it's needed to be able
7426                  * to create objects of the enum type (for use in SetConstant).
7427                  */
7428                 /* FIXME: Does this mean enums can't have method overrides ? */
7429                 mono_class_setup_vtable (klass, NULL, 0);
7430         }
7431 }
7432
7433 static MonoMarshalSpec*
7434 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7435                                                                 MonoReflectionMarshal *minfo)
7436 {
7437         MonoMarshalSpec *res;
7438
7439         res = g_new0 (MonoMarshalSpec, 1);
7440         res->native = minfo->type;
7441
7442         switch (minfo->type) {
7443         case MONO_NATIVE_LPARRAY:
7444                 res->data.array_data.elem_type = minfo->eltype;
7445                 res->data.array_data.param_num = 0; /* Not yet */
7446                 res->data.array_data.num_elem = minfo->count;
7447                 break;
7448
7449         case MONO_NATIVE_BYVALTSTR:
7450         case MONO_NATIVE_BYVALARRAY:
7451                 res->data.array_data.num_elem = minfo->count;
7452                 break;
7453
7454         case MONO_NATIVE_CUSTOM:
7455                 if (minfo->marshaltyperef)
7456                         res->data.custom_data.custom_name =
7457                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7458                 if (minfo->mcookie)
7459                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7460                 break;
7461
7462         default:
7463                 break;
7464         }
7465
7466         return res;
7467 }
7468
7469 MonoReflectionMarshal*
7470 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7471                                                                                    MonoMarshalSpec *spec)
7472 {
7473         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7474         MonoReflectionMarshal *minfo;
7475         MonoType *mtype;
7476
7477         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7478                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7479                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7480                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7481         }
7482
7483         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7484         minfo->type = spec->native;
7485
7486         switch (minfo->type) {
7487         case MONO_NATIVE_LPARRAY:
7488                 minfo->eltype = spec->data.array_data.elem_type;
7489                 minfo->count = spec->data.array_data.num_elem;
7490                 break;
7491
7492         case MONO_NATIVE_BYVALTSTR:
7493         case MONO_NATIVE_BYVALARRAY:
7494                 minfo->count = spec->data.array_data.num_elem;
7495                 break;
7496
7497         case MONO_NATIVE_CUSTOM:
7498                 if (spec->data.custom_data.custom_name) {
7499                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7500                         if (mtype)
7501                                 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7502
7503                         minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7504                 }
7505                 if (spec->data.custom_data.cookie)
7506                         minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7507                 break;
7508
7509         default:
7510                 break;
7511         }
7512
7513         return minfo;
7514 }
7515
7516 static MonoMethod*
7517 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7518                                          ReflectionMethodBuilder *rmb,
7519                                          MonoMethodSignature *sig)
7520 {
7521         MonoMethod *m;
7522         MonoMethodNormal *pm;
7523         MonoMarshalSpec **specs;
7524         MonoReflectionMethodAux *method_aux;
7525         int i;
7526
7527         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7528                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7529                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7530         else if (rmb->refs)
7531                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7532         else
7533                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7534
7535         pm = (MonoMethodNormal*)m;
7536
7537         m->slot = -1;
7538         m->flags = rmb->attrs;
7539         m->iflags = rmb->iattrs;
7540         m->name = mono_string_to_utf8 (rmb->name);
7541         m->klass = klass;
7542         m->signature = sig;
7543         if (rmb->table_idx)
7544                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7545
7546         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7547                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7548                         m->string_ctor = 1;
7549
7550                 m->signature->pinvoke = 1;
7551         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7552                 m->signature->pinvoke = 1;
7553
7554                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7555
7556                 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7557                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7558                 
7559                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7560
7561                 if (klass->image->dynamic)
7562                         mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7563
7564                 return m;
7565         } else if (!m->klass->dummy && 
7566                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7567                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7568                 MonoMethodHeader *header;
7569                 guint32 code_size;
7570                 gint32 max_stack, i;
7571                 gint32 num_locals = 0;
7572                 gint32 num_clauses = 0;
7573                 guint8 *code;
7574
7575                 if (rmb->ilgen) {
7576                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7577                         code_size = rmb->ilgen->code_len;
7578                         max_stack = rmb->ilgen->max_stack;
7579                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7580                         if (rmb->ilgen->ex_handlers)
7581                                 num_clauses = method_count_clauses (rmb->ilgen);
7582                 } else {
7583                         if (rmb->code) {
7584                                 code = mono_array_addr (rmb->code, guint8, 0);
7585                                 code_size = mono_array_length (rmb->code);
7586                                 /* we probably need to run a verifier on the code... */
7587                                 max_stack = 8; 
7588                         }
7589                         else {
7590                                 code = NULL;
7591                                 code_size = 0;
7592                                 max_stack = 8;
7593                         }
7594                 }
7595
7596                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7597                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7598                 header->code_size = code_size;
7599                 header->code = g_malloc (code_size);
7600                 memcpy ((char*)header->code, code, code_size);
7601                 header->max_stack = max_stack;
7602                 header->init_locals = rmb->init_locals;
7603                 header->num_locals = num_locals;
7604
7605                 for (i = 0; i < num_locals; ++i) {
7606                         MonoReflectionLocalBuilder *lb = 
7607                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7608
7609                         header->locals [i] = g_new0 (MonoType, 1);
7610                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7611                 }
7612
7613                 header->num_clauses = num_clauses;
7614                 if (num_clauses) {
7615                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7616                                  rmb->ilgen, num_clauses);
7617                 }
7618
7619                 pm->header = header;
7620         }
7621
7622         if (rmb->generic_params) {
7623                 int count = mono_array_length (rmb->generic_params);
7624                 MonoGenericContainer *container;
7625
7626                 pm->generic_container = container = rmb->generic_container;
7627                 container->type_argc = count;
7628                 container->type_params = g_new0 (MonoGenericParam, count);
7629
7630                 for (i = 0; i < count; i++) {
7631                         MonoReflectionGenericParam *gp =
7632                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7633
7634                         container->type_params [i] = *gp->type.type->data.generic_param;
7635                 }
7636         }
7637
7638         if (rmb->refs) {
7639                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7640                 int i;
7641
7642                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7643
7644                 for (i = 0; i < rmb->nrefs; ++i)
7645                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7646         }
7647
7648         method_aux = NULL;
7649
7650         /* Parameter info */
7651         if (rmb->pinfo) {
7652                 if (!method_aux)
7653                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7654                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7655                 for (i = 0; i <= m->signature->param_count; ++i) {
7656                         MonoReflectionParamBuilder *pb;
7657                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7658                                 if (i > 0)
7659                                         m->signature->params [i - 1]->attrs = pb->attrs;
7660
7661                                 if (pb->def_value) {
7662                                         MonoDynamicImage *assembly;
7663                                         guint32 idx, def_type, len;
7664                                         char *p;
7665                                         const char *p2;
7666
7667                                         if (!method_aux->param_defaults)
7668                                                 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7669                                         assembly = (MonoDynamicImage*)klass->image;
7670                                         idx = encode_constant (assembly, pb->def_value, &def_type);
7671                                         /* Copy the data from the blob since it might get realloc-ed */
7672                                         p = assembly->blob.data + idx;
7673                                         len = mono_metadata_decode_blob_size (p, &p2);
7674                                         len += p2 - p;
7675                                         method_aux->param_defaults [i] = g_malloc (len);
7676                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7677                                 }
7678
7679                                 if (pb->name)
7680                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7681                                 if (pb->cattrs) {
7682                                         if (!method_aux->param_cattr)
7683                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7684                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7685                                 }
7686                         }
7687                 }
7688         }
7689
7690         /* Parameter marshalling */
7691         specs = NULL;
7692         if (rmb->pinfo)         
7693                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7694                         MonoReflectionParamBuilder *pb;
7695                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7696                                 if (pb->marshal_info) {
7697                                         if (specs == NULL)
7698                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7699                                         specs [pb->position] = 
7700                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7701                                 }
7702                         }
7703                 }
7704         if (specs != NULL) {
7705                 if (!method_aux)
7706                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7707                 method_aux->param_marshall = specs;
7708         }
7709
7710         if (klass->image->dynamic && method_aux)
7711                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7712
7713         return m;
7714 }       
7715
7716 static MonoMethod*
7717 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7718 {
7719         ReflectionMethodBuilder rmb;
7720         MonoMethodSignature *sig;
7721
7722         sig = ctor_builder_to_signature (mb);
7723
7724         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7725
7726         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7727         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7728
7729         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7730                 /* ilgen is no longer needed */
7731                 mb->ilgen = NULL;
7732         }
7733
7734         return mb->mhandle;
7735 }
7736
7737 static MonoMethod*
7738 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7739 {
7740         ReflectionMethodBuilder rmb;
7741         MonoMethodSignature *sig;
7742
7743         sig = method_builder_to_signature (mb);
7744
7745         reflection_methodbuilder_from_method_builder (&rmb, mb);
7746
7747         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7748         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7749
7750         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7751                 /* ilgen is no longer needed */
7752                 mb->ilgen = NULL;
7753         }
7754         return mb->mhandle;
7755 }
7756
7757 static MonoClassField*
7758 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7759 {
7760         MonoClassField *field;
7761         const char *p, *p2;
7762         guint32 len, idx;
7763
7764         if (fb->handle)
7765                 return fb->handle;
7766
7767         field = g_new0 (MonoClassField, 1);
7768
7769         field->name = mono_string_to_utf8 (fb->name);
7770         if (fb->attrs) {
7771                 /* FIXME: handle type modifiers */
7772                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7773                 field->type->attrs = fb->attrs;
7774         } else {
7775                 field->type = fb->type->type;
7776         }
7777         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7778                 field->data = mono_array_addr (fb->rva_data, char, 0);
7779         if (fb->offset != -1)
7780                 field->offset = fb->offset;
7781         field->parent = klass;
7782         fb->handle = field;
7783         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7784
7785         if (fb->def_value) {
7786                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7787                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7788                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7789                 /* Copy the data from the blob since it might get realloc-ed */
7790                 p = assembly->blob.data + idx;
7791                 len = mono_metadata_decode_blob_size (p, &p2);
7792                 len += p2 - p;
7793                 field->data = g_malloc (len);
7794                 memcpy ((gpointer)field->data, p, len);
7795         }
7796
7797         return field;
7798 }
7799
7800 static MonoType*
7801 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7802                                             MonoType *parent)
7803 {
7804         MonoClass *klass, *gklass;
7805         MonoReflectionTypeBuilder *tb = NULL;
7806         MonoGenericInst *ginst, *cached;
7807         MonoDomain *domain;
7808         MonoType *geninst;
7809         int icount, i;
7810
7811         klass = mono_class_from_mono_type (type->type);
7812         if (!klass->generic_container && !klass->generic_inst &&
7813             !(klass->nested_in && klass->nested_in->generic_container))
7814                 return NULL;
7815
7816         mono_loader_lock ();
7817
7818         domain = mono_object_domain (type);
7819
7820         ginst = g_new0 (MonoGenericInst, 1);
7821
7822         ginst->type_argc = type_argc;
7823         ginst->type_argv = types;
7824
7825         for (i = 0; i < ginst->type_argc; ++i) {
7826                 if (!ginst->is_open)
7827                         ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7828         }
7829
7830         ginst->generic_type = &klass->byval_arg;
7831
7832         if (klass->generic_inst) {
7833                 MonoGenericInst *kginst = klass->generic_inst;
7834                 MonoGenericInst *oginst = ginst;
7835
7836                 oginst->context = g_new0 (MonoGenericContext, 1);
7837                 oginst->context->ginst = oginst;
7838
7839                 ginst = g_new0 (MonoGenericInst, 1);
7840
7841                 ginst->type_argc = kginst->type_argc;
7842                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7843
7844                 for (i = 0; i < ginst->type_argc; i++) {
7845                         MonoType *t = kginst->type_argv [i];
7846
7847                         t = mono_class_inflate_generic_type (t, oginst->context);
7848
7849                         if (!ginst->is_open)
7850                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7851
7852                         ginst->type_argv [i] = t;
7853                 }
7854
7855                 ginst->generic_type = kginst->generic_type;
7856         }
7857
7858         geninst = g_new0 (MonoType, 1);
7859         geninst->type = MONO_TYPE_GENERICINST;
7860
7861         cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7862         if (cached) {
7863                 g_free (ginst);
7864                 mono_loader_unlock ();
7865                 geninst->data.generic_inst = cached;
7866                 return geninst;
7867         }
7868
7869         gklass = mono_class_from_mono_type (ginst->generic_type);
7870         g_assert ((ginst->container = gklass->generic_container) != NULL);
7871
7872         geninst->data.generic_inst = ginst;
7873
7874         ginst->parent = parent;
7875
7876         ginst->context = g_new0 (MonoGenericContext, 1);
7877         ginst->context->ginst = ginst;
7878
7879         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7880                 tb = (MonoReflectionTypeBuilder *) type;
7881
7882                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7883                 ginst->is_dynamic = TRUE;
7884         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7885                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7886                 MonoReflectionType *rgt = rgi->generic_type;
7887
7888                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7889                 tb = (MonoReflectionTypeBuilder *) rgt;
7890
7891                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7892                 ginst->is_dynamic = TRUE;
7893         } else {
7894                 icount = klass->interface_count;
7895         }
7896
7897         ginst->ifaces = g_new0 (MonoType *, icount);
7898         ginst->count_ifaces = icount;
7899
7900         for (i = 0; i < icount; i++) {
7901                 MonoReflectionType *itype;
7902
7903                 if (tb)
7904                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7905                 else
7906                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7907                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7908                 if (!ginst->ifaces [i])
7909                         ginst->ifaces [i] = itype->type;
7910         }
7911
7912         mono_class_create_generic (ginst);
7913         mono_class_create_generic_2 (ginst);
7914
7915         g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7916
7917         mono_loader_unlock ();
7918
7919         return geninst;
7920 }
7921
7922 MonoType*
7923 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7924 {
7925         MonoClass *klass, *pklass = NULL;
7926         MonoReflectionType *parent = NULL;
7927         MonoType *the_parent = NULL, *geninst;
7928         MonoReflectionTypeBuilder *tb = NULL;
7929         MonoGenericInst *ginst;
7930         MonoDomain *domain;
7931
7932         domain = mono_object_domain (type);
7933         klass = mono_class_from_mono_type (type->type);
7934
7935         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7936                 tb = (MonoReflectionTypeBuilder *) type;
7937
7938                 if (tb->parent) {
7939                         parent = tb->parent;
7940                         pklass = mono_class_from_mono_type (parent->type);
7941                 }
7942         } else {
7943                 pklass = klass->parent;
7944                 if (pklass)
7945                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7946                 else if (klass->generic_inst && klass->generic_inst->parent) {
7947                         parent = mono_type_get_object (domain, klass->generic_inst->parent);
7948                         pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7949                 }
7950         }
7951
7952         if (pklass && pklass->generic_inst)
7953                 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7954
7955         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7956         if (!geninst)
7957                 return NULL;
7958
7959         ginst = geninst->data.generic_inst;
7960
7961         return geninst;
7962 }
7963
7964 MonoReflectionMethod*
7965 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7966 {
7967         MonoMethod *method, *inflated;
7968         MonoReflectionMethodBuilder *mb = NULL;
7969         MonoGenericContainer *container;
7970         MonoGenericMethod *gmethod;
7971         MonoGenericContext *context;
7972         int count, i;
7973
7974         MONO_ARCH_SAVE_REGS;
7975         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7976                 MonoReflectionTypeBuilder *tb;
7977                 MonoClass *klass;
7978
7979                 mb = (MonoReflectionMethodBuilder *) rmethod;
7980                 tb = (MonoReflectionTypeBuilder *) mb->type;
7981                 klass = mono_class_from_mono_type (tb->type.type);
7982
7983                 method = methodbuilder_to_mono_method (klass, mb);
7984         } else {
7985                 method = rmethod->method;
7986         }
7987
7988         count = method->signature->generic_param_count;
7989         if (count != mono_array_length (types))
7990                 return NULL;
7991
7992         container = ((MonoMethodNormal*) method)->generic_container;
7993         g_assert (container);
7994
7995         if (!container->method_hash)
7996                 container->method_hash = g_hash_table_new (
7997                         mono_metadata_generic_method_hash, mono_metadata_generic_method_equal);
7998
7999         gmethod = g_new0 (MonoGenericMethod, 1);
8000         gmethod->mtype_argc = count;
8001         gmethod->mtype_argv = g_new0 (MonoType *, count);
8002         for (i = 0; i < count; i++) {
8003                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8004                 gmethod->mtype_argv [i] = garg->type;
8005         }
8006
8007         inflated = g_hash_table_lookup (container->method_hash, gmethod);
8008         if (inflated) {
8009                 g_free (gmethod->mtype_argv);
8010                 g_free (gmethod);
8011
8012                 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8013         }
8014
8015         gmethod->reflection_info = rmethod;
8016
8017         context = g_new0 (MonoGenericContext, 1);
8018         context->ginst = method->klass->generic_inst;
8019         context->gmethod = gmethod;
8020
8021         inflated = mono_class_inflate_generic_method (method, context, NULL);
8022         g_hash_table_insert (container->method_hash, gmethod, inflated);
8023
8024         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8025 }
8026
8027 static MonoMethod *
8028 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
8029 {
8030         MonoGenericMethod *gmethod;
8031         MonoGenericInst *ginst;
8032         MonoGenericContext *context;
8033         int i;
8034
8035         ginst = type->type.type->data.generic_inst;
8036
8037         gmethod = g_new0 (MonoGenericMethod, 1);
8038         gmethod->reflection_info = obj;
8039
8040         gmethod->mtype_argc = method->signature->generic_param_count;
8041         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
8042
8043         for (i = 0; i < gmethod->mtype_argc; i++) {
8044                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8045                 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8046
8047                 g_assert (gparam->pklass);
8048                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
8049         }
8050
8051         context = g_new0 (MonoGenericContext, 1);
8052         context->ginst = ginst;
8053         context->gmethod = gmethod;
8054
8055         return mono_class_inflate_generic_method (method, context, ginst->klass);
8056 }
8057
8058 static MonoMethod *
8059 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8060 {
8061         MonoMethod *method;
8062         MonoClass *klass;
8063
8064         klass = mono_class_from_mono_type (type->type.type);
8065
8066         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8067                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8068         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8069                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8070         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8071                 method = ((MonoReflectionMethod *) obj)->method;
8072         else {
8073                 method = NULL; /* prevent compiler warning */
8074                 g_assert_not_reached ();
8075         }
8076
8077         return inflate_mono_method (type, method, obj);
8078 }
8079
8080 void
8081 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods, 
8082         MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8083 {
8084         MonoGenericInst *ginst;
8085         MonoDynamicGenericInst *dginst;
8086         MonoClass *klass, *gklass, *pklass;
8087         int i;
8088
8089         MONO_ARCH_SAVE_REGS;
8090
8091         klass = mono_class_from_mono_type (type->type.type);
8092         ginst = type->type.type->data.generic_inst;
8093
8094         if (ginst->initialized)
8095                 return;
8096
8097         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8098
8099         gklass = mono_class_from_mono_type (ginst->generic_type);
8100         mono_class_init (gklass);
8101
8102         if (ginst->parent)
8103                 pklass = mono_class_from_mono_type (ginst->parent);
8104         else
8105                 pklass = gklass->parent;
8106
8107         mono_class_setup_parent (klass, pklass);
8108
8109         dginst->count_methods = methods ? mono_array_length (methods) : 0;
8110         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8111         dginst->count_fields = fields ? mono_array_length (fields) : 0;
8112         dginst->count_properties = properties ? mono_array_length (properties) : 0;
8113         dginst->count_events = events ? mono_array_length (events) : 0;
8114
8115         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8116         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8117         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8118         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8119         dginst->events = g_new0 (MonoEvent, dginst->count_events);
8120
8121         for (i = 0; i < dginst->count_methods; i++) {
8122                 MonoObject *obj = mono_array_get (methods, gpointer, i);
8123
8124                 dginst->methods [i] = inflate_method (type, obj);
8125         }
8126
8127         for (i = 0; i < dginst->count_ctors; i++) {
8128                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8129
8130                 dginst->ctors [i] = inflate_method (type, obj);
8131         }
8132
8133         for (i = 0; i < dginst->count_fields; i++) {
8134                 MonoObject *obj = mono_array_get (fields, gpointer, i);
8135                 MonoClassField *field;
8136                 MonoInflatedField *ifield;
8137
8138                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8139                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8140                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8141                         field = ((MonoReflectionField *) obj)->field;
8142                 else {
8143                         field = NULL; /* prevent compiler warning */
8144                         g_assert_not_reached ();
8145                 }
8146
8147                 ifield = g_new0 (MonoInflatedField, 1);
8148                 ifield->generic_type = field->type;
8149                 ifield->reflection_info = obj;
8150
8151                 dginst->fields [i] = *field;
8152                 dginst->fields [i].generic_info = ifield;
8153                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8154         }
8155
8156         for (i = 0; i < dginst->count_properties; i++) {
8157                 MonoObject *obj = mono_array_get (properties, gpointer, i);
8158                 MonoProperty *property = &dginst->properties [i];
8159
8160                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8161                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8162
8163                         property->parent = klass;
8164                         property->attrs = pb->attrs;
8165                         property->name = mono_string_to_utf8 (pb->name);
8166                         if (pb->get_method)
8167                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8168                         if (pb->set_method)
8169                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8170                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8171                         *property = *((MonoReflectionProperty *) obj)->property;
8172
8173                         if (property->get)
8174                                 property->get = inflate_mono_method (type, property->get, NULL);
8175                         if (property->set)
8176                                 property->set = inflate_mono_method (type, property->set, NULL);
8177                 } else
8178                         g_assert_not_reached ();
8179         }
8180
8181         for (i = 0; i < dginst->count_events; i++) {
8182                 MonoObject *obj = mono_array_get (events, gpointer, i);
8183                 MonoEvent *event = &dginst->events [i];
8184
8185                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8186                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8187
8188                         event->parent = klass;
8189                         event->attrs = eb->attrs;
8190                         event->name = mono_string_to_utf8 (eb->name);
8191                         if (eb->add_method)
8192                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8193                         if (eb->remove_method)
8194                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8195                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8196                         *event = *((MonoReflectionEvent *) obj)->event;
8197
8198                         if (event->add)
8199                                 event->add = inflate_mono_method (type, event->add, NULL);
8200                         if (event->remove)
8201                                 event->remove = inflate_mono_method (type, event->remove, NULL);
8202                 } else
8203                         g_assert_not_reached ();
8204         }
8205
8206         ginst->initialized = TRUE;
8207 }
8208
8209 static void
8210 ensure_runtime_vtable (MonoClass *klass)
8211 {
8212         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8213         int i, num, j, onum;
8214         MonoMethod **overrides;
8215
8216         if (!tb || klass->wastypebuilder)
8217                 return;
8218         if (klass->parent)
8219                 ensure_runtime_vtable (klass->parent);
8220
8221         num = tb->ctors? mono_array_length (tb->ctors): 0;
8222         num += tb->num_methods;
8223         klass->method.count = num;
8224         klass->methods = g_new (MonoMethod*, num);
8225         num = tb->ctors? mono_array_length (tb->ctors): 0;
8226         for (i = 0; i < num; ++i)
8227                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8228         num = tb->num_methods;
8229         j = i;
8230         for (i = 0; i < num; ++i)
8231                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8232
8233         if (tb->interfaces) {
8234                 klass->interface_count = mono_array_length (tb->interfaces);
8235                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8236                 for (i = 0; i < klass->interface_count; ++i) {
8237                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8238                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8239                 }
8240         }
8241
8242         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8243                 for (i = 0; i < klass->method.count; ++i)
8244                         klass->methods [i]->slot = i;
8245
8246         /* Overrides */
8247         onum = 0;
8248         if (tb->methods) {
8249                 for (i = 0; i < tb->num_methods; ++i) {
8250                         MonoReflectionMethodBuilder *mb = 
8251                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8252                         if (mb->override_method)
8253                                 onum ++;
8254                 }
8255         }
8256
8257         overrides = g_new0 (MonoMethod*, onum * 2);
8258
8259         if (tb->methods) {
8260                 onum = 0;
8261                 for (i = 0; i < tb->num_methods; ++i) {
8262                         MonoReflectionMethodBuilder *mb = 
8263                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8264                         if (mb->override_method) {
8265                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8266                                 overrides [onum * 2] = 
8267                                         mb->override_method->method;
8268                                 overrides [onum * 2 + 1] =
8269                                         mb->mhandle;
8270
8271                                 g_assert (mb->mhandle);
8272
8273                                 onum ++;
8274                         }
8275                 }
8276         }
8277
8278         mono_class_setup_vtable (klass, overrides, onum);
8279         g_free (overrides);
8280 }
8281
8282 static void
8283 typebuilder_setup_fields (MonoClass *klass)
8284 {
8285         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8286         MonoReflectionFieldBuilder *fb;
8287         MonoClassField *field;
8288         const char *p, *p2;
8289         int i;
8290         guint32 len, idx;
8291
8292         klass->field.count = tb->num_fields;
8293         klass->field.first = 0;
8294         klass->field.last = klass->field.count;
8295
8296         if (!klass->field.count)
8297                 return;
8298         
8299         klass->fields = g_new0 (MonoClassField, klass->field.count);
8300
8301         for (i = 0; i < klass->field.count; ++i) {
8302                 fb = mono_array_get (tb->fields, gpointer, i);
8303                 field = &klass->fields [i];
8304                 field->name = mono_string_to_utf8 (fb->name);
8305                 if (fb->attrs) {
8306                         /* FIXME: handle type modifiers */
8307                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
8308                         field->type->attrs = fb->attrs;
8309                 } else {
8310                         field->type = fb->type->type;
8311                 }
8312                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8313                         field->data = mono_array_addr (fb->rva_data, char, 0);
8314                 if (fb->offset != -1)
8315                         field->offset = fb->offset;
8316                 field->parent = klass;
8317                 fb->handle = field;
8318                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8319
8320                 if (fb->def_value) {
8321                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8322                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8323                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
8324                         /* Copy the data from the blob since it might get realloc-ed */
8325                         p = assembly->blob.data + idx;
8326                         len = mono_metadata_decode_blob_size (p, &p2);
8327                         len += p2 - p;
8328                         field->data = g_malloc (len);
8329                         memcpy ((gpointer)field->data, p, len);
8330                 }
8331         }
8332         mono_class_layout_fields (klass);
8333 }
8334
8335 static void
8336 typebuilder_setup_properties (MonoClass *klass)
8337 {
8338         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8339         MonoReflectionPropertyBuilder *pb;
8340         int i;
8341
8342         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8343         klass->property.first = 0;
8344         klass->property.last = klass->property.count;
8345
8346         klass->properties = g_new0 (MonoProperty, klass->property.count);
8347         for (i = 0; i < klass->property.count; ++i) {
8348                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8349                 klass->properties [i].parent = klass;
8350                 klass->properties [i].attrs = pb->attrs;
8351                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8352                 if (pb->get_method)
8353                         klass->properties [i].get = pb->get_method->mhandle;
8354                 if (pb->set_method)
8355                         klass->properties [i].set = pb->set_method->mhandle;
8356         }
8357 }
8358
8359 MonoReflectionEvent *
8360 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8361 {
8362         MonoEvent *event = g_new0 (MonoEvent, 1);
8363         MonoClass *klass;
8364         int j;
8365
8366         klass = my_mono_class_from_mono_type (tb->type.type);
8367
8368         event->parent = klass;
8369         event->attrs = eb->attrs;
8370         event->name = mono_string_to_utf8 (eb->name);
8371         if (eb->add_method)
8372                 event->add = eb->add_method->mhandle;
8373         if (eb->remove_method)
8374                 event->remove = eb->remove_method->mhandle;
8375         if (eb->raise_method)
8376                 event->raise = eb->raise_method->mhandle;
8377
8378         if (eb->other_methods) {
8379                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8380                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8381                         MonoReflectionMethodBuilder *mb = 
8382                                 mono_array_get (eb->other_methods,
8383                                                 MonoReflectionMethodBuilder*, j);
8384                         event->other [j] = mb->mhandle;
8385                 }
8386         }
8387
8388         return mono_event_get_object (mono_object_domain (tb), klass, event);
8389 }
8390
8391 static void
8392 typebuilder_setup_events (MonoClass *klass)
8393 {
8394         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8395         MonoReflectionEventBuilder *eb;
8396         int i, j;
8397
8398         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8399         klass->event.first = 0;
8400         klass->event.last = klass->event.count;
8401
8402         klass->events = g_new0 (MonoEvent, klass->event.count);
8403         for (i = 0; i < klass->event.count; ++i) {
8404                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8405                 klass->events [i].parent = klass;
8406                 klass->events [i].attrs = eb->attrs;
8407                 klass->events [i].name = mono_string_to_utf8 (eb->name);
8408                 if (eb->add_method)
8409                         klass->events [i].add = eb->add_method->mhandle;
8410                 if (eb->remove_method)
8411                         klass->events [i].remove = eb->remove_method->mhandle;
8412                 if (eb->raise_method)
8413                         klass->events [i].raise = eb->raise_method->mhandle;
8414
8415                 if (eb->other_methods) {
8416                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8417                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8418                                 MonoReflectionMethodBuilder *mb = 
8419                                         mono_array_get (eb->other_methods,
8420                                                                         MonoReflectionMethodBuilder*, j);
8421                                 klass->events [i].other [j] = mb->mhandle;
8422                         }
8423                 }
8424         }
8425 }
8426
8427 MonoReflectionType*
8428 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8429 {
8430         MonoClass *klass;
8431         MonoReflectionType* res;
8432         int i;
8433
8434         MONO_ARCH_SAVE_REGS;
8435
8436         klass = my_mono_class_from_mono_type (tb->type.type);
8437
8438         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8439
8440         /*
8441          * Fields to set in klass:
8442          * the various flags: delegate/unicode/contextbound etc.
8443          */
8444         klass->flags = tb->attrs;
8445
8446         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8447                 /* No need to fully construct the type */
8448                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8449
8450         /* enums are done right away */
8451         if (!klass->enumtype)
8452                 ensure_runtime_vtable (klass);
8453
8454         if (tb->subtypes) {
8455                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8456                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8457                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8458                 }
8459         }
8460
8461         /* fields and object layout */
8462         if (klass->parent) {
8463                 if (!klass->parent->size_inited)
8464                         mono_class_init (klass->parent);
8465                 klass->instance_size += klass->parent->instance_size;
8466                 klass->class_size += klass->parent->class_size;
8467                 klass->min_align = klass->parent->min_align;
8468         } else {
8469                 klass->instance_size = sizeof (MonoObject);
8470                 klass->min_align = 1;
8471         }
8472
8473         /* FIXME: handle packing_size and instance_size */
8474         typebuilder_setup_fields (klass);
8475
8476         typebuilder_setup_properties (klass);
8477
8478         typebuilder_setup_events (klass);
8479
8480         klass->wastypebuilder = TRUE;
8481
8482         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8483         g_assert (res != (MonoReflectionType*)tb);
8484         return res;
8485 }
8486
8487 void
8488 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8489 {
8490         MonoGenericParam *param;
8491         MonoImage *image;
8492
8493         MONO_ARCH_SAVE_REGS;
8494
8495         param = g_new0 (MonoGenericParam, 1);
8496
8497         if (gparam->mbuilder) {
8498                 if (!gparam->mbuilder->generic_container)
8499                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8500                 param->owner = gparam->mbuilder->generic_container;
8501         } else if (gparam->tbuilder) {
8502                 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8503                 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8504
8505                 while (nesting) {
8506                         int count;
8507
8508                         count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8509                         if (gparam->index >= count)
8510                                 break;
8511
8512                         container = nesting->generic_container;
8513                         nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8514                 }
8515
8516                 g_assert (container);
8517                 param->owner = container;
8518         }
8519
8520         param->method = NULL;
8521         param->name = mono_string_to_utf8 (gparam->name);
8522         param->num = gparam->index;
8523
8524         image = &gparam->tbuilder->module->dynamic_image->image;
8525         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8526
8527         param->pklass->reflection_info = gparam;
8528
8529         gparam->type.type = g_new0 (MonoType, 1);
8530         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8531         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8532         gparam->type.type->data.generic_param = param;
8533 }
8534
8535 MonoArray *
8536 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8537 {
8538         MonoDynamicImage *assembly = sig->module->dynamic_image;
8539         guint32 na = mono_array_length (sig->arguments);
8540         guint32 buflen, i;
8541         MonoArray *result;
8542         char *buf, *p;
8543
8544         MONO_ARCH_SAVE_REGS;
8545
8546         p = buf = g_malloc (10 + na * 10);
8547
8548         mono_metadata_encode_value (0x07, p, &p);
8549         mono_metadata_encode_value (na, p, &p);
8550         for (i = 0; i < na; ++i) {
8551                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8552                 encode_reflection_type (assembly, type, p, &p);
8553         }
8554
8555         buflen = p - buf;
8556         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8557         p = mono_array_addr (result, char, 0);
8558         memcpy (p, buf, buflen);
8559         g_free (buf);
8560
8561         return result;
8562 }
8563
8564 MonoArray *
8565 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8566 {
8567         MonoDynamicImage *assembly = sig->module->dynamic_image;
8568         guint32 na = mono_array_length (sig->arguments);
8569         guint32 buflen, i;
8570         MonoArray *result;
8571         char *buf, *p;
8572
8573         MONO_ARCH_SAVE_REGS;
8574
8575         p = buf = g_malloc (10 + na * 10);
8576
8577         mono_metadata_encode_value (0x06, p, &p);
8578         for (i = 0; i < na; ++i) {
8579                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8580                 encode_reflection_type (assembly, type, p, &p);
8581         }
8582
8583         buflen = p - buf;
8584         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8585         p = mono_array_addr (result, char, 0);
8586         memcpy (p, buf, buflen);
8587         g_free (buf);
8588
8589         return result;
8590 }
8591
8592 void 
8593 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8594 {
8595         ReflectionMethodBuilder rmb;
8596         MonoMethodSignature *sig;
8597         int i;
8598
8599         sig = dynamic_method_to_signature (mb);
8600
8601         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8602
8603         /*
8604          * Resolve references.
8605          */
8606         rmb.nrefs = mb->nrefs;
8607         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8608         for (i = 0; i < mb->nrefs; ++i) {
8609                 gpointer ref = resolve_object (mb->module->image, 
8610                                                mono_array_get (mb->refs, MonoObject*, i));
8611                 if (!ref) {
8612                         g_free (rmb.refs);
8613                         mono_raise_exception (mono_get_exception_type_load (NULL));
8614                         return;
8615                 }
8616                 rmb.refs [i] = ref;
8617         }               
8618
8619         /* FIXME: class */
8620         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8621
8622         g_free (rmb.refs);
8623
8624         /* ilgen is no longer needed */
8625         mb->ilgen = NULL;
8626 }
8627
8628 /**
8629  * mono_reflection_lookup_dynamic_token:
8630  *
8631  *  Finish the Builder object pointed to by TOKEN and return the corresponding
8632  * runtime structure.
8633  */
8634 gpointer
8635 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8636 {
8637         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8638         MonoObject *obj;
8639
8640         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8641         g_assert (obj);
8642
8643         return resolve_object (image, obj);
8644 }
8645
8646 static gpointer
8647 resolve_object (MonoImage *image, MonoObject *obj)
8648 {
8649         gpointer result = NULL;
8650
8651         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8652                 result = mono_string_intern ((MonoString*)obj);
8653                 g_assert (result);
8654         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8655                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8656                 result = mono_class_from_mono_type (tb->type);
8657                 g_assert (result);
8658         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8659                 result = ((MonoReflectionMethod*)obj)->method;
8660                 g_assert (result);
8661         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8662                 result = ((MonoReflectionMethod*)obj)->method;
8663                 g_assert (result);
8664         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8665                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8666                 result = mb->mhandle;
8667                 if (!result) {
8668                         /* Type is not yet created */
8669                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8670
8671                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8672
8673                         /*
8674                          * Hopefully this has been filled in by calling CreateType() on the
8675                          * TypeBuilder.
8676                          */
8677                         /**
8678                          * TODO: This won't work if the application finishes another 
8679                          * TypeBuilder instance instead of this one.
8680                          */
8681                         result = mb->mhandle;
8682                 }
8683         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8684                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8685
8686                 result = cb->mhandle;
8687                 if (!result) {
8688                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8689
8690                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8691                         result = cb->mhandle;
8692                 }
8693         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8694                 result = ((MonoReflectionField*)obj)->field;
8695                 g_assert (result);
8696         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8697                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8698                 result = fb->handle;
8699
8700                 if (!result) {
8701                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8702
8703                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8704                         result = fb->handle;
8705                 }
8706         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8707                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8708                 MonoClass *klass;
8709
8710                 klass = tb->type.type->data.klass;
8711                 if (klass->wastypebuilder) {
8712                         /* Already created */
8713                         result = klass;
8714                 }
8715                 else {
8716                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8717                         result = tb->type.type->data.klass;
8718                         g_assert (result);
8719                 }
8720         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8721                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8722                 MonoMethodSignature *sig;
8723                 int nargs, i;
8724
8725                 if (helper->arguments)
8726                         nargs = mono_array_length (helper->arguments);
8727                 else
8728                         nargs = 0;
8729
8730                 sig = mono_metadata_signature_alloc (image, nargs);
8731                 sig->explicit_this = helper->call_conv & 64;
8732                 sig->hasthis = helper->call_conv & 32;
8733
8734                 if (helper->call_conv == 0) /* unmanaged */
8735                         sig->call_convention = helper->unmanaged_call_conv - 1;
8736                 else
8737                         if (helper->call_conv & 0x02)
8738                                 sig->call_convention = MONO_CALL_VARARG;
8739                 else
8740                         sig->call_convention = MONO_CALL_DEFAULT;
8741
8742                 sig->param_count = nargs;
8743                 /* TODO: Copy type ? */
8744                 sig->ret = helper->return_type->type;
8745                 for (i = 0; i < nargs; ++i) {
8746                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8747                         sig->params [i] = rt->type;
8748                 }
8749
8750                 result = sig;
8751         } else {
8752                 g_print (obj->vtable->klass->name);
8753                 g_assert_not_reached ();
8754         }
8755         return result;
8756 }
8757