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