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