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