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