2006-12-11 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/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                 offset = mono_array_length (rsrc->data);
3746                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3747                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3748                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3749                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3750
3751                 if (!mb->is_main)
3752                         /* 
3753                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3754                          * the main module, but that needs to reference the FILE table
3755                          * which isn't emitted yet.
3756                          */
3757                         return;
3758                 else
3759                         idx = 0;
3760         }
3761
3762         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3763 }
3764
3765 static void
3766 set_version_from_string (MonoString *version, guint32 *values)
3767 {
3768         gchar *ver, *p, *str;
3769         guint32 i;
3770         
3771         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3772         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3773         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3774         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3775         if (!version)
3776                 return;
3777         ver = str = mono_string_to_utf8 (version);
3778         for (i = 0; i < 4; ++i) {
3779                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3780                 switch (*p) {
3781                 case '.':
3782                         p++;
3783                         break;
3784                 case '*':
3785                         /* handle Revision and Build */
3786                         p++;
3787                         break;
3788                 }
3789                 ver = p;
3790         }
3791         g_free (str);
3792 }
3793
3794 static guint32
3795 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3796         gsize len;
3797         guint32 token = 0;
3798         char blob_size [6];
3799         char *b = blob_size;
3800
3801         if (!pkey)
3802                 return token;
3803
3804         len = mono_array_length (pkey);
3805         mono_metadata_encode_value (len, b, &b);
3806         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3807         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3808
3809         /* Special case: check for ECMA key (16 bytes) */
3810         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3811                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3812                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3813         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3814                 /* minimum key size (in 2.0) is 384 bits */
3815                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3816         } else {
3817                 /* FIXME - verifier */
3818                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3819                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3820         }
3821         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3822
3823         return token;
3824 }
3825
3826 static void
3827 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3828 {
3829         MonoDynamicTable *table;
3830         MonoDynamicImage *assembly;
3831         MonoReflectionAssemblyBuilder *assemblyb;
3832         MonoDomain *domain;
3833         guint32 *values;
3834         int i;
3835         guint32 module_index;
3836
3837         assemblyb = moduleb->assemblyb;
3838         assembly = moduleb->dynamic_image;
3839         domain = mono_object_domain (assemblyb);
3840
3841         /* Emit ASSEMBLY table */
3842         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3843         alloc_table (table, 1);
3844         values = table->values + MONO_ASSEMBLY_SIZE;
3845         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3846         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3847         if (assemblyb->culture) {
3848                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3849         } else {
3850                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3851         }
3852         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3853         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3854         set_version_from_string (assemblyb->version, values);
3855
3856         /* Emit FILE + EXPORTED_TYPE table */
3857         module_index = 0;
3858         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3859                 int j;
3860                 MonoReflectionModuleBuilder *file_module = 
3861                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3862                 if (file_module != moduleb) {
3863                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3864                         module_index ++;
3865                         if (file_module->types) {
3866                                 for (j = 0; j < file_module->num_types; ++j) {
3867                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3868                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3869                                 }
3870                         }
3871                 }
3872         }
3873         if (assemblyb->loaded_modules) {
3874                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3875                         MonoReflectionModule *file_module = 
3876                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3877                         mono_image_fill_file_table (domain, file_module, assembly);
3878                         module_index ++;
3879                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3880                 }
3881         }
3882         if (assemblyb->type_forwarders)
3883                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3884
3885         /* Emit MANIFESTRESOURCE table */
3886         module_index = 0;
3887         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3888                 int j;
3889                 MonoReflectionModuleBuilder *file_module = 
3890                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3891                 /* The table for the main module is emitted later */
3892                 if (file_module != moduleb) {
3893                         module_index ++;
3894                         if (file_module->resources) {
3895                                 int len = mono_array_length (file_module->resources);
3896                                 for (j = 0; j < len; ++j) {
3897                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3898                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3899                                 }
3900                         }
3901                 }
3902         }               
3903 }
3904
3905 /*
3906  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3907  * for the modulebuilder @moduleb.
3908  * At the end of the process, method and field tokens are fixed up and the 
3909  * on-disk compressed metadata representation is created.
3910  */
3911 void
3912 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3913 {
3914         MonoDynamicTable *table;
3915         MonoDynamicImage *assembly;
3916         MonoReflectionAssemblyBuilder *assemblyb;
3917         MonoDomain *domain;
3918         GPtrArray *types;
3919         guint32 *values;
3920         int i, j;
3921
3922         assemblyb = moduleb->assemblyb;
3923         assembly = moduleb->dynamic_image;
3924         domain = mono_object_domain (assemblyb);
3925
3926         if (assembly->text_rva)
3927                 return;
3928
3929         assembly->text_rva = START_TEXT_RVA;
3930
3931         if (moduleb->is_main) {
3932                 mono_image_emit_manifest (moduleb);
3933         }
3934
3935         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3936         table->rows = 1; /* .<Module> */
3937         table->next_idx++;
3938         alloc_table (table, table->rows);
3939         /*
3940          * Set the first entry.
3941          */
3942         values = table->values + table->columns;
3943         values [MONO_TYPEDEF_FLAGS] = 0;
3944         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3945         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3946         values [MONO_TYPEDEF_EXTENDS] = 0;
3947         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3948         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3949
3950         /* 
3951          * handle global methods 
3952          * FIXME: test what to do when global methods are defined in multiple modules.
3953          */
3954         if (moduleb->global_methods) {
3955                 table = &assembly->tables [MONO_TABLE_METHOD];
3956                 table->rows += mono_array_length (moduleb->global_methods);
3957                 alloc_table (table, table->rows);
3958                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3959                         mono_image_get_method_info (
3960                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3961         }
3962         if (moduleb->global_fields) {
3963                 table = &assembly->tables [MONO_TABLE_FIELD];
3964                 table->rows += mono_array_length (moduleb->global_fields);
3965                 alloc_table (table, table->rows);
3966                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3967                         mono_image_get_field_info (
3968                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3969         }
3970
3971         table = &assembly->tables [MONO_TABLE_MODULE];
3972         alloc_table (table, 1);
3973         mono_image_fill_module_table (domain, moduleb, assembly);
3974
3975         /* Collect all types into a list sorted by their table_idx */
3976         types = g_ptr_array_new ();
3977
3978         if (moduleb->types)
3979                 for (i = 0; i < moduleb->num_types; ++i) {
3980                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3981                         collect_types (types, type);
3982                 }
3983
3984         g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3985         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3986         table->rows += types->len;
3987         alloc_table (table, table->rows);
3988
3989         /*
3990          * Emit type names + namespaces at one place inside the string heap,
3991          * so load_class_names () needs to touch fewer pages.
3992          */
3993         for (i = 0; i < types->len; ++i) {
3994                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3995                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3996         }
3997         for (i = 0; i < types->len; ++i) {
3998                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3999                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4000         }
4001
4002         for (i = 0; i < types->len; ++i) {
4003                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4004                 mono_image_get_type_info (domain, type, assembly);
4005         }
4006
4007         /* 
4008          * table->rows is already set above and in mono_image_fill_module_table.
4009          */
4010         /* add all the custom attributes at the end, once all the indexes are stable */
4011         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4012
4013         /* CAS assembly permissions */
4014         if (assemblyb->permissions_minimum)
4015                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4016         if (assemblyb->permissions_optional)
4017                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4018         if (assemblyb->permissions_refused)
4019                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4020
4021         module_add_cattrs (assembly, moduleb);
4022
4023         /* fixup tokens */
4024         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4025
4026         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4027          * the final tokens and don't need another fixup pass. */
4028
4029         if (moduleb->global_methods) {
4030                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4031                         MonoReflectionMethodBuilder *mb = mono_array_get (
4032                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4033                         mono_image_add_methodimpl (assembly, mb);
4034                 }
4035         }
4036
4037         for (i = 0; i < types->len; ++i) {
4038                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4039                 if (type->methods) {
4040                         for (j = 0; j < type->num_methods; ++j) {
4041                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4042                                         type->methods, MonoReflectionMethodBuilder*, j);
4043
4044                                 mono_image_add_methodimpl (assembly, mb);
4045                         }
4046                 }
4047         }
4048
4049         g_ptr_array_free (types, TRUE);
4050
4051         fixup_cattrs (assembly);
4052 }
4053
4054 /*
4055  * mono_image_insert_string:
4056  * @module: module builder object
4057  * @str: a string
4058  *
4059  * Insert @str into the user string stream of @module.
4060  */
4061 guint32
4062 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4063 {
4064         MonoDynamicImage *assembly;
4065         guint32 idx;
4066         char buf [16];
4067         char *b = buf;
4068         
4069         MONO_ARCH_SAVE_REGS;
4070
4071         if (!module->dynamic_image)
4072                 mono_image_module_basic_init (module);
4073
4074         assembly = module->dynamic_image;
4075         
4076         if (assembly->save) {
4077                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4078                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4079 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4080         {
4081                 char *swapped = g_malloc (2 * mono_string_length (str));
4082                 const char *p = (const char*)mono_string_chars (str);
4083
4084                 swap_with_size (swapped, p, 2, mono_string_length (str));
4085                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4086                 g_free (swapped);
4087         }
4088 #else
4089                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4090 #endif
4091                 mono_image_add_stream_data (&assembly->us, "", 1);
4092         } else {
4093                 idx = assembly->us.index ++;
4094         }
4095
4096         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4097
4098         return MONO_TOKEN_STRING | idx;
4099 }
4100
4101 guint32
4102 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4103 {
4104         MonoClass *klass;
4105         guint32 token = 0;
4106
4107         klass = obj->vtable->klass;
4108         if (strcmp (klass->name, "MonoMethod") == 0) {
4109                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4110                 MonoMethodSignature *sig, *old;
4111                 guint32 sig_token, parent;
4112                 int nargs, i;
4113
4114                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4115
4116                 nargs = mono_array_length (opt_param_types);
4117                 old = mono_method_signature (method);
4118                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4119
4120                 sig->hasthis = old->hasthis;
4121                 sig->explicit_this = old->explicit_this;
4122                 sig->call_convention = old->call_convention;
4123                 sig->generic_param_count = old->generic_param_count;
4124                 sig->param_count = old->param_count + nargs;
4125                 sig->sentinelpos = old->param_count;
4126                 sig->ret = old->ret;
4127
4128                 for (i = 0; i < old->param_count; i++)
4129                         sig->params [i] = old->params [i];
4130
4131                 for (i = 0; i < nargs; i++) {
4132                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4133                         sig->params [old->param_count + i] = rt->type;
4134                 }
4135
4136                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4137                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4138                 parent >>= MONO_TYPEDEFORREF_BITS;
4139
4140                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4141                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4142
4143                 sig_token = method_encode_signature (assembly, sig);
4144                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4145         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4146                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4147                 ReflectionMethodBuilder rmb;
4148                 guint32 parent, sig;
4149         
4150                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4151                 rmb.opt_types = opt_param_types;
4152
4153                 sig = method_builder_encode_signature (assembly, &rmb);
4154
4155                 parent = mono_image_create_token (assembly, obj, TRUE);
4156                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4157
4158                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4159                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4160
4161                 token = mono_image_get_varargs_method_token (
4162                         assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4163         } else {
4164                 g_error ("requested method token for %s\n", klass->name);
4165         }
4166
4167         return token;
4168 }
4169
4170 /*
4171  * mono_image_create_token:
4172  * @assembly: a dynamic assembly
4173  * @obj:
4174  *
4175  * Get a token to insert in the IL code stream for the given MemberInfo.
4176  * @obj can be one of:
4177  *      ConstructorBuilder
4178  *      MethodBuilder
4179  *      FieldBuilder
4180  *      MonoCMethod
4181  *      MonoMethod
4182  *      MonoField
4183  *      MonoType
4184  *      TypeBuilder
4185  */
4186 guint32
4187 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4188 {
4189         MonoClass *klass;
4190         guint32 token = 0;
4191
4192         klass = obj->vtable->klass;
4193         if (strcmp (klass->name, "MethodBuilder") == 0) {
4194                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4195
4196                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4197                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4198                 else
4199                         token = mono_image_get_methodbuilder_token (assembly, mb);
4200                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4201         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4202                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4203
4204                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4205                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4206                 else
4207                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4208                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4209         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4210                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4211                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4212                 if (tb->generic_params) {
4213                         token = mono_image_get_generic_field_token (assembly, fb);
4214                 } else {
4215                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4216                 }
4217         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4218                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4219                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4220         } else if (strcmp (klass->name, "MonoType") == 0 ||
4221                  strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4222                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4223                 token = mono_metadata_token_from_dor (
4224                         mono_image_typedef_or_ref (assembly, tb->type));
4225         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4226                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4227                 token = mono_metadata_token_from_dor (
4228                         mono_image_typedef_or_ref (assembly, tb->type));
4229         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4230                    strcmp (klass->name, "MonoMethod") == 0 ||
4231                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4232                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4233                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4234                 if (m->method->is_inflated) {
4235                         if (create_methodspec)
4236                                 token = mono_image_get_methodspec_token (assembly, m->method);
4237                         else
4238                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4239                 } else if ((m->method->klass->image == &assembly->image) &&
4240                          !m->method->klass->generic_class) {
4241                         static guint32 method_table_idx = 0xffffff;
4242                         if (m->method->klass->wastypebuilder) {
4243                                 /* we use the same token as the one that was assigned
4244                                  * to the Methodbuilder.
4245                                  * FIXME: do the equivalent for Fields.
4246                                  */
4247                                 token = m->method->token;
4248                         } else {
4249                                 /*
4250                                  * Each token should have a unique index, but the indexes are
4251                                  * assigned by managed code, so we don't know about them. An
4252                                  * easy solution is to count backwards...
4253                                  */
4254                                 method_table_idx --;
4255                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4256                         }
4257                 } else {
4258                         token = mono_image_get_methodref_token (assembly, m->method);
4259                 }
4260                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4261         } else if (strcmp (klass->name, "MonoField") == 0) {
4262                 MonoReflectionField *f = (MonoReflectionField *)obj;
4263                 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4264                         static guint32 field_table_idx = 0xffffff;
4265                         field_table_idx --;
4266                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4267                 } else {
4268                         token = mono_image_get_fieldref_token (assembly, f);
4269                 }
4270                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4271         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4272                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4273                 token = mono_image_get_array_token (assembly, m);
4274         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4275                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4276                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4277         } else {
4278                 g_error ("requested token for %s\n", klass->name);
4279         }
4280
4281         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4282
4283         return token;
4284 }
4285
4286 typedef struct {
4287         guint32 import_lookup_table;
4288         guint32 timestamp;
4289         guint32 forwarder;
4290         guint32 name_rva;
4291         guint32 import_address_table_rva;
4292 } MonoIDT;
4293
4294 typedef struct {
4295         guint32 name_rva;
4296         guint32 flags;
4297 } MonoILT;
4298
4299 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4300
4301 static MonoDynamicImage*
4302 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4303 {
4304         static const guchar entrycode [16] = {0xff, 0x25, 0};
4305         MonoDynamicImage *image;
4306         int i;
4307
4308         const char *version = mono_get_runtime_info ()->runtime_version;
4309
4310 #if HAVE_BOEHM_GC
4311         image = GC_MALLOC (sizeof (MonoDynamicImage));
4312 #else
4313         image = g_new0 (MonoDynamicImage, 1);
4314 #endif
4315
4316         /*g_print ("created image %p\n", image);*/
4317         /* keep in sync with image.c */
4318         image->image.name = assembly_name;
4319         image->image.assembly_name = image->image.name; /* they may be different */
4320         image->image.module_name = module_name;
4321         image->image.version = g_strdup (version);
4322         image->image.md_version_major = 1;
4323         image->image.md_version_minor = 1;
4324         image->image.dynamic = TRUE;
4325
4326         image->image.references = g_new0 (MonoAssembly*, 1);
4327         image->image.references [0] = NULL;
4328
4329         mono_image_init (&image->image);
4330
4331         image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4332         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4333         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4334         image->method_aux_hash = g_hash_table_new (NULL, NULL);
4335         image->handleref = g_hash_table_new (NULL, NULL);
4336         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4337         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4338         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4339         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4340         image->gen_params = g_ptr_array_new ();
4341
4342         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4343         string_heap_init (&image->sheap);
4344         mono_image_add_stream_data (&image->us, "", 1);
4345         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4346         /* import tables... */
4347         mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4348         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4349         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4350         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4351         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4352         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4353         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4354         stream_data_align (&image->code);
4355
4356         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4357
4358         for (i=0; i < MONO_TABLE_NUM; ++i) {
4359                 image->tables [i].next_idx = 1;
4360                 image->tables [i].columns = table_sizes [i];
4361         }
4362
4363         image->image.assembly = (MonoAssembly*)assembly;
4364         image->run = assembly->run;
4365         image->save = assembly->save;
4366         image->pe_kind = 0x1; /* ILOnly */
4367         image->machine = 0x14c; /* I386 */
4368
4369         return image;
4370 }
4371
4372 /*
4373  * mono_image_basic_init:
4374  * @assembly: an assembly builder object
4375  *
4376  * Create the MonoImage that represents the assembly builder and setup some
4377  * of the helper hash table and the basic metadata streams.
4378  */
4379 void
4380 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4381 {
4382         MonoDynamicAssembly *assembly;
4383         MonoDynamicImage *image;
4384         MonoDomain *domain = mono_object_domain (assemblyb);
4385         
4386         MONO_ARCH_SAVE_REGS;
4387
4388         if (assemblyb->dynamic_assembly)
4389                 return;
4390
4391 #if HAVE_BOEHM_GC
4392         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4393 #else
4394         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4395 #endif
4396
4397         assembly->assembly.ref_count = 1;
4398         assembly->assembly.dynamic = TRUE;
4399         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4400         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4401         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4402         if (assemblyb->culture)
4403                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4404         else
4405                 assembly->assembly.aname.culture = g_strdup ("");
4406
4407         if (assemblyb->version) {
4408                         char *vstr = mono_string_to_utf8 (assemblyb->version);
4409                         char **version = g_strsplit (vstr, ".", 4);
4410                         char **parts = version;
4411                         assembly->assembly.aname.major = atoi (*parts++);
4412                         assembly->assembly.aname.minor = atoi (*parts++);
4413                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4414                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4415
4416                         g_strfreev (version);
4417                         g_free (vstr);
4418         } else {
4419                         assembly->assembly.aname.major = 0;
4420                         assembly->assembly.aname.minor = 0;
4421                         assembly->assembly.aname.build = 0;
4422                         assembly->assembly.aname.revision = 0;
4423         }
4424
4425         assembly->run = assemblyb->access != 2;
4426         assembly->save = assemblyb->access != 1;
4427
4428         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4429         image->initial_image = TRUE;
4430         assembly->assembly.aname.name = image->image.name;
4431         assembly->assembly.image = &image->image;
4432
4433         mono_domain_assemblies_lock (domain);
4434         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4435         mono_domain_assemblies_unlock (domain);
4436
4437         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4438         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4439 }
4440
4441 static int
4442 calc_section_size (MonoDynamicImage *assembly)
4443 {
4444         int nsections = 0;
4445
4446         /* alignment constraints */
4447         assembly->code.index += 3;
4448         assembly->code.index &= ~3;
4449         assembly->meta_size += 3;
4450         assembly->meta_size &= ~3;
4451         assembly->resources.index += 3;
4452         assembly->resources.index &= ~3;
4453
4454         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4455         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4456         nsections++;
4457
4458         if (assembly->win32_res) {
4459                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4460
4461                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4462                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4463                 nsections++;
4464         }
4465
4466         assembly->sections [MONO_SECTION_RELOC].size = 12;
4467         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4468         nsections++;
4469
4470         return nsections;
4471 }
4472
4473 typedef struct {
4474         guint32 id;
4475         guint32 offset;
4476         GSList *children;
4477         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4478 } ResTreeNode;
4479
4480 static int
4481 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4482 {
4483         ResTreeNode *t1 = (ResTreeNode*)a;
4484         ResTreeNode *t2 = (ResTreeNode*)b;
4485
4486         return t1->id - t2->id;
4487 }
4488
4489 /*
4490  * resource_tree_create:
4491  *
4492  *  Organize the resources into a resource tree.
4493  */
4494 static ResTreeNode *
4495 resource_tree_create (MonoArray *win32_resources)
4496 {
4497         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4498         GSList *l;
4499         int i;
4500
4501         tree = g_new0 (ResTreeNode, 1);
4502         
4503         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4504                 MonoReflectionWin32Resource *win32_res =
4505                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4506
4507                 /* Create node */
4508
4509                 /* FIXME: BUG: this stores managed references in unmanaged memory */
4510                 lang_node = g_new0 (ResTreeNode, 1);
4511                 lang_node->id = win32_res->lang_id;
4512                 lang_node->win32_res = win32_res;
4513
4514                 /* Create type node if neccesary */
4515                 type_node = NULL;
4516                 for (l = tree->children; l; l = l->next)
4517                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4518                                 type_node = (ResTreeNode*)l->data;
4519                                 break;
4520                         }
4521
4522                 if (!type_node) {
4523                         type_node = g_new0 (ResTreeNode, 1);
4524                         type_node->id = win32_res->res_type;
4525
4526                         /* 
4527                          * The resource types have to be sorted otherwise
4528                          * Windows Explorer can't display the version information.
4529                          */
4530                         tree->children = g_slist_insert_sorted (tree->children, 
4531                                 type_node, resource_tree_compare_by_id);
4532                 }
4533
4534                 /* Create res node if neccesary */
4535                 res_node = NULL;
4536                 for (l = type_node->children; l; l = l->next)
4537                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4538                                 res_node = (ResTreeNode*)l->data;
4539                                 break;
4540                         }
4541
4542                 if (!res_node) {
4543                         res_node = g_new0 (ResTreeNode, 1);
4544                         res_node->id = win32_res->res_id;
4545                         type_node->children = g_slist_append (type_node->children, res_node);
4546                 }
4547
4548                 res_node->children = g_slist_append (res_node->children, lang_node);
4549         }
4550
4551         return tree;
4552 }
4553
4554 /*
4555  * resource_tree_encode:
4556  * 
4557  *   Encode the resource tree into the format used in the PE file.
4558  */
4559 static void
4560 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4561 {
4562         char *entries;
4563         MonoPEResourceDir dir;
4564         MonoPEResourceDirEntry dir_entry;
4565         MonoPEResourceDataEntry data_entry;
4566         GSList *l;
4567
4568         /*
4569          * For the format of the resource directory, see the article
4570          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4571          * Matt Pietrek
4572          */
4573
4574         memset (&dir, 0, sizeof (dir));
4575         memset (&dir_entry, 0, sizeof (dir_entry));
4576         memset (&data_entry, 0, sizeof (data_entry));
4577
4578         g_assert (sizeof (dir) == 16);
4579         g_assert (sizeof (dir_entry) == 8);
4580         g_assert (sizeof (data_entry) == 16);
4581
4582         node->offset = p - begin;
4583
4584         /* IMAGE_RESOURCE_DIRECTORY */
4585         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4586
4587         memcpy (p, &dir, sizeof (dir));
4588         p += sizeof (dir);
4589
4590         /* Reserve space for entries */
4591         entries = p;
4592         p += sizeof (dir_entry) * dir.res_id_entries;
4593
4594         /* Write children */
4595         for (l = node->children; l; l = l->next) {
4596                 ResTreeNode *child = (ResTreeNode*)l->data;
4597
4598                 if (child->win32_res) {
4599
4600                         child->offset = p - begin;
4601
4602                         /* IMAGE_RESOURCE_DATA_ENTRY */
4603                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4604                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4605
4606                         memcpy (p, &data_entry, sizeof (data_entry));
4607                         p += sizeof (data_entry);
4608
4609                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4610                         p += data_entry.rde_size;
4611                 } else {
4612                         resource_tree_encode (child, begin, p, &p);
4613                 }
4614         }
4615
4616         /* IMAGE_RESOURCE_ENTRY */
4617         for (l = node->children; l; l = l->next) {
4618                 ResTreeNode *child = (ResTreeNode*)l->data;
4619                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4620
4621                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4622                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4623
4624                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4625                 entries += sizeof (dir_entry);
4626         }
4627
4628         *endbuf = p;
4629 }
4630
4631 static void
4632 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4633 {
4634         char *buf;
4635         char *p;
4636         guint32 size, i;
4637         MonoReflectionWin32Resource *win32_res;
4638         ResTreeNode *tree;
4639
4640         if (!assemblyb->win32_resources)
4641                 return;
4642
4643         /*
4644          * Resources are stored in a three level tree inside the PE file.
4645          * - level one contains a node for each type of resource
4646          * - level two contains a node for each resource
4647          * - level three contains a node for each instance of a resource for a
4648          *   specific language.
4649          */
4650
4651         tree = resource_tree_create (assemblyb->win32_resources);
4652
4653         /* Estimate the size of the encoded tree */
4654         size = 0;
4655         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4656                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4657                 size += mono_array_length (win32_res->res_data);
4658         }
4659         /* Directory structure */
4660         size += mono_array_length (assemblyb->win32_resources) * 256;
4661         p = buf = g_malloc (size);
4662
4663         resource_tree_encode (tree, p, p, &p);
4664
4665         g_assert (p - buf < size);
4666
4667         assembly->win32_res = g_malloc (p - buf);
4668         assembly->win32_res_size = p - buf;
4669         memcpy (assembly->win32_res, buf, p - buf);
4670
4671         g_free (buf);
4672 }
4673
4674 static void
4675 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4676 {
4677         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4678         int i;
4679
4680         p += sizeof (MonoPEResourceDir);
4681         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4682                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4683                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4684                 if (dir_entry->is_dir) {
4685                         fixup_resource_directory (res_section, child, rva);
4686                 } else {
4687                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4688                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4689                 }
4690
4691                 p += sizeof (MonoPEResourceDirEntry);
4692         }
4693 }
4694
4695 static void
4696 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4697 {
4698         guint32 dummy;
4699         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4700                 g_error ("WriteFile returned %d\n", GetLastError ());
4701 }
4702
4703 /*
4704  * mono_image_create_pefile:
4705  * @mb: a module builder object
4706  * 
4707  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4708  * assembly->pefile where it can be easily retrieved later in chunks.
4709  */
4710 void
4711 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4712         MonoMSDOSHeader *msdos;
4713         MonoDotNetHeader *header;
4714         MonoSectionTable *section;
4715         MonoCLIHeader *cli_header;
4716         guint32 size, image_size, virtual_base, text_offset;
4717         guint32 header_start, section_start, file_offset, virtual_offset;
4718         MonoDynamicImage *assembly;
4719         MonoReflectionAssemblyBuilder *assemblyb;
4720         MonoDynamicStream pefile_stream = {0};
4721         MonoDynamicStream *pefile = &pefile_stream;
4722         int i, nsections;
4723         guint32 *rva, value;
4724         guchar *p;
4725         static const unsigned char msheader[] = {
4726                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4727                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4728                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4729                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4730                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4731                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4732                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4733                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4734         };
4735
4736         assemblyb = mb->assemblyb;
4737
4738         mono_image_basic_init (assemblyb);
4739         assembly = mb->dynamic_image;
4740
4741         assembly->pe_kind = assemblyb->pe_kind;
4742         assembly->machine = assemblyb->machine;
4743         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4744         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4745         
4746         mono_image_build_metadata (mb);
4747
4748         if (mb->is_main && assemblyb->resources) {
4749                 int len = mono_array_length (assemblyb->resources);
4750                 for (i = 0; i < len; ++i)
4751                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4752         }
4753
4754         if (mb->resources) {
4755                 int len = mono_array_length (mb->resources);
4756                 for (i = 0; i < len; ++i)
4757                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4758         }
4759
4760         build_compressed_metadata (assembly);
4761
4762         if (mb->is_main)
4763                 assembly_add_win32_resources (assembly, assemblyb);
4764
4765         nsections = calc_section_size (assembly);
4766         
4767         /* The DOS header and stub */
4768         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4769         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4770
4771         /* the dotnet header */
4772         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4773
4774         /* the section tables */
4775         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4776
4777         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4778         virtual_offset = VIRT_ALIGN;
4779         image_size = 0;
4780
4781         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4782                 if (!assembly->sections [i].size)
4783                         continue;
4784                 /* align offsets */
4785                 file_offset += FILE_ALIGN - 1;
4786                 file_offset &= ~(FILE_ALIGN - 1);
4787                 virtual_offset += VIRT_ALIGN - 1;
4788                 virtual_offset &= ~(VIRT_ALIGN - 1);
4789
4790                 assembly->sections [i].offset = file_offset;
4791                 assembly->sections [i].rva = virtual_offset;
4792
4793                 file_offset += assembly->sections [i].size;
4794                 virtual_offset += assembly->sections [i].size;
4795                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4796         }
4797
4798         file_offset += FILE_ALIGN - 1;
4799         file_offset &= ~(FILE_ALIGN - 1);
4800
4801         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4802
4803         /* back-patch info */
4804         msdos = (MonoMSDOSHeader*)pefile->data;
4805         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4806
4807         header = (MonoDotNetHeader*)(pefile->data + header_start);
4808         header->pesig [0] = 'P';
4809         header->pesig [1] = 'E';
4810         
4811         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4812         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4813         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4814         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4815         if (assemblyb->pekind == 1) {
4816                 /* it's a dll */
4817                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4818         } else {
4819                 /* it's an exe */
4820                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4821         }
4822
4823         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4824
4825         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4826         header->pe.pe_major = 6;
4827         header->pe.pe_minor = 0;
4828         size = assembly->sections [MONO_SECTION_TEXT].size;
4829         size += FILE_ALIGN - 1;
4830         size &= ~(FILE_ALIGN - 1);
4831         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4832         size = assembly->sections [MONO_SECTION_RSRC].size;
4833         size += FILE_ALIGN - 1;
4834         size &= ~(FILE_ALIGN - 1);
4835         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4836         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4837         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4838         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4839         /* pe_rva_entry_point always at the beginning of the text section */
4840         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4841
4842         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4843         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4844         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4845         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4846         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4847         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4848         size = section_start;
4849         size += FILE_ALIGN - 1;
4850         size &= ~(FILE_ALIGN - 1);
4851         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4852         size = image_size;
4853         size += VIRT_ALIGN - 1;
4854         size &= ~(VIRT_ALIGN - 1);
4855         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4856
4857         /*
4858         // Translate the PEFileKind value to the value expected by the Windows loader
4859         */
4860         {
4861                 short kind;
4862
4863                 /*
4864                 // PEFileKinds.Dll == 1
4865                 // PEFileKinds.ConsoleApplication == 2
4866                 // PEFileKinds.WindowApplication == 3
4867                 //
4868                 // need to get:
4869                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4870                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4871                 */
4872                 if (assemblyb->pekind == 3)
4873                         kind = 2;
4874                 else
4875                         kind = 3;
4876                 
4877                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4878         }    
4879         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4880         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4881         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4882         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4883         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4884         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4885
4886         /* fill data directory entries */
4887
4888         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4889         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4890
4891         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4892         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4893
4894         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4895         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4896         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4897         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4898         /* patch entrypoint name */
4899         if (assemblyb->pekind == 1)
4900                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4901         else
4902                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4903         /* patch imported function RVA name */
4904         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4905         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4906
4907         /* the import table */
4908         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4909         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4910         /* patch imported dll RVA name and other entries in the dir */
4911         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4912         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4913         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4914         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4915         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4916         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4917
4918         p = (assembly->code.data + assembly->ilt_offset);
4919         value = (assembly->text_rva + assembly->imp_names_offset);
4920         *p++ = (value) & 0xff;
4921         *p++ = (value >> 8) & (0xff);
4922         *p++ = (value >> 16) & (0xff);
4923         *p++ = (value >> 24) & (0xff);
4924
4925         /* the CLI header info */
4926         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4927         cli_header->ch_size = GUINT32_FROM_LE (72);
4928         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4929         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4930         if (assemblyb->entry_point) {
4931                 guint32 table_idx = 0;
4932                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4933                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4934                         table_idx = methodb->table_idx;
4935                 } else {
4936                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4937                 }
4938                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4939         } else {
4940                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4941         }
4942         /* The embedded managed resources */
4943         text_offset = assembly->text_rva + assembly->code.index;
4944         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4945         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4946         text_offset += assembly->resources.index;
4947         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4948         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4949         text_offset += assembly->meta_size;
4950         if (assembly->strong_name_size) {
4951                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4952                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4953                 text_offset += assembly->strong_name_size;
4954         }
4955
4956         /* write the section tables and section content */
4957         section = (MonoSectionTable*)(pefile->data + section_start);
4958         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4959                 static const char section_names [][7] = {
4960                         ".text", ".rsrc", ".reloc"
4961                 };
4962                 if (!assembly->sections [i].size)
4963                         continue;
4964                 strcpy (section->st_name, section_names [i]);
4965                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4966                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4967                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4968                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4969                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4970                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4971                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4972                 section ++;
4973         }
4974         
4975         checked_write_file (file, pefile->data, pefile->index);
4976         
4977         mono_dynamic_stream_reset (pefile);
4978         
4979         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4980                 if (!assembly->sections [i].size)
4981                         continue;
4982                 
4983                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4984                         g_error ("SetFilePointer returned %d\n", GetLastError ());
4985                 
4986                 switch (i) {
4987                 case MONO_SECTION_TEXT:
4988                         /* patch entry point */
4989                         p = (assembly->code.data + 2);
4990                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4991                         *p++ = (value) & 0xff;
4992                         *p++ = (value >> 8) & 0xff;
4993                         *p++ = (value >> 16) & 0xff;
4994                         *p++ = (value >> 24) & 0xff;
4995                 
4996                         checked_write_file (file, assembly->code.data, assembly->code.index);
4997                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
4998                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4999                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5000                                 
5001
5002                         g_free (assembly->image.raw_metadata);
5003                         break;
5004                 case MONO_SECTION_RELOC: {
5005                         struct {
5006                                 guint32 page_rva;
5007                                 guint32 block_size;
5008                                 guint16 type_and_offset;
5009                                 guint16 term;
5010                         } reloc;
5011                         
5012                         g_assert (sizeof (reloc) == 12);
5013                         
5014                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5015                         reloc.block_size = GUINT32_FROM_LE (12);
5016                         
5017                         /* 
5018                          * the entrypoint is always at the start of the text section 
5019                          * 3 is IMAGE_REL_BASED_HIGHLOW
5020                          * 2 is patch_size_rva - text_rva
5021                          */
5022                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5023                         reloc.term = 0;
5024                         
5025                         checked_write_file (file, &reloc, sizeof (reloc));
5026                         
5027                         break;
5028                 }
5029                 case MONO_SECTION_RSRC:
5030                         if (assembly->win32_res) {
5031
5032                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5033                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5034                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5035                         }
5036                         break;
5037                 default:
5038                         g_assert_not_reached ();
5039                 }
5040         }
5041         
5042         /* check that the file is properly padded */
5043         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5044                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5045         if (! SetEndOfFile (file))
5046                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5047         
5048         mono_dynamic_stream_reset (&assembly->code);
5049         mono_dynamic_stream_reset (&assembly->us);
5050         mono_dynamic_stream_reset (&assembly->blob);
5051         mono_dynamic_stream_reset (&assembly->guid);
5052         mono_dynamic_stream_reset (&assembly->sheap);
5053
5054         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5055         g_hash_table_destroy (assembly->blob_cache);
5056         assembly->blob_cache = NULL;
5057 }
5058
5059 MonoReflectionModule *
5060 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5061 {
5062         char *name;
5063         MonoImage *image;
5064         MonoImageOpenStatus status;
5065         MonoDynamicAssembly *assembly;
5066         guint32 module_count;
5067         MonoImage **new_modules;
5068         
5069         name = mono_string_to_utf8 (fileName);
5070
5071         image = mono_image_open (name, &status);
5072         if (!image) {
5073                 MonoException *exc;
5074                 if (status == MONO_IMAGE_ERROR_ERRNO)
5075                         exc = mono_get_exception_file_not_found (fileName);
5076                 else
5077                         exc = mono_get_exception_bad_image_format (name);
5078                 g_free (name);
5079                 mono_raise_exception (exc);
5080         }
5081
5082         g_free (name);
5083
5084         assembly = ab->dynamic_assembly;
5085         image->assembly = (MonoAssembly*)assembly;
5086
5087         module_count = image->assembly->image->module_count;
5088         new_modules = g_new0 (MonoImage *, module_count + 1);
5089
5090         if (image->assembly->image->modules)
5091                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5092         new_modules [module_count] = image;
5093         mono_image_addref (image);
5094
5095         g_free (image->assembly->image->modules);
5096         image->assembly->image->modules = new_modules;
5097         image->assembly->image->module_count ++;
5098
5099         mono_assembly_load_references (image, &status);
5100         if (status) {
5101                 mono_image_close (image);
5102                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5103         }
5104
5105         return mono_module_get_object (mono_domain_get (), image);
5106 }
5107
5108 /*
5109  * We need to return always the same object for MethodInfo, FieldInfo etc..
5110  * but we need to consider the reflected type.
5111  * type uses a different hash, since it uses custom hash/equal functions.
5112  */
5113
5114 typedef struct {
5115         gpointer item;
5116         MonoClass *refclass;
5117 } ReflectedEntry;
5118
5119 static gboolean
5120 reflected_equal (gconstpointer a, gconstpointer b) {
5121         const ReflectedEntry *ea = a;
5122         const ReflectedEntry *eb = b;
5123
5124         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5125 }
5126
5127 static guint
5128 reflected_hash (gconstpointer a) {
5129         const ReflectedEntry *ea = a;
5130         return mono_aligned_addr_hash (ea->item);
5131 }
5132
5133 #define CHECK_OBJECT(t,p,k)     \
5134         do {    \
5135                 t _obj; \
5136                 ReflectedEntry e;       \
5137                 e.item = (p);   \
5138                 e.refclass = (k);       \
5139                 mono_domain_lock (domain);      \
5140                 if (!domain->refobject_hash)    \
5141                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5142                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5143                         mono_domain_unlock (domain);    \
5144                         return _obj;    \
5145                 }       \
5146         mono_domain_unlock (domain); \
5147         } while (0)
5148
5149 #if HAVE_BOEHM_GC
5150 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5151 #elif HAVE_SGEN_GC
5152 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5153 #else
5154 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5155 #endif
5156
5157 #define CACHE_OBJECT(t,p,o,k)   \
5158         do {    \
5159                 t _obj; \
5160         ReflectedEntry pe; \
5161         pe.item = (p); \
5162         pe.refclass = (k); \
5163         mono_domain_lock (domain); \
5164                 if (!domain->refobject_hash)    \
5165                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5166         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5167         if (!_obj) { \
5168                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5169                     e->item = (p);      \
5170                     e->refclass = (k);  \
5171                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5172             _obj = o; \
5173         } \
5174                 mono_domain_unlock (domain);    \
5175         return _obj; \
5176         } while (0)
5177
5178 static gpointer
5179 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5180 {
5181         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5182 }
5183
5184 static gpointer
5185 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5186 {
5187         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5188 }
5189
5190 void
5191 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5192 {
5193         MonoDynamicImage *image = moduleb->dynamic_image;
5194         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5195         if (!image) {
5196                 int module_count;
5197                 MonoImage **new_modules;
5198                 MonoImage *ass;
5199                 /*
5200                  * FIXME: we already created an image in mono_image_basic_init (), but
5201                  * we don't know which module it belongs to, since that is only 
5202                  * determined at assembly save time.
5203                  */
5204                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5205                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5206
5207                 moduleb->module.image = &image->image;
5208                 moduleb->dynamic_image = image;
5209                 register_module (mono_object_domain (moduleb), moduleb, image);
5210
5211                 /* register the module with the assembly */
5212                 ass = ab->dynamic_assembly->assembly.image;
5213                 module_count = ass->module_count;
5214                 new_modules = g_new0 (MonoImage *, module_count + 1);
5215
5216                 if (ass->modules)
5217                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5218                 new_modules [module_count] = &image->image;
5219                 mono_image_addref (&image->image);
5220
5221                 g_free (ass->modules);
5222                 ass->modules = new_modules;
5223                 ass->module_count ++;
5224         }
5225 }
5226
5227 /*
5228  * mono_assembly_get_object:
5229  * @domain: an app domain
5230  * @assembly: an assembly
5231  *
5232  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5233  */
5234 MonoReflectionAssembly*
5235 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5236 {
5237         static MonoClass *System_Reflection_Assembly;
5238         MonoReflectionAssembly *res;
5239         
5240         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5241         if (!System_Reflection_Assembly)
5242                 System_Reflection_Assembly = mono_class_from_name (
5243                         mono_defaults.corlib, "System.Reflection", "Assembly");
5244         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5245         res->assembly = assembly;
5246
5247         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5248 }
5249
5250
5251
5252 MonoReflectionModule*   
5253 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5254 {
5255         static MonoClass *System_Reflection_Module;
5256         MonoReflectionModule *res;
5257         char* basename;
5258         
5259         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5260         if (!System_Reflection_Module)
5261                 System_Reflection_Module = mono_class_from_name (
5262                         mono_defaults.corlib, "System.Reflection", "Module");
5263         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5264
5265         res->image = image;
5266         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5267
5268         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5269         basename = g_path_get_basename (image->name);
5270         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5271         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5272         
5273         g_free (basename);
5274
5275         if (image->assembly->image == image) {
5276                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5277         } else {
5278                 int i;
5279                 res->token = 0;
5280                 if (image->assembly->image->modules) {
5281                         for (i = 0; i < image->assembly->image->module_count; i++) {
5282                                 if (image->assembly->image->modules [i] == image)
5283                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5284                         }
5285                         g_assert (res->token);
5286                 }
5287         }
5288
5289         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5290 }
5291
5292 MonoReflectionModule*   
5293 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5294 {
5295         static MonoClass *System_Reflection_Module;
5296         MonoReflectionModule *res;
5297         MonoTableInfo *table;
5298         guint32 cols [MONO_FILE_SIZE];
5299         const char *name;
5300         guint32 i, name_idx;
5301         const char *val;
5302         
5303         if (!System_Reflection_Module)
5304                 System_Reflection_Module = mono_class_from_name (
5305                         mono_defaults.corlib, "System.Reflection", "Module");
5306         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5307
5308         table = &image->tables [MONO_TABLE_FILE];
5309         g_assert (table_index < table->rows);
5310         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5311
5312         res->image = NULL;
5313         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5314         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5315
5316         /* Check whenever the row has a corresponding row in the moduleref table */
5317         table = &image->tables [MONO_TABLE_MODULEREF];
5318         for (i = 0; i < table->rows; ++i) {
5319                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5320                 val = mono_metadata_string_heap (image, name_idx);
5321                 if (strcmp (val, name) == 0)
5322                         res->image = image->modules [i];
5323         }
5324
5325         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5326         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5327         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5328         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5329         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5330
5331         return res;
5332 }
5333
5334 static gboolean
5335 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5336 {
5337         if ((t1->type != t2->type) ||
5338             (t1->byref != t2->byref))
5339                 return FALSE;
5340
5341         switch (t1->type) {
5342         case MONO_TYPE_VOID:
5343         case MONO_TYPE_BOOLEAN:
5344         case MONO_TYPE_CHAR:
5345         case MONO_TYPE_I1:
5346         case MONO_TYPE_U1:
5347         case MONO_TYPE_I2:
5348         case MONO_TYPE_U2:
5349         case MONO_TYPE_I4:
5350         case MONO_TYPE_U4:
5351         case MONO_TYPE_I8:
5352         case MONO_TYPE_U8:
5353         case MONO_TYPE_R4:
5354         case MONO_TYPE_R8:
5355         case MONO_TYPE_STRING:
5356         case MONO_TYPE_I:
5357         case MONO_TYPE_U:
5358         case MONO_TYPE_OBJECT:
5359         case MONO_TYPE_TYPEDBYREF:
5360                 return TRUE;
5361         case MONO_TYPE_VALUETYPE:
5362         case MONO_TYPE_CLASS:
5363         case MONO_TYPE_SZARRAY:
5364                 return t1->data.klass == t2->data.klass;
5365         case MONO_TYPE_PTR:
5366                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5367         case MONO_TYPE_ARRAY:
5368                 if (t1->data.array->rank != t2->data.array->rank)
5369                         return FALSE;
5370                 return t1->data.array->eklass == t2->data.array->eklass;
5371         case MONO_TYPE_GENERICINST: {
5372                 int i;
5373                 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5374                         return FALSE;
5375                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5376                                                &t2->data.generic_class->container_class->byval_arg))
5377                         return FALSE;
5378                 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5379                         if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5380                                 return FALSE;
5381                 }
5382                 return TRUE;
5383         }
5384         case MONO_TYPE_VAR:
5385         case MONO_TYPE_MVAR:
5386                 return t1->data.generic_param == t2->data.generic_param;
5387         default:
5388                 g_error ("implement type compare for %0x!", t1->type);
5389                 return FALSE;
5390         }
5391
5392         return FALSE;
5393 }
5394
5395 static guint
5396 mymono_metadata_type_hash (MonoType *t1)
5397 {
5398         guint hash;
5399
5400         hash = t1->type;
5401
5402         hash |= t1->byref << 6; /* do not collide with t1->type values */
5403         switch (t1->type) {
5404         case MONO_TYPE_VALUETYPE:
5405         case MONO_TYPE_CLASS:
5406         case MONO_TYPE_SZARRAY:
5407                 /* check if the distribution is good enough */
5408                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5409         case MONO_TYPE_PTR:
5410                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5411         case MONO_TYPE_GENERICINST: {
5412                 int i;
5413                 MonoGenericInst *inst = t1->data.generic_class->inst;
5414                 hash += g_str_hash (t1->data.generic_class->container_class->name);
5415                 hash *= 13;
5416                 for (i = 0; i < inst->type_argc; ++i) {
5417                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
5418                         hash *= 13;
5419                 }
5420                 return hash;
5421         }
5422         }
5423         return hash;
5424 }
5425
5426 static MonoReflectionGenericClass*
5427 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5428 {
5429         static MonoClass *System_Reflection_MonoGenericClass;
5430         MonoReflectionGenericClass *res;
5431         MonoInflatedGenericClass *gclass;
5432         MonoClass *gklass;
5433
5434         if (!System_Reflection_MonoGenericClass) {
5435                 System_Reflection_MonoGenericClass = mono_class_from_name (
5436                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5437                 g_assert (System_Reflection_MonoGenericClass);
5438         }
5439
5440         gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5441         gklass = gclass->generic_class.container_class;
5442         g_assert (gklass->generic_container);
5443
5444         mono_class_init (gclass->klass);
5445
5446 #ifdef HAVE_SGEN_GC
5447         /* FIXME: allow unpinned later */
5448         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5449 #else
5450         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5451 #endif
5452
5453         res->type.type = geninst;
5454         if (gklass->wastypebuilder && gklass->reflection_info)
5455                 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5456         else
5457                 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5458
5459         return res;
5460 }
5461
5462 static gboolean
5463 verify_safe_for_managed_space (MonoType *type)
5464 {
5465         switch (type->type) {
5466 #ifdef DEBUG_HARDER
5467         case MONO_TYPE_ARRAY:
5468                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5469         case MONO_TYPE_PTR:
5470                 return verify_safe_for_managed_space (type->data.type);
5471         case MONO_TYPE_SZARRAY:
5472                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5473         case MONO_TYPE_GENERICINST: {
5474                 MonoGenericInst *inst = type->data.generic_class->inst;
5475                 int i;
5476                 if (!inst->is_open)
5477                         break;
5478                 for (i = 0; i < inst->type_argc; ++i)
5479                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
5480                                 return FALSE;
5481                 break;
5482         }
5483 #endif
5484         case MONO_TYPE_VAR:
5485         case MONO_TYPE_MVAR:
5486                 return TRUE;
5487         }
5488         return TRUE;
5489 }
5490
5491 /*
5492  * mono_type_get_object:
5493  * @domain: an app domain
5494  * @type: a type
5495  *
5496  * Return an System.MonoType object representing the type @type.
5497  */
5498 MonoReflectionType*
5499 mono_type_get_object (MonoDomain *domain, MonoType *type)
5500 {
5501         MonoReflectionType *res;
5502         MonoClass *klass = mono_class_from_mono_type (type);
5503
5504         mono_domain_lock (domain);
5505         if (!domain->type_hash)
5506                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
5507                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5508         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5509                 mono_domain_unlock (domain);
5510                 return res;
5511         }
5512         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5513                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5514                 mono_g_hash_table_insert (domain->type_hash, type, res);
5515                 mono_domain_unlock (domain);
5516                 return res;
5517         }
5518
5519         if (!verify_safe_for_managed_space (type)) {
5520                 mono_domain_unlock (domain);
5521                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5522         }
5523
5524         if (klass->reflection_info && !klass->wastypebuilder) {
5525                 /* g_assert_not_reached (); */
5526                 /* should this be considered an error condition? */
5527                 if (!type->byref) {
5528                         mono_domain_unlock (domain);
5529                         return klass->reflection_info;
5530                 }
5531         }
5532         mono_class_init (klass);
5533 #ifdef HAVE_SGEN_GC
5534         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5535 #else
5536         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5537 #endif
5538         res->type = type;
5539         mono_g_hash_table_insert (domain->type_hash, type, res);
5540         mono_domain_unlock (domain);
5541         return res;
5542 }
5543
5544 /*
5545  * mono_method_get_object:
5546  * @domain: an app domain
5547  * @method: a method
5548  * @refclass: the reflected type (can be NULL)
5549  *
5550  * Return an System.Reflection.MonoMethod object representing the method @method.
5551  */
5552 MonoReflectionMethod*
5553 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5554 {
5555         /*
5556          * We use the same C representation for methods and constructors, but the type 
5557          * name in C# is different.
5558          */
5559         static MonoClass *System_Reflection_MonoMethod = NULL;
5560         static MonoClass *System_Reflection_MonoCMethod = NULL;
5561         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5562         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5563         const char *cname;
5564         MonoClass *klass;
5565         MonoReflectionMethod *ret;
5566
5567         if (method->is_inflated) {
5568                 MonoReflectionGenericMethod *gret;
5569
5570                 method = mono_get_inflated_method (method);
5571                 refclass = method->klass;
5572                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5573                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5574                         if (!System_Reflection_MonoGenericCMethod)
5575                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5576                         klass = System_Reflection_MonoGenericCMethod;
5577                 } else {
5578                         if (!System_Reflection_MonoGenericMethod)
5579                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5580                         klass = System_Reflection_MonoGenericMethod;
5581                 }
5582                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5583                 gret->method.method = method;
5584                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5585                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5586                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5587         }
5588
5589         if (!refclass)
5590                 refclass = method->klass;
5591
5592         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5593         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5594                 if (!System_Reflection_MonoCMethod)
5595                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5596                 klass = System_Reflection_MonoCMethod;
5597         }
5598         else {
5599                 if (!System_Reflection_MonoMethod)
5600                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5601                 klass = System_Reflection_MonoMethod;
5602         }
5603         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5604         ret->method = method;
5605         MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5606         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5607         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5608 }
5609
5610 /*
5611  * mono_field_get_object:
5612  * @domain: an app domain
5613  * @klass: a type
5614  * @field: a field
5615  *
5616  * Return an System.Reflection.MonoField object representing the field @field
5617  * in class @klass.
5618  */
5619 MonoReflectionField*
5620 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5621 {
5622         MonoReflectionField *res;
5623         MonoClass *oklass;
5624
5625         CHECK_OBJECT (MonoReflectionField *, field, klass);
5626         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5627         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5628         res->klass = klass;
5629         res->field = field;
5630         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5631         if (field->generic_info)
5632                 res->attrs = field->generic_info->generic_type->attrs;
5633         else
5634                 res->attrs = field->type->attrs;
5635         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5636         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5637 }
5638
5639 /*
5640  * mono_property_get_object:
5641  * @domain: an app domain
5642  * @klass: a type
5643  * @property: a property
5644  *
5645  * Return an System.Reflection.MonoProperty object representing the property @property
5646  * in class @klass.
5647  */
5648 MonoReflectionProperty*
5649 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5650 {
5651         MonoReflectionProperty *res;
5652         MonoClass *oklass;
5653
5654         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5655         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5656         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5657         res->klass = klass;
5658         res->property = property;
5659         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5660 }
5661
5662 /*
5663  * mono_event_get_object:
5664  * @domain: an app domain
5665  * @klass: a type
5666  * @event: a event
5667  *
5668  * Return an System.Reflection.MonoEvent object representing the event @event
5669  * in class @klass.
5670  */
5671 MonoReflectionEvent*
5672 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5673 {
5674         MonoReflectionEvent *res;
5675         MonoClass *oklass;
5676
5677         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5678         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5679         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5680         res->klass = klass;
5681         res->event = event;
5682         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5683 }
5684
5685 /*
5686  * mono_param_get_objects:
5687  * @domain: an app domain
5688  * @method: a method
5689  *
5690  * Return an System.Reflection.ParameterInfo array object representing the parameters
5691  * in the method @method.
5692  */
5693 MonoArray*
5694 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5695 {
5696         static MonoClass *System_Reflection_ParameterInfo;
5697         MonoArray *res = NULL;
5698         MonoReflectionMethod *member = NULL;
5699         MonoReflectionParameter *param = NULL;
5700         char **names, **blobs = NULL;
5701         guint32 *types = NULL;
5702         MonoType *type = NULL;
5703         MonoObject *dbnull = mono_get_dbnull_object (domain);
5704         MonoMarshalSpec **mspecs;
5705         MonoMethodSignature *sig;
5706         int i;
5707
5708         if (!System_Reflection_ParameterInfo)
5709                 System_Reflection_ParameterInfo = mono_class_from_name (
5710                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5711         
5712         if (!mono_method_signature (method)->param_count)
5713                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5714
5715         /* Note: the cache is based on the address of the signature into the method
5716          * since we already cache MethodInfos with the method as keys.
5717          */
5718         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5719
5720         sig = mono_method_signature (method);
5721         member = mono_method_get_object (domain, method, NULL);
5722         names = g_new (char *, sig->param_count);
5723         mono_method_get_param_names (method, (const char **) names);
5724
5725         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5726         mono_method_get_marshal_info (method, mspecs);
5727
5728         res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5729         for (i = 0; i < sig->param_count; ++i) {
5730                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5731                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5732                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5733                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5734                 param->PositionImpl = i;
5735                 param->AttrsImpl = sig->params [i]->attrs;
5736
5737                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5738                         MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5739                 } else {
5740
5741                         if (!blobs) {
5742                                 blobs = g_new0 (char *, sig->param_count);
5743                                 types = g_new0 (guint32, sig->param_count);
5744                                 get_default_param_value_blobs (method, blobs, types); 
5745                         }
5746
5747                         /* Build MonoType for the type from the Constant Table */
5748                         if (!type)
5749                                 type = g_new0 (MonoType, 1);
5750                         type->type = types [i];
5751                         type->data.klass = NULL;
5752                         if (types [i] == MONO_TYPE_CLASS)
5753                                 type->data.klass = mono_defaults.object_class;
5754                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5755                                 /* For enums, types [i] contains the base type */
5756
5757                                         type->type = MONO_TYPE_VALUETYPE;
5758                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
5759                         } else
5760                                 type->data.klass = mono_class_from_mono_type (type);
5761
5762                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5763
5764                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5765                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) 
5766                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5767                         
5768                 }
5769
5770                 if (mspecs [i + 1])
5771                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5772                 
5773                 mono_array_setref (res, i, param);
5774         }
5775         g_free (names);
5776         g_free (blobs);
5777         g_free (types);
5778         g_free (type);
5779
5780         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5781                 if (mspecs [i])
5782                         mono_metadata_free_marshal_spec (mspecs [i]);
5783         g_free (mspecs);
5784         
5785         CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5786 }
5787
5788 /*
5789  * mono_method_body_get_object:
5790  * @domain: an app domain
5791  * @method: a method
5792  *
5793  * Return an System.Reflection.MethodBody object representing the method @method.
5794  */
5795 MonoReflectionMethodBody*
5796 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5797 {
5798         static MonoClass *System_Reflection_MethodBody = NULL;
5799         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5800         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5801         MonoReflectionMethodBody *ret;
5802         MonoMethodNormal *mn;
5803         MonoMethodHeader *header;
5804         guint32 method_rva, local_var_sig_token;
5805     char *ptr;
5806         unsigned char format, flags;
5807         int i;
5808
5809         if (!System_Reflection_MethodBody)
5810                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5811         if (!System_Reflection_LocalVariableInfo)
5812                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5813         if (!System_Reflection_ExceptionHandlingClause)
5814                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5815
5816         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5817
5818         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5819                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5820             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5821             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5822                 return NULL;
5823         mn = (MonoMethodNormal *)method;
5824         header = mono_method_get_header (method);
5825         
5826         /* Obtain local vars signature token */
5827         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5828         ptr = mono_image_rva_map (method->klass->image, method_rva);
5829         flags = *(const unsigned char *) ptr;
5830         format = flags & METHOD_HEADER_FORMAT_MASK;
5831         switch (format){
5832         case METHOD_HEADER_TINY_FORMAT:
5833         case METHOD_HEADER_TINY_FORMAT1:
5834                 local_var_sig_token = 0;
5835                 break;
5836         case METHOD_HEADER_FAT_FORMAT:
5837                 ptr += 2;
5838                 ptr += 2;
5839                 ptr += 4;
5840                 local_var_sig_token = read32 (ptr);
5841                 break;
5842         default:
5843                 g_assert_not_reached ();
5844         }
5845
5846         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5847
5848         ret->init_locals = header->init_locals;
5849         ret->max_stack = header->max_stack;
5850         ret->local_var_sig_token = local_var_sig_token;
5851         MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5852         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5853
5854         /* Locals */
5855         MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5856         for (i = 0; i < header->num_locals; ++i) {
5857                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5858                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5859                 info->is_pinned = header->locals [i]->pinned;
5860                 info->local_index = i;
5861                 mono_array_setref (ret->locals, i, info);
5862         }
5863
5864         /* Exceptions */
5865         MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5866         for (i = 0; i < header->num_clauses; ++i) {
5867                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5868                 MonoExceptionClause *clause = &header->clauses [i];
5869
5870                 info->flags = clause->flags;
5871                 info->try_offset = clause->try_offset;
5872                 info->try_length = clause->try_len;
5873                 info->handler_offset = clause->handler_offset;
5874                 info->handler_length = clause->handler_len;
5875                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5876                         info->filter_offset = clause->data.filter_offset;
5877                 else if (clause->data.catch_class)
5878                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5879
5880                 mono_array_setref (ret->clauses, i, info);
5881         }
5882
5883         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5884         return ret;
5885 }
5886
5887 MonoObject *
5888 mono_get_dbnull_object (MonoDomain *domain)
5889 {
5890         MonoObject *obj;
5891         MonoClass *klass;
5892         static MonoClassField *dbnull_value_field = NULL;
5893         
5894         if (!dbnull_value_field) {
5895                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5896                 mono_class_init (klass);
5897                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5898                 g_assert (dbnull_value_field);
5899         }
5900         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5901         g_assert (obj);
5902         return obj;
5903 }
5904
5905
5906 static void
5907 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5908 {
5909         guint32 param_index, i, lastp, crow = 0;
5910         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5911         gint32 idx;
5912
5913         MonoClass *klass = method->klass;
5914         MonoImage *image = klass->image;
5915         MonoMethodSignature *methodsig = mono_method_signature (method);
5916
5917         MonoTableInfo *constt;
5918         MonoTableInfo *methodt;
5919         MonoTableInfo *paramt;
5920
5921         if (!methodsig->param_count)
5922                 return;
5923
5924         mono_class_init (klass);
5925
5926         if (klass->image->dynamic) {
5927                 MonoReflectionMethodAux *aux;
5928                 if (method->is_inflated)
5929                         method = ((MonoMethodInflated*)method)->declaring;
5930                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5931                 if (aux && aux->param_defaults) {
5932                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5933                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5934                 }
5935                 return;
5936         }
5937
5938         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5939         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5940         constt = &image->tables [MONO_TABLE_CONSTANT];
5941
5942         idx = mono_method_get_index (method) - 1;
5943         g_assert (idx != -1);
5944
5945         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5946         if (idx + 1 < methodt->rows)
5947                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5948         else
5949                 lastp = paramt->rows + 1;
5950
5951         for (i = param_index; i < lastp; ++i) {
5952                 guint32 paramseq;
5953
5954                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5955                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5956
5957                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5958                         continue;
5959
5960                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5961                 if (!crow) {
5962                         continue;
5963                 }
5964         
5965                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5966                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5967                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5968         }
5969
5970         return;
5971 }
5972
5973 static MonoObject *
5974 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5975 {
5976         void *retval;
5977         MonoClass *klass;
5978         MonoObject *object;
5979         MonoType *basetype = type;
5980
5981         if (!blob)
5982                 return NULL;
5983         
5984         klass = mono_class_from_mono_type (type);
5985         if (klass->valuetype) {
5986                 object = mono_object_new (domain, klass);
5987                 retval = ((gchar *) object + sizeof (MonoObject));
5988                 if (klass->enumtype)
5989                         basetype = klass->enum_basetype;
5990         } else {
5991                 retval = &object;
5992         }
5993                         
5994         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
5995                 return object;
5996         else
5997                 return NULL;
5998 }
5999
6000 static int
6001 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6002         int found_sep;
6003         char *s;
6004
6005         memset (assembly, 0, sizeof (MonoAssemblyName));
6006         assembly->name = p;
6007         assembly->culture = "";
6008         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6009
6010         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6011                 p++;
6012         found_sep = 0;
6013         while (g_ascii_isspace (*p) || *p == ',') {
6014                 *p++ = 0;
6015                 found_sep = 1;
6016                 continue;
6017         }
6018         /* failed */
6019         if (!found_sep)
6020                 return 1;
6021         while (*p) {
6022                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6023                         p += 8;
6024                         assembly->major = strtoul (p, &s, 10);
6025                         if (s == p || *s != '.')
6026                                 return 1;
6027                         p = ++s;
6028                         assembly->minor = strtoul (p, &s, 10);
6029                         if (s == p || *s != '.')
6030                                 return 1;
6031                         p = ++s;
6032                         assembly->build = strtoul (p, &s, 10);
6033                         if (s == p || *s != '.')
6034                                 return 1;
6035                         p = ++s;
6036                         assembly->revision = strtoul (p, &s, 10);
6037                         if (s == p)
6038                                 return 1;
6039                         p = s;
6040                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6041                         p += 8;
6042                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6043                                 assembly->culture = "";
6044                                 p += 7;
6045                         } else {
6046                                 assembly->culture = p;
6047                                 while (*p && *p != ',') {
6048                                         p++;
6049                                 }
6050                         }
6051                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6052                         p += 15;
6053                         if (strncmp (p, "null", 4) == 0) {
6054                                 p += 4;
6055                         } else {
6056                                 int len;
6057                                 gchar *start = p;
6058                                 while (*p && *p != ',') {
6059                                         p++;
6060                                 }
6061                                 len = (p - start + 1);
6062                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6063                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6064                                 g_strlcpy (assembly->public_key_token, start, len);
6065                         }
6066                 } else {
6067                         while (*p && *p != ',')
6068                                 p++;
6069                 }
6070                 found_sep = 0;
6071                 while (g_ascii_isspace (*p) || *p == ',') {
6072                         *p++ = 0;
6073                         found_sep = 1;
6074                         continue;
6075                 }
6076                 /* failed */
6077                 if (!found_sep)
6078                         return 1;
6079         }
6080
6081         return 0;
6082 }
6083
6084 /*
6085  * mono_reflection_parse_type:
6086  * @name: type name
6087  *
6088  * Parse a type name as accepted by the GetType () method and output the info
6089  * extracted in the info structure.
6090  * the name param will be mangled, so, make a copy before passing it to this function.
6091  * The fields in info will be valid until the memory pointed to by name is valid.
6092  *
6093  * See also mono_type_get_name () below.
6094  *
6095  * Returns: 0 on parse error.
6096  */
6097 static int
6098 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6099                              MonoTypeNameParse *info)
6100 {
6101         char *start, *p, *w, *temp, *last_point, *startn;
6102         int in_modifiers = 0;
6103         int isbyref = 0, rank, arity = 0, i;
6104
6105         start = p = w = name;
6106
6107         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6108         info->name = info->name_space = NULL;
6109         info->nested = NULL;
6110         info->modifiers = NULL;
6111         info->type_arguments = NULL;
6112
6113         /* last_point separates the namespace from the name */
6114         last_point = NULL;
6115
6116         while (*p) {
6117                 switch (*p) {
6118                 case '+':
6119                         *p = 0; /* NULL terminate the name */
6120                         startn = p + 1;
6121                         info->nested = g_list_append (info->nested, startn);
6122                         /* we have parsed the nesting namespace + name */
6123                         if (info->name)
6124                                 break;
6125                         if (last_point) {
6126                                 info->name_space = start;
6127                                 *last_point = 0;
6128                                 info->name = last_point + 1;
6129                         } else {
6130                                 info->name_space = (char *)"";
6131                                 info->name = start;
6132                         }
6133                         break;
6134                 case '.':
6135                         last_point = p;
6136                         break;
6137                 case '\\':
6138                         ++p;
6139                         break;
6140                 case '&':
6141                 case '*':
6142                 case '[':
6143                 case ',':
6144                 case ']':
6145                         in_modifiers = 1;
6146                         break;
6147                 case '`':
6148                         ++p;
6149                         i = strtol (p, &temp, 10);
6150                         arity += i;
6151                         if (p == temp)
6152                                 return 0;
6153                         p = temp-1;
6154                         break;
6155                 default:
6156                         break;
6157                 }
6158                 if (in_modifiers)
6159                         break;
6160                 // *w++ = *p++;
6161                 p++;
6162         }
6163         
6164         if (!info->name) {
6165                 if (last_point) {
6166                         info->name_space = start;
6167                         *last_point = 0;
6168                         info->name = last_point + 1;
6169                 } else {
6170                         info->name_space = (char *)"";
6171                         info->name = start;
6172                 }
6173         }
6174         while (*p) {
6175                 switch (*p) {
6176                 case '&':
6177                         if (isbyref) /* only one level allowed by the spec */
6178                                 return 0;
6179                         isbyref = 1;
6180                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6181                         *p++ = 0;
6182                         break;
6183                 case '*':
6184                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6185                         *p++ = 0;
6186                         break;
6187                 case '[':
6188                         if (arity != 0) {
6189                                 *p++ = 0;
6190                                 info->type_arguments = g_ptr_array_new ();
6191                                 for (i = 0; i < arity; i++) {
6192                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6193                                         gboolean fqname = FALSE;
6194
6195                                         g_ptr_array_add (info->type_arguments, subinfo);
6196
6197                                         if (*p == '[') {
6198                                                 p++;
6199                                                 fqname = TRUE;
6200                                         }
6201
6202                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6203                                                 return 0;
6204
6205                                         if (fqname) {
6206                                                 char *aname;
6207
6208                                                 if (*p != ',')
6209                                                         return 0;
6210                                                 *p++ = 0;
6211
6212                                                 aname = p;
6213                                                 while (*p && (*p != ']'))
6214                                                         p++;
6215
6216                                                 if (*p != ']')
6217                                                         return 0;
6218
6219                                                 *p++ = 0;
6220                                                 while (*aname) {
6221                                                         if (g_ascii_isspace (*aname)) {
6222                                                                 ++aname;
6223                                                                 continue;
6224                                                         }
6225                                                         break;
6226                                                 }
6227                                                 if (!*aname ||
6228                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
6229                                                         return 0;
6230                                         }
6231
6232                                         if (i + 1 < arity) {
6233                                                 if (*p != ',')
6234                                                         return 0;
6235                                         } else {
6236                                                 if (*p != ']')
6237                                                         return 0;
6238                                         }
6239                                         *p++ = 0;
6240                                 }
6241
6242                                 arity = 0;
6243                                 break;
6244                         }
6245                         rank = 1;
6246                         *p++ = 0;
6247                         while (*p) {
6248                                 if (*p == ']')
6249                                         break;
6250                                 if (*p == ',')
6251                                         rank++;
6252                                 else if (*p != '*') /* '*' means unknown lower bound */
6253                                         return 0;
6254                                 ++p;
6255                         }
6256                         if (*p++ != ']')
6257                                 return 0;
6258                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6259                         break;
6260                 case ']':
6261                         if (is_recursed)
6262                                 goto end;
6263                         return 0;
6264                 case ',':
6265                         if (is_recursed)
6266                                 goto end;
6267                         *p++ = 0;
6268                         while (*p) {
6269                                 if (g_ascii_isspace (*p)) {
6270                                         ++p;
6271                                         continue;
6272                                 }
6273                                 break;
6274                         }
6275                         if (!*p)
6276                                 return 0; /* missing assembly name */
6277                         if (!assembly_name_to_aname (&info->assembly, p))
6278                                 return 0;
6279                         break;
6280                 default:
6281                         return 0;
6282                 }
6283                 if (info->assembly.name)
6284                         break;
6285         }
6286         // *w = 0; /* terminate class name */
6287  end:
6288         if (!info->name || !*info->name)
6289                 return 0;
6290         if (endptr)
6291                 *endptr = p;
6292         /* add other consistency checks */
6293         return 1;
6294 }
6295
6296 int
6297 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6298 {
6299         return _mono_reflection_parse_type (name, NULL, FALSE, info);
6300 }
6301
6302 static MonoType*
6303 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6304 {
6305         gboolean type_resolve = FALSE;
6306         MonoType *type;
6307
6308         if (info->assembly.name) {
6309                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6310                 if (!assembly) {
6311                         /* then we must load the assembly ourselve - see #60439 */
6312                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6313                         if (!assembly)
6314                                 return NULL;
6315                 }
6316                 image = assembly->image;
6317         } else if (!image) {
6318                 image = mono_defaults.corlib;
6319         }
6320
6321         type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6322         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6323                 image = mono_defaults.corlib;
6324                 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6325         }
6326
6327         return type;
6328 }
6329
6330 static MonoType*
6331 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6332 {
6333         MonoClass *klass;
6334         GList *mod;
6335         int modval;
6336         
6337         if (!image)
6338                 image = mono_defaults.corlib;
6339
6340         if (ignorecase)
6341                 klass = mono_class_from_name_case (image, info->name_space, info->name);
6342         else
6343                 klass = mono_class_from_name (image, info->name_space, info->name);
6344         if (!klass)
6345                 return NULL;
6346         for (mod = info->nested; mod; mod = mod->next) {
6347                 GList *nested;
6348
6349                 mono_class_init (klass);
6350                 nested = klass->nested_classes;
6351                 klass = NULL;
6352                 while (nested) {
6353                         klass = nested->data;
6354                         if (ignorecase) {
6355                                 if (g_strcasecmp (klass->name, mod->data) == 0)
6356                                         break;
6357                         } else {
6358                                 if (strcmp (klass->name, mod->data) == 0)
6359                                         break;
6360                         }
6361                         klass = NULL;
6362                         nested = nested->next;
6363                 }
6364                 if (!klass)
6365                         break;
6366         }
6367         if (!klass)
6368                 return NULL;
6369         mono_class_init (klass);
6370
6371         if (info->type_arguments) {
6372                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6373                 MonoReflectionType *the_type;
6374                 MonoType *instance;
6375                 int i;
6376
6377                 for (i = 0; i < info->type_arguments->len; i++) {
6378                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6379
6380                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6381                         if (!type_args [i]) {
6382                                 g_free (type_args);
6383                                 return NULL;
6384                         }
6385                 }
6386
6387                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6388
6389                 instance = mono_reflection_bind_generic_parameters (
6390                         the_type, info->type_arguments->len, type_args);
6391
6392                 if (!instance) {
6393                         g_free (type_args);
6394                         return NULL;
6395                 }
6396
6397                 klass = mono_class_from_mono_type (instance);
6398         }
6399
6400         for (mod = info->modifiers; mod; mod = mod->next) {
6401                 modval = GPOINTER_TO_UINT (mod->data);
6402                 if (!modval) { /* byref: must be last modifier */
6403                         return &klass->this_arg;
6404                 } else if (modval == -1) {
6405                         klass = mono_ptr_class_get (&klass->byval_arg);
6406                 } else { /* array rank */
6407                         klass = mono_array_class_get (klass, modval);
6408                 }
6409                 mono_class_init (klass);
6410         }
6411
6412         return &klass->byval_arg;
6413 }
6414
6415 /*
6416  * mono_reflection_get_type:
6417  * @image: a metadata context
6418  * @info: type description structure
6419  * @ignorecase: flag for case-insensitive string compares
6420  * @type_resolve: whenever type resolve was already tried
6421  *
6422  * Build a MonoType from the type description in @info.
6423  * 
6424  */
6425
6426 MonoType*
6427 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6428 {
6429         MonoType *type;
6430         MonoReflectionAssembly *assembly;
6431         GString *fullName;
6432         GList *mod;
6433
6434         type = mono_reflection_get_type_internal (image, info, ignorecase);
6435         if (type)
6436                 return type;
6437         if (!mono_domain_has_type_resolve (mono_domain_get ()))
6438                 return NULL;
6439
6440         if (type_resolve) {
6441                 if (*type_resolve) 
6442                         return NULL;
6443                 else
6444                         *type_resolve = TRUE;
6445         }
6446         
6447         /* Reconstruct the type name */
6448         fullName = g_string_new ("");
6449         if (info->name_space && (info->name_space [0] != '\0'))
6450                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6451         else
6452                 g_string_printf (fullName, info->name);
6453         for (mod = info->nested; mod; mod = mod->next)
6454                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6455
6456         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6457         if (assembly) {
6458                 if (assembly->assembly->dynamic) {
6459                         /* Enumerate all modules */
6460                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6461                         int i;
6462
6463                         type = NULL;
6464                         if (abuilder->modules) {
6465                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6466                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6467                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6468                                         if (type)
6469                                                 break;
6470                                 }
6471                         }
6472
6473                         if (!type && abuilder->loaded_modules) {
6474                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6475                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6476                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6477                                         if (type)
6478                                                 break;
6479                                 }
6480                         }
6481                 }
6482                 else
6483                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
6484                                                                                                           info, ignorecase);
6485         }
6486         g_string_free (fullName, TRUE);
6487         return type;
6488 }
6489
6490 static void
6491 free_type_info (MonoTypeNameParse *info)
6492 {
6493         g_list_free (info->modifiers);
6494         g_list_free (info->nested);
6495
6496         if (info->type_arguments) {
6497                 int i;
6498
6499                 for (i = 0; i < info->type_arguments->len; i++) {
6500                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6501
6502                         free_type_info (subinfo);
6503                 }
6504
6505                 g_ptr_array_free (info->type_arguments, TRUE);
6506         }
6507 }
6508
6509 /*
6510  * mono_reflection_type_from_name:
6511  * @name: type name.
6512  * @image: a metadata context (can be NULL).
6513  *
6514  * Retrieves a MonoType from its @name. If the name is not fully qualified,
6515  * it defaults to get the type from @image or, if @image is NULL or loading
6516  * from it fails, uses corlib.
6517  * 
6518  */
6519 MonoType*
6520 mono_reflection_type_from_name (char *name, MonoImage *image)
6521 {
6522         MonoType *type = NULL;
6523         MonoTypeNameParse info;
6524         char *tmp;
6525
6526         /* Make a copy since parse_type modifies its argument */
6527         tmp = g_strdup (name);
6528         
6529         /*g_print ("requested type %s\n", str);*/
6530         if (mono_reflection_parse_type (tmp, &info)) {
6531                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6532         }
6533
6534         g_free (tmp);
6535         free_type_info (&info);
6536         return type;
6537 }
6538
6539 /*
6540  * mono_reflection_get_token:
6541  *
6542  *   Return the metadata token of OBJ which should be an object
6543  * representing a metadata element.
6544  */
6545 guint32
6546 mono_reflection_get_token (MonoObject *obj)
6547 {
6548         MonoClass *klass;
6549         guint32 token = 0;
6550
6551         klass = obj->vtable->klass;
6552
6553         if (strcmp (klass->name, "MethodBuilder") == 0) {
6554                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6555
6556                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6557         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6558                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6559
6560                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6561         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6562                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6563                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6564         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6565                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6566                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6567         } else if (strcmp (klass->name, "MonoType") == 0) {
6568                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6569                 token = mono_class_from_mono_type (tb->type)->type_token;
6570         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6571                    strcmp (klass->name, "MonoMethod") == 0 ||
6572                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
6573                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
6574                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6575                 if (m->method->is_inflated) {
6576                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6577                         return inflated->declaring->token;
6578                 } else {
6579                         token = m->method->token;
6580                 }
6581         } else if (strcmp (klass->name, "MonoField") == 0) {
6582                 MonoReflectionField *f = (MonoReflectionField*)obj;
6583
6584                 if (f->field->generic_info && f->field->generic_info->reflection_info)
6585                         return mono_reflection_get_token (f->field->generic_info->reflection_info);
6586
6587                 token = mono_class_get_field_token (f->field);
6588         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6589                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6590
6591                 token = mono_class_get_property_token (p->property);
6592         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6593                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6594
6595                 token = mono_class_get_event_token (p->event);
6596         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6597                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6598
6599                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6600         } else if (strcmp (klass->name, "Module") == 0) {
6601                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6602
6603                 token = m->token;
6604         } else if (strcmp (klass->name, "Assembly") == 0) {
6605                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6606         } else {
6607                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6608                 MonoException *ex = mono_get_exception_not_implemented (msg);
6609                 g_free (msg);
6610                 mono_raise_exception (ex);
6611         }
6612
6613         return token;
6614 }
6615
6616 static void*
6617 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6618 {
6619         int slen, type = t->type;
6620         MonoClass *tklass = t->data.klass;
6621
6622 handle_enum:
6623         switch (type) {
6624         case MONO_TYPE_U1:
6625         case MONO_TYPE_I1:
6626         case MONO_TYPE_BOOLEAN: {
6627                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6628                 *bval = *p;
6629                 *end = p + 1;
6630                 return bval;
6631         }
6632         case MONO_TYPE_CHAR:
6633         case MONO_TYPE_U2:
6634         case MONO_TYPE_I2: {
6635                 guint16 *val = g_malloc (sizeof (guint16));
6636                 *val = read16 (p);
6637                 *end = p + 2;
6638                 return val;
6639         }
6640 #if SIZEOF_VOID_P == 4
6641         case MONO_TYPE_U:
6642         case MONO_TYPE_I:
6643 #endif
6644         case MONO_TYPE_R4:
6645         case MONO_TYPE_U4:
6646         case MONO_TYPE_I4: {
6647                 guint32 *val = g_malloc (sizeof (guint32));
6648                 *val = read32 (p);
6649                 *end = p + 4;
6650                 return val;
6651         }
6652 #if SIZEOF_VOID_P == 8
6653         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6654         case MONO_TYPE_I:
6655 #endif
6656         case MONO_TYPE_R8:
6657         case MONO_TYPE_U8:
6658         case MONO_TYPE_I8: {
6659                 guint64 *val = g_malloc (sizeof (guint64));
6660                 *val = read64 (p);
6661                 *end = p + 8;
6662                 return val;
6663         }
6664         case MONO_TYPE_VALUETYPE:
6665                 if (t->data.klass->enumtype) {
6666                         type = t->data.klass->enum_basetype->type;
6667                         goto handle_enum;
6668                 } else {
6669                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6670                 }
6671                 break;
6672         case MONO_TYPE_STRING:
6673                 if (*p == (char)0xFF) {
6674                         *end = p + 1;
6675                         return NULL;
6676                 }
6677                 slen = mono_metadata_decode_value (p, &p);
6678                 *end = p + slen;
6679                 return mono_string_new_len (mono_domain_get (), p, slen);
6680         case MONO_TYPE_CLASS: {
6681                 char *n;
6682                 MonoType *t;
6683                 if (*p == (char)0xFF) {
6684                         *end = p + 1;
6685                         return NULL;
6686                 }
6687 handle_type:
6688                 slen = mono_metadata_decode_value (p, &p);
6689                 n = g_memdup (p, slen + 1);
6690                 n [slen] = 0;
6691                 t = mono_reflection_type_from_name (n, image);
6692                 if (!t)
6693                         g_warning ("Cannot load type '%s'", n);
6694                 g_free (n);
6695                 *end = p + slen;
6696                 if (t)
6697                         return mono_type_get_object (mono_domain_get (), t);
6698                 else
6699                         return NULL;
6700         }
6701         case MONO_TYPE_OBJECT: {
6702                 char subt = *p++;
6703                 MonoObject *obj;
6704                 MonoClass *subc = NULL;
6705                 void *val;
6706
6707                 if (subt == 0x50) {
6708                         goto handle_type;
6709                 } else if (subt == 0x0E) {
6710                         type = MONO_TYPE_STRING;
6711                         goto handle_enum;
6712                 } else if (subt == 0x1D) {
6713                         MonoType simple_type = {{0}};
6714                         int etype = *p;
6715                         p ++;
6716
6717                         type = MONO_TYPE_SZARRAY;
6718                         simple_type.type = etype;
6719                         tklass = mono_class_from_mono_type (&simple_type);
6720                         goto handle_enum;
6721                 } else if (subt == 0x55) {
6722                         char *n;
6723                         MonoType *t;
6724                         slen = mono_metadata_decode_value (p, &p);
6725                         n = g_memdup (p, slen + 1);
6726                         n [slen] = 0;
6727                         t = mono_reflection_type_from_name (n, image);
6728                         if (!t)
6729                                 g_error ("Cannot load type '%s'", n);
6730                         g_free (n);
6731                         p += slen;
6732                         subc = mono_class_from_mono_type (t);
6733                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6734                         MonoType simple_type = {{0}};
6735                         simple_type.type = subt;
6736                         subc = mono_class_from_mono_type (&simple_type);
6737                 } else {
6738                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6739                 }
6740                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6741                 obj = mono_object_new (mono_domain_get (), subc);
6742                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6743                 g_free (val);
6744                 return obj;
6745         }
6746         case MONO_TYPE_SZARRAY: {
6747                 MonoArray *arr;
6748                 guint32 i, alen, basetype;
6749                 alen = read32 (p);
6750                 p += 4;
6751                 if (alen == 0xffffffff) {
6752                         *end = p;
6753                         return NULL;
6754                 }
6755                 arr = mono_array_new (mono_domain_get(), tklass, alen);
6756                 basetype = tklass->byval_arg.type;
6757                 switch (basetype)
6758                 {
6759                         case MONO_TYPE_U1:
6760                         case MONO_TYPE_I1:
6761                         case MONO_TYPE_BOOLEAN:
6762                                 for (i = 0; i < alen; i++) {
6763                                         MonoBoolean val = *p++;
6764                                         mono_array_set (arr, MonoBoolean, i, val);
6765                                 }
6766                                 break;
6767                         case MONO_TYPE_CHAR:
6768                         case MONO_TYPE_U2:
6769                         case MONO_TYPE_I2:
6770                                 for (i = 0; i < alen; i++) {
6771                                         guint16 val = read16 (p);
6772                                         mono_array_set (arr, guint16, i, val);
6773                                         p += 2;
6774                                 }
6775                                 break;
6776                         case MONO_TYPE_R4:
6777                         case MONO_TYPE_U4:
6778                         case MONO_TYPE_I4:
6779                                 for (i = 0; i < alen; i++) {
6780                                         guint32 val = read32 (p);
6781                                         mono_array_set (arr, guint32, i, val);
6782                                         p += 4;
6783                                 }
6784                                 break;
6785                         case MONO_TYPE_R8:
6786                         case MONO_TYPE_U8:
6787                         case MONO_TYPE_I8:
6788                                 for (i = 0; i < alen; i++) {
6789                                         guint64 val = read64 (p);
6790                                         mono_array_set (arr, guint64, i, val);
6791                                         p += 8;
6792                                 }
6793                                 break;
6794                         case MONO_TYPE_CLASS:
6795                         case MONO_TYPE_OBJECT:
6796                         case MONO_TYPE_STRING:
6797                                 for (i = 0; i < alen; i++) {
6798                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6799                                         mono_array_setref (arr, i, item);
6800                                 }
6801                                 break;
6802                         default:
6803                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6804                 }
6805                 *end=p;
6806                 return arr;
6807         }
6808         default:
6809                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6810         }
6811         return NULL;
6812 }
6813
6814 static MonoObject*
6815 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6816 {
6817         static MonoClass *klass;
6818         static MonoMethod *ctor;
6819         MonoObject *retval;
6820         void *params [2], *unboxed;
6821
6822         if (!klass)
6823                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6824         if (!ctor)
6825                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6826         
6827         params [0] = mono_type_get_object (mono_domain_get (), t);
6828         params [1] = val;
6829         retval = mono_object_new (mono_domain_get (), klass);
6830         unboxed = mono_object_unbox (retval);
6831         mono_runtime_invoke (ctor, unboxed, params, NULL);
6832
6833         return retval;
6834 }
6835
6836 static MonoObject*
6837 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6838 {
6839         static MonoClass *klass;
6840         static MonoMethod *ctor;
6841         MonoObject *retval;
6842         void *unboxed, *params [2];
6843
6844         if (!klass)
6845                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6846         if (!ctor)
6847                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6848
6849         params [0] = minfo;
6850         params [1] = typedarg;
6851         retval = mono_object_new (mono_domain_get (), klass);
6852         unboxed = mono_object_unbox (retval);
6853         mono_runtime_invoke (ctor, unboxed, params, NULL);
6854
6855         return retval;
6856 }
6857
6858 static gboolean
6859 type_is_reference (MonoType *type)
6860 {
6861         switch (type->type) {
6862         case MONO_TYPE_BOOLEAN:
6863         case MONO_TYPE_CHAR:
6864         case MONO_TYPE_U:
6865         case MONO_TYPE_I:
6866         case MONO_TYPE_U1:
6867         case MONO_TYPE_I1:
6868         case MONO_TYPE_U2:
6869         case MONO_TYPE_I2:
6870         case MONO_TYPE_U4:
6871         case MONO_TYPE_I4:
6872         case MONO_TYPE_U8:
6873         case MONO_TYPE_I8:
6874         case MONO_TYPE_R8:
6875         case MONO_TYPE_R4:
6876         case MONO_TYPE_VALUETYPE:
6877                 return FALSE;
6878         default:
6879                 return TRUE;
6880         }
6881 }
6882
6883 static void
6884 free_param_data (MonoMethodSignature *sig, void **params) {
6885         int i;
6886         for (i = 0; i < sig->param_count; ++i) {
6887                 if (!type_is_reference (sig->params [i]))
6888                         g_free (params [i]);
6889         }
6890 }
6891
6892 /*
6893  * Find the field index in the metadata FieldDef table.
6894  */
6895 static guint32
6896 find_field_index (MonoClass *klass, MonoClassField *field) {
6897         int i;
6898
6899         for (i = 0; i < klass->field.count; ++i) {
6900                 if (field == &klass->fields [i])
6901                         return klass->field.first + 1 + i;
6902         }
6903         return 0;
6904 }
6905
6906 /*
6907  * Find the property index in the metadata Property table.
6908  */
6909 static guint32
6910 find_property_index (MonoClass *klass, MonoProperty *property) {
6911         int i;
6912
6913         for (i = 0; i < klass->property.count; ++i) {
6914                 if (property == &klass->properties [i])
6915                         return klass->property.first + 1 + i;
6916         }
6917         return 0;
6918 }
6919
6920 /*
6921  * Find the event index in the metadata Event table.
6922  */
6923 static guint32
6924 find_event_index (MonoClass *klass, MonoEvent *event) {
6925         int i;
6926
6927         for (i = 0; i < klass->event.count; ++i) {
6928                 if (event == &klass->events [i])
6929                         return klass->event.first + 1 + i;
6930         }
6931         return 0;
6932 }
6933
6934 static MonoObject*
6935 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6936 {
6937         const char *p = (const char*)data;
6938         const char *named;
6939         guint32 i, j, num_named;
6940         MonoObject *attr;
6941         void **params;
6942
6943         mono_class_init (method->klass);
6944
6945         if (len == 0) {
6946                 attr = mono_object_new (mono_domain_get (), method->klass);
6947                 mono_runtime_invoke (method, attr, NULL, NULL);
6948                 return attr;
6949         }
6950
6951         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6952                 return NULL;
6953
6954         /*g_print ("got attr %s\n", method->klass->name);*/
6955
6956         /* Allocate using alloca so it gets GC tracking */
6957         params = alloca (mono_method_signature (method)->param_count * sizeof (void*)); 
6958
6959         /* skip prolog */
6960         p += 2;
6961         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6962                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6963         }
6964
6965         named = p;
6966         attr = mono_object_new (mono_domain_get (), method->klass);
6967         mono_runtime_invoke (method, attr, params, NULL);
6968         free_param_data (method->signature, params);
6969         num_named = read16 (named);
6970         named += 2;
6971         for (j = 0; j < num_named; j++) {
6972                 gint name_len;
6973                 gboolean is_boxed = FALSE;
6974                 char *name, named_type, data_type;
6975                 named_type = *named++;
6976                 data_type = *named++; /* type of data */
6977                 if (data_type == 0x51)
6978                         is_boxed = TRUE;
6979
6980                 if (data_type == 0x55) {
6981                         gint type_len;
6982                         char *type_name;
6983                         type_len = mono_metadata_decode_blob_size (named, &named);
6984                         type_name = g_malloc (type_len + 1);
6985                         memcpy (type_name, named, type_len);
6986                         type_name [type_len] = 0;
6987                         named += type_len;
6988                         /* FIXME: lookup the type and check type consistency */
6989                         g_free (type_name);
6990                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6991                         /* this seems to be the type of the element of the array */
6992                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6993                         named++;
6994                 }
6995                 name_len = mono_metadata_decode_blob_size (named, &named);
6996                 name = g_malloc (name_len + 1);
6997                 memcpy (name, named, name_len);
6998                 name [name_len] = 0;
6999                 named += name_len;
7000                 if (named_type == 0x53) {
7001                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7002                         void *val = load_cattr_value (image, field->type, named, &named);
7003                         mono_field_set_value (attr, field, val);
7004                         if (!type_is_reference (field->type))
7005                                 g_free (val);
7006                 } else if (named_type == 0x54) {
7007                         MonoProperty *prop;
7008                         void *pparams [1];
7009                         MonoType *prop_type;
7010
7011                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7012                         /* can we have more that 1 arg in a custom attr named property? */
7013                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7014                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7015                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
7016                         mono_property_set_value (prop, attr, pparams, NULL);
7017                         if (!type_is_reference (prop_type))
7018                                 g_free (pparams [0]);
7019                 }
7020                 g_free (name);
7021         }
7022
7023         return attr;
7024 }
7025
7026 static MonoObject*
7027 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7028 {
7029         MonoArray *typedargs, *namedargs;
7030         MonoClass *attrklass;
7031         static MonoClass *klass;
7032         static MonoMethod *ctor;
7033         MonoDomain *domain;
7034         MonoObject *attr;
7035         const char *p = (const char*)data;
7036         const char *named;
7037         guint32 i, j, num_named;
7038         void *params [3];
7039
7040         mono_class_init (method->klass);
7041         
7042         if (!klass)
7043                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7044         if (!ctor)
7045                 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7046         
7047         domain = mono_domain_get ();
7048         if (len == 0) {
7049                 /* This is for Attributes with no parameters */
7050                 attr = mono_object_new (domain, klass);
7051                 params [0] = mono_method_get_object (domain, method, NULL);
7052                 params [1] = params [2] = NULL;
7053                 mono_runtime_invoke (method, attr, params, NULL);
7054                 return attr;
7055         }
7056
7057         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7058                 return NULL;
7059
7060         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7061         
7062         /* skip prolog */
7063         p += 2;
7064         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7065                 MonoObject *obj, *typedarg;
7066                 void *val;
7067
7068                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7069                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
7070                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7071                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7072                 mono_array_setref (typedargs, i, typedarg);
7073
7074                 if (!type_is_reference (mono_method_signature (method)->params [i]))
7075                         g_free (val);
7076         }
7077
7078         named = p;
7079         num_named = read16 (named);
7080         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7081         named += 2;
7082         attrklass = method->klass;
7083         for (j = 0; j < num_named; j++) {
7084                 gint name_len;
7085                 char *name, named_type, data_type;
7086                 named_type = *named++;
7087                 data_type = *named++; /* type of data */
7088                 if (data_type == 0x55) {
7089                         gint type_len;
7090                         char *type_name;
7091                         type_len = mono_metadata_decode_blob_size (named, &named);
7092                         type_name = g_malloc (type_len + 1);
7093                         memcpy (type_name, named, type_len);
7094                         type_name [type_len] = 0;
7095                         named += type_len;
7096                         /* FIXME: lookup the type and check type consistency */
7097                         g_free (type_name);
7098                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
7099                         /* this seems to be the type of the element of the array */
7100                         /* g_print ("skipping 0x%02x after prop\n", *named); */
7101                         named++;
7102                 }
7103                 name_len = mono_metadata_decode_blob_size (named, &named);
7104                 name = g_malloc (name_len + 1);
7105                 memcpy (name, named, name_len);
7106                 name [name_len] = 0;
7107                 named += name_len;
7108                 if (named_type == 0x53) {
7109                         MonoObject *obj, *typedarg, *namedarg;
7110                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7111                         void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7112                         
7113                         minfo = mono_field_get_object (domain, NULL, field);
7114                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7115                         typedarg = create_cattr_typed_arg (field->type, obj);
7116                         namedarg = create_cattr_named_arg (minfo, typedarg);
7117                         mono_array_setref (namedargs, j, namedarg);
7118                         if (!type_is_reference (field->type))
7119                                 g_free (val);
7120                 } else if (named_type == 0x54) {
7121                         MonoObject *obj, *typedarg, *namedarg;
7122                         MonoType *prop_type;
7123                         void *val, *minfo;
7124                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7125
7126                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
7127                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7128                         minfo =  mono_property_get_object (domain, NULL, prop);
7129                         val = load_cattr_value (image, prop_type, named, &named);
7130                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7131                         typedarg = create_cattr_typed_arg (prop_type, obj);
7132                         namedarg = create_cattr_named_arg (minfo, typedarg);
7133                         mono_array_setref (namedargs, j, namedarg);
7134                         if (!type_is_reference (prop_type))
7135                                 g_free (val);
7136                 }
7137                 g_free (name);
7138         }
7139         attr = mono_object_new (domain, klass);
7140         params [0] = mono_method_get_object (domain, method, NULL);
7141         params [1] = typedargs;
7142         params [2] = namedargs;
7143         mono_runtime_invoke (ctor, attr, params, NULL);
7144         return attr;
7145 }
7146
7147 MonoArray*
7148 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7149 {
7150         MonoArray *result;
7151         MonoClass *klass;
7152         MonoObject *attr;
7153         int i;
7154
7155         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7156         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7157         for (i = 0; i < cinfo->num_attrs; ++i) {
7158                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7159                 mono_array_setref (result, i, attr);
7160         }
7161         return result;
7162 }
7163
7164 static MonoArray*
7165 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7166 {
7167         MonoArray *result;
7168         MonoObject *attr;
7169         MonoClass *klass;
7170         int i, n;
7171
7172         n = 0;
7173         for (i = 0; i < cinfo->num_attrs; ++i) {
7174                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7175                         n ++;
7176         }
7177
7178         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7179         result = mono_array_new (mono_domain_get (), klass, n);
7180         n = 0;
7181         for (i = 0; i < cinfo->num_attrs; ++i) {
7182                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7183                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7184                         mono_array_setref (result, n, attr);
7185                         n ++;
7186                 }
7187         }
7188         return result;
7189 }
7190
7191 static MonoArray*
7192 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7193 {
7194         MonoArray *result;
7195         static MonoClass *klass;
7196         MonoObject *attr;
7197         int i;
7198
7199         if (!klass)
7200                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7201         
7202         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7203         for (i = 0; i < cinfo->num_attrs; ++i) {
7204                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7205                 mono_array_setref (result, i, attr);
7206         }
7207         return result;
7208 }
7209
7210 MonoCustomAttrInfo*
7211 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7212 {
7213         guint32 mtoken, i, len;
7214         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7215         MonoTableInfo *ca;
7216         MonoCustomAttrInfo *ainfo;
7217         GList *tmp, *list = NULL;
7218         const char *data;
7219
7220         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7221
7222         i = mono_metadata_custom_attrs_from_index (image, idx);
7223         if (!i)
7224                 return NULL;
7225         i --;
7226         while (i < ca->rows) {
7227                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7228                         break;
7229                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7230                 ++i;
7231         }
7232         len = g_list_length (list);
7233         if (!len)
7234                 return NULL;
7235         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7236         ainfo->num_attrs = len;
7237         ainfo->image = image;
7238         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7239                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7240                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7241                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7242                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7243                         mtoken |= MONO_TOKEN_METHOD_DEF;
7244                         break;
7245                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7246                         mtoken |= MONO_TOKEN_MEMBER_REF;
7247                         break;
7248                 default:
7249                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7250                         break;
7251                 }
7252                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7253                 if (!ainfo->attrs [i].ctor)
7254                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7255                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7256                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7257                 ainfo->attrs [i].data = (guchar*)data;
7258         }
7259         g_list_free (list);
7260
7261         return ainfo;
7262 }
7263
7264 MonoCustomAttrInfo*
7265 mono_custom_attrs_from_method (MonoMethod *method)
7266 {
7267         MonoCustomAttrInfo *cinfo;
7268         guint32 idx;
7269         
7270         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7271                 return cinfo;
7272         idx = mono_method_get_index (method);
7273         idx <<= MONO_CUSTOM_ATTR_BITS;
7274         idx |= MONO_CUSTOM_ATTR_METHODDEF;
7275         return mono_custom_attrs_from_index (method->klass->image, idx);
7276 }
7277
7278 MonoCustomAttrInfo*
7279 mono_custom_attrs_from_class (MonoClass *klass)
7280 {
7281         MonoCustomAttrInfo *cinfo;
7282         guint32 idx;
7283         
7284         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7285                 return cinfo;
7286         idx = mono_metadata_token_index (klass->type_token);
7287         idx <<= MONO_CUSTOM_ATTR_BITS;
7288         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7289         return mono_custom_attrs_from_index (klass->image, idx);
7290 }
7291
7292 MonoCustomAttrInfo*
7293 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7294 {
7295         MonoCustomAttrInfo *cinfo;
7296         guint32 idx;
7297         
7298         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7299                 return cinfo;
7300         idx = 1; /* there is only one assembly */
7301         idx <<= MONO_CUSTOM_ATTR_BITS;
7302         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7303         return mono_custom_attrs_from_index (assembly->image, idx);
7304 }
7305
7306 static MonoCustomAttrInfo*
7307 mono_custom_attrs_from_module (MonoImage *image)
7308 {
7309         MonoCustomAttrInfo *cinfo;
7310         guint32 idx;
7311         
7312         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7313                 return cinfo;
7314         idx = 1; /* there is only one module */
7315         idx <<= MONO_CUSTOM_ATTR_BITS;
7316         idx |= MONO_CUSTOM_ATTR_MODULE;
7317         return mono_custom_attrs_from_index (image, idx);
7318 }
7319
7320 MonoCustomAttrInfo*
7321 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7322 {
7323         MonoCustomAttrInfo *cinfo;
7324         guint32 idx;
7325         
7326         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7327                 return cinfo;
7328         idx = find_property_index (klass, property);
7329         idx <<= MONO_CUSTOM_ATTR_BITS;
7330         idx |= MONO_CUSTOM_ATTR_PROPERTY;
7331         return mono_custom_attrs_from_index (klass->image, idx);
7332 }
7333
7334 MonoCustomAttrInfo*
7335 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7336 {
7337         MonoCustomAttrInfo *cinfo;
7338         guint32 idx;
7339         
7340         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7341                 return cinfo;
7342         idx = find_event_index (klass, event);
7343         idx <<= MONO_CUSTOM_ATTR_BITS;
7344         idx |= MONO_CUSTOM_ATTR_EVENT;
7345         return mono_custom_attrs_from_index (klass->image, idx);
7346 }
7347
7348 MonoCustomAttrInfo*
7349 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7350 {
7351         MonoCustomAttrInfo *cinfo;
7352         guint32 idx;
7353         
7354         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7355                 return cinfo;
7356         idx = find_field_index (klass, field);
7357         idx <<= MONO_CUSTOM_ATTR_BITS;
7358         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7359         return mono_custom_attrs_from_index (klass->image, idx);
7360 }
7361
7362 MonoCustomAttrInfo*
7363 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7364 {
7365         MonoTableInfo *ca;
7366         guint32 i, idx, method_index;
7367         guint32 param_list, param_last, param_pos, found;
7368         MonoImage *image;
7369         MonoReflectionMethodAux *aux;
7370
7371         if (method->klass->image->dynamic) {
7372                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7373                 if (!aux || !aux->param_cattr)
7374                         return NULL;
7375                 return aux->param_cattr [param];
7376         }
7377
7378         image = method->klass->image;
7379         method_index = mono_method_get_index (method);
7380         ca = &image->tables [MONO_TABLE_METHOD];
7381
7382         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7383         if (method_index == ca->rows) {
7384                 ca = &image->tables [MONO_TABLE_PARAM];
7385                 param_last = ca->rows + 1;
7386         } else {
7387                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7388                 ca = &image->tables [MONO_TABLE_PARAM];
7389         }
7390         found = FALSE;
7391         for (i = param_list; i < param_last; ++i) {
7392                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7393                 if (param_pos == param) {
7394                         found = TRUE;
7395                         break;
7396                 }
7397         }
7398         if (!found)
7399                 return NULL;
7400         idx = i;
7401         idx <<= MONO_CUSTOM_ATTR_BITS;
7402         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7403         return mono_custom_attrs_from_index (image, idx);
7404 }
7405
7406 gboolean
7407 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7408 {
7409         int i;
7410         MonoClass *klass;
7411         for (i = 0; i < ainfo->num_attrs; ++i) {
7412                 klass = ainfo->attrs [i].ctor->klass;
7413                 if (mono_class_has_parent (klass, attr_klass))
7414                         return TRUE;
7415         }
7416         return FALSE;
7417 }
7418
7419 MonoObject*
7420 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7421 {
7422         int i, attr_index;
7423         MonoClass *klass;
7424         MonoArray *attrs;
7425
7426         attr_index = -1;
7427         for (i = 0; i < ainfo->num_attrs; ++i) {
7428                 klass = ainfo->attrs [i].ctor->klass;
7429                 if (mono_class_has_parent (klass, attr_klass)) {
7430                         attr_index = i;
7431                         break;
7432                 }
7433         }
7434         if (attr_index == -1)
7435                 return NULL;
7436
7437         attrs = mono_custom_attrs_construct (ainfo);
7438         if (attrs)
7439                 return mono_array_get (attrs, MonoObject*, attr_index);
7440         else
7441                 return NULL;
7442 }
7443
7444 /*
7445  * mono_reflection_get_custom_attrs_info:
7446  * @obj: a reflection object handle
7447  *
7448  * Return the custom attribute info for attributes defined for the
7449  * reflection handle @obj. The objects.
7450  */
7451 MonoCustomAttrInfo*
7452 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7453 {
7454         MonoClass *klass;
7455         MonoCustomAttrInfo *cinfo = NULL;
7456         
7457         klass = obj->vtable->klass;
7458         if (klass == mono_defaults.monotype_class) {
7459                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7460                 klass = mono_class_from_mono_type (rtype->type);
7461                 cinfo = mono_custom_attrs_from_class (klass);
7462         } else if (strcmp ("Assembly", klass->name) == 0) {
7463                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7464                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7465         } else if (strcmp ("Module", klass->name) == 0) {
7466                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7467                 cinfo = mono_custom_attrs_from_module (module->image);
7468         } else if (strcmp ("MonoProperty", klass->name) == 0) {
7469                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7470                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7471         } else if (strcmp ("MonoEvent", klass->name) == 0) {
7472                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7473                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7474         } else if (strcmp ("MonoField", klass->name) == 0) {
7475                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7476                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7477         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7478                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7479                 cinfo = mono_custom_attrs_from_method (rmethod->method);
7480         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7481                 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7482                 cinfo = mono_custom_attrs_from_method (method);
7483         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7484                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7485                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7486                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7487         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7488                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7489                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7490         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7491                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7492                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7493         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7494                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7495                 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7496         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7497                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7498                 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7499         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7500                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7501                 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7502         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7503                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7504                 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7505         } else { /* handle other types here... */
7506                 g_error ("get custom attrs not yet supported for %s", klass->name);
7507         }
7508
7509         return cinfo;
7510 }
7511
7512 /*
7513  * mono_reflection_get_custom_attrs_by_type:
7514  * @obj: a reflection object handle
7515  *
7516  * Return an array with all the custom attributes defined of the
7517  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
7518  * of that type are returned. The objects are fully build.
7519  */
7520 MonoArray*
7521 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7522 {
7523         MonoArray *result;
7524         MonoCustomAttrInfo *cinfo;
7525
7526         cinfo = mono_reflection_get_custom_attrs_info (obj);
7527         if (cinfo) {
7528                 if (attr_klass)
7529                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7530                 else
7531                         result = mono_custom_attrs_construct (cinfo);
7532                 if (!cinfo->cached)
7533                         mono_custom_attrs_free (cinfo);
7534         } else {
7535                 MonoClass *klass;
7536                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7537                 result = mono_array_new (mono_domain_get (), klass, 0);
7538         }
7539
7540         return result;
7541 }
7542
7543 /*
7544  * mono_reflection_get_custom_attrs:
7545  * @obj: a reflection object handle
7546  *
7547  * Return an array with all the custom attributes defined of the
7548  * reflection handle @obj. The objects are fully build.
7549  */
7550 MonoArray*
7551 mono_reflection_get_custom_attrs (MonoObject *obj)
7552 {
7553         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7554 }
7555
7556 /*
7557  * mono_reflection_get_custom_attrs_data:
7558  * @obj: a reflection obj handle
7559  *
7560  * Returns an array of System.Reflection.CustomAttributeData,
7561  * which include information about attributes reflected on
7562  * types loaded using the Reflection Only methods
7563  */
7564 MonoArray*
7565 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7566 {
7567         MonoArray *result;
7568         MonoCustomAttrInfo *cinfo;
7569
7570         cinfo = mono_reflection_get_custom_attrs_info (obj);
7571         if (cinfo) {
7572                 result = mono_custom_attrs_data_construct (cinfo);
7573                 if (!cinfo->cached)
7574                         mono_custom_attrs_free (cinfo);
7575         } else {
7576                 MonoClass *klass;
7577                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7578                 result = mono_array_new (mono_domain_get (), klass, 0);
7579         }
7580
7581         return result;
7582 }
7583
7584 /**
7585  * LOCKING: Assumes the loader lock is held.
7586  */
7587 static MonoMethodSignature*
7588 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7589         MonoMethodSignature *sig;
7590         int count, i;
7591
7592         count = parameters? mono_array_length (parameters): 0;
7593
7594         sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7595         sig->param_count = count;
7596         sig->sentinelpos = -1; /* FIXME */
7597         for (i = 0; i < count; ++i) {
7598                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7599                 sig->params [i] = pt->type;
7600         }
7601         return sig;
7602 }
7603
7604 /**
7605  * LOCKING: Assumes the loader lock is held.
7606  */
7607 static MonoMethodSignature*
7608 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7609         MonoMethodSignature *sig;
7610
7611         sig = parameters_to_signature (mp, ctor->parameters);
7612         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7613         sig->ret = &mono_defaults.void_class->byval_arg;
7614         return sig;
7615 }
7616
7617 /**
7618  * LOCKING: Assumes the loader lock is held.
7619  */
7620 static MonoMethodSignature*
7621 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7622         MonoMethodSignature *sig;
7623
7624         sig = parameters_to_signature (mp, method->parameters);
7625         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7626         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7627         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7628         return sig;
7629 }
7630
7631 static MonoMethodSignature*
7632 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7633         MonoMethodSignature *sig;
7634
7635         sig = parameters_to_signature (NULL, method->parameters);
7636         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7637         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7638         sig->generic_param_count = 0;
7639         return sig;
7640 }
7641
7642 static void
7643 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7644 {
7645         MonoClass *klass = mono_object_class (prop);
7646         if (strcmp (klass->name, "PropertyBuilder") == 0) {
7647                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7648                 *name = mono_string_to_utf8 (pb->name);
7649                 *type = pb->type->type;
7650         } else {
7651                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7652                 *name = g_strdup (p->property->name);
7653                 if (p->property->get)
7654                         *type = mono_method_signature (p->property->get)->ret;
7655                 else
7656                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7657         }
7658 }
7659
7660 static void
7661 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7662 {
7663         MonoClass *klass = mono_object_class (field);
7664         if (strcmp (klass->name, "FieldBuilder") == 0) {
7665                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7666                 *name = mono_string_to_utf8 (fb->name);
7667                 *type = fb->type->type;
7668         } else {
7669                 MonoReflectionField *f = (MonoReflectionField *)field;
7670                 *name = g_strdup (f->field->name);
7671                 *type = f->field->type;
7672         }
7673 }
7674
7675 /*
7676  * Encode a value in a custom attribute stream of bytes.
7677  * The value to encode is either supplied as an object in argument val
7678  * (valuetypes are boxed), or as a pointer to the data in the
7679  * argument argval.
7680  * @type represents the type of the value
7681  * @buffer is the start of the buffer
7682  * @p the current position in the buffer
7683  * @buflen contains the size of the buffer and is used to return the new buffer size
7684  * if this needs to be realloced.
7685  * @retbuffer and @retp return the start and the position of the buffer
7686  */
7687 static void
7688 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7689 {
7690         MonoTypeEnum simple_type;
7691         
7692         if ((p-buffer) + 10 >= *buflen) {
7693                 char *newbuf;
7694                 *buflen *= 2;
7695                 newbuf = g_realloc (buffer, *buflen);
7696                 p = newbuf + (p-buffer);
7697                 buffer = newbuf;
7698         }
7699         if (!argval)
7700                 argval = ((char*)arg + sizeof (MonoObject));
7701         simple_type = type->type;
7702 handle_enum:
7703         switch (simple_type) {
7704         case MONO_TYPE_BOOLEAN:
7705         case MONO_TYPE_U1:
7706         case MONO_TYPE_I1:
7707                 *p++ = *argval;
7708                 break;
7709         case MONO_TYPE_CHAR:
7710         case MONO_TYPE_U2:
7711         case MONO_TYPE_I2:
7712                 swap_with_size (p, argval, 2, 1);
7713                 p += 2;
7714                 break;
7715         case MONO_TYPE_U4:
7716         case MONO_TYPE_I4:
7717         case MONO_TYPE_R4:
7718                 swap_with_size (p, argval, 4, 1);
7719                 p += 4;
7720                 break;
7721         case MONO_TYPE_U8:
7722         case MONO_TYPE_I8:
7723         case MONO_TYPE_R8:
7724                 swap_with_size (p, argval, 8, 1);
7725                 p += 8;
7726                 break;
7727         case MONO_TYPE_VALUETYPE:
7728                 if (type->data.klass->enumtype) {
7729                         simple_type = type->data.klass->enum_basetype->type;
7730                         goto handle_enum;
7731                 } else {
7732                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7733                 }
7734                 break;
7735         case MONO_TYPE_STRING: {
7736                 char *str;
7737                 guint32 slen;
7738                 if (!arg) {
7739                         *p++ = 0xFF;
7740                         break;
7741                 }
7742                 str = mono_string_to_utf8 ((MonoString*)arg);
7743                 slen = strlen (str);
7744                 if ((p-buffer) + 10 + slen >= *buflen) {
7745                         char *newbuf;
7746                         *buflen *= 2;
7747                         *buflen += slen;
7748                         newbuf = g_realloc (buffer, *buflen);
7749                         p = newbuf + (p-buffer);
7750                         buffer = newbuf;
7751                 }
7752                 mono_metadata_encode_value (slen, p, &p);
7753                 memcpy (p, str, slen);
7754                 p += slen;
7755                 g_free (str);
7756                 break;
7757         }
7758         case MONO_TYPE_CLASS: {
7759                 char *str;
7760                 guint32 slen;
7761                 MonoClass *k;
7762                 if (!arg) {
7763                         *p++ = 0xFF;
7764                         break;
7765                 }
7766                 k = mono_object_class (arg);
7767                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7768                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7769                         g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7770 handle_type:
7771                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7772                 slen = strlen (str);
7773                 if ((p-buffer) + 10 + slen >= *buflen) {
7774                         char *newbuf;
7775                         *buflen *= 2;
7776                         *buflen += slen;
7777                         newbuf = g_realloc (buffer, *buflen);
7778                         p = newbuf + (p-buffer);
7779                         buffer = newbuf;
7780                 }
7781                 mono_metadata_encode_value (slen, p, &p);
7782                 memcpy (p, str, slen);
7783                 p += slen;
7784                 g_free (str);
7785                 break;
7786         }
7787         case MONO_TYPE_SZARRAY: {
7788                 int len, i;
7789                 MonoClass *eclass, *arg_eclass;
7790
7791                 if (!arg) {
7792                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7793                         break;
7794                 }
7795                 len = mono_array_length ((MonoArray*)arg);
7796                 *p++ = len & 0xff;
7797                 *p++ = (len >> 8) & 0xff;
7798                 *p++ = (len >> 16) & 0xff;
7799                 *p++ = (len >> 24) & 0xff;
7800                 *retp = p;
7801                 *retbuffer = buffer;
7802                 eclass = type->data.klass;
7803                 arg_eclass = mono_object_class (arg)->element_class;
7804
7805                 if (!eclass) {
7806                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7807                         eclass = mono_defaults.object_class;
7808                 }
7809                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7810                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7811                         int elsize = mono_class_array_element_size (arg_eclass);
7812                         for (i = 0; i < len; ++i) {
7813                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7814                                 elptr += elsize;
7815                         }
7816                 } else if (eclass->valuetype && arg_eclass->valuetype) {
7817                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7818                         int elsize = mono_class_array_element_size (eclass);
7819                         for (i = 0; i < len; ++i) {
7820                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7821                                 elptr += elsize;
7822                         }
7823                 } else {
7824                         for (i = 0; i < len; ++i) {
7825                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7826                         }
7827                 }
7828                 break;
7829         }
7830         case MONO_TYPE_OBJECT: {
7831                 MonoClass *klass;
7832                 char *str;
7833                 guint32 slen;
7834
7835                 /*
7836                  * The parameter type is 'object' but the type of the actual
7837                  * argument is not. So we have to add type information to the blob
7838                  * too. This is completely undocumented in the spec.
7839                  */
7840
7841                 if (arg == NULL) {
7842                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
7843                         *p++ = 0xFF;
7844                         break;
7845                 }
7846                 
7847                 klass = mono_object_class (arg);
7848
7849                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7850                         *p++ = 0x50;
7851                         goto handle_type;
7852                 } else if (klass->enumtype) {
7853                         *p++ = 0x55;
7854                 } else if (klass == mono_defaults.string_class) {
7855                         simple_type = MONO_TYPE_STRING;
7856                         *p++ = 0x0E;
7857                         goto handle_enum;
7858                 } else if (klass->rank == 1) {
7859                         simple_type = MONO_TYPE_SZARRAY;
7860                         *p++ = 0x1D;
7861                         *p++ = klass->element_class->byval_arg.type;
7862                         goto handle_enum;
7863                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7864                         *p++ = simple_type = klass->byval_arg.type;
7865                         goto handle_enum;
7866                 } else {
7867                         g_error ("unhandled type in custom attr");
7868                 }
7869                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7870                 slen = strlen (str);
7871                 if ((p-buffer) + 10 + slen >= *buflen) {
7872                         char *newbuf;
7873                         *buflen *= 2;
7874                         *buflen += slen;
7875                         newbuf = g_realloc (buffer, *buflen);
7876                         p = newbuf + (p-buffer);
7877                         buffer = newbuf;
7878                 }
7879                 mono_metadata_encode_value (slen, p, &p);
7880                 memcpy (p, str, slen);
7881                 p += slen;
7882                 g_free (str);
7883                 simple_type = klass->enum_basetype->type;
7884                 goto handle_enum;
7885         }
7886         default:
7887                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7888         }
7889         *retp = p;
7890         *retbuffer = buffer;
7891 }
7892
7893 static void
7894 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7895 {
7896         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7897                 char *str = type_get_qualified_name (type, NULL);
7898                 int slen = strlen (str);
7899
7900                 *p++ = 0x55;
7901                 /*
7902                  * This seems to be optional...
7903                  * *p++ = 0x80;
7904                  */
7905                 mono_metadata_encode_value (slen, p, &p);
7906                 memcpy (p, str, slen);
7907                 p += slen;
7908                 g_free (str);
7909         } else if (type->type == MONO_TYPE_OBJECT) {
7910                 *p++ = 0x51;
7911         } else if (type->type == MONO_TYPE_CLASS) {
7912                 /* it should be a type: encode_cattr_value () has the check */
7913                 *p++ = 0x50;
7914         } else {
7915                 mono_metadata_encode_value (type->type, p, &p);
7916                 if (type->type == MONO_TYPE_SZARRAY)
7917                         /* See the examples in Partition VI, Annex B */
7918                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7919         }
7920
7921         *retp = p;
7922 }
7923
7924 static void
7925 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7926 {
7927         int len;
7928         /* Preallocate a large enough buffer */
7929         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7930                 char *str = type_get_qualified_name (type, NULL);
7931                 len = strlen (str);
7932                 g_free (str);
7933         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7934                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7935                 len = strlen (str);
7936                 g_free (str);
7937         } else {
7938                 len = 0;
7939         }
7940         len += strlen (name);
7941
7942         if ((p-buffer) + 20 + len >= *buflen) {
7943                 char *newbuf;
7944                 *buflen *= 2;
7945                 *buflen += len;
7946                 newbuf = g_realloc (buffer, *buflen);
7947                 p = newbuf + (p-buffer);
7948                 buffer = newbuf;
7949         }
7950
7951         encode_field_or_prop_type (type, p, &p);
7952
7953         len = strlen (name);
7954         mono_metadata_encode_value (len, p, &p);
7955         memcpy (p, name, len);
7956         p += len;
7957         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7958         *retp = p;
7959         *retbuffer = buffer;
7960 }
7961
7962 /*
7963  * mono_reflection_get_custom_attrs_blob:
7964  * @ctor: custom attribute constructor
7965  * @ctorArgs: arguments o the constructor
7966  * @properties:
7967  * @propValues:
7968  * @fields:
7969  * @fieldValues:
7970  * 
7971  * Creates the blob of data that needs to be saved in the metadata and that represents
7972  * the custom attributed described by @ctor, @ctorArgs etc.
7973  * Returns: a Byte array representing the blob of data.
7974  */
7975 MonoArray*
7976 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
7977 {
7978         MonoArray *result;
7979         MonoMethodSignature *sig;
7980         MonoObject *arg;
7981         char *buffer, *p;
7982         guint32 buflen, i;
7983
7984         MONO_ARCH_SAVE_REGS;
7985
7986         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7987                 /* sig is freed later so allocate it in the heap */
7988                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7989         } else {
7990                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7991         }
7992
7993         g_assert (mono_array_length (ctorArgs) == sig->param_count);
7994         buflen = 256;
7995         p = buffer = g_malloc (buflen);
7996         /* write the prolog */
7997         *p++ = 1;
7998         *p++ = 0;
7999         for (i = 0; i < sig->param_count; ++i) {
8000                 arg = mono_array_get (ctorArgs, MonoObject*, i);
8001                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8002         }
8003         i = 0;
8004         if (properties)
8005                 i += mono_array_length (properties);
8006         if (fields)
8007                 i += mono_array_length (fields);
8008         *p++ = i & 0xff;
8009         *p++ = (i >> 8) & 0xff;
8010         if (properties) {
8011                 MonoObject *prop;
8012                 for (i = 0; i < mono_array_length (properties); ++i) {
8013                         MonoType *ptype;
8014                         char *pname;
8015
8016                         prop = mono_array_get (properties, gpointer, i);
8017                         get_prop_name_and_type (prop, &pname, &ptype);
8018                         *p++ = 0x54; /* PROPERTY signature */
8019                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8020                         g_free (pname);
8021                 }
8022         }
8023
8024         if (fields) {
8025                 MonoObject *field;
8026                 for (i = 0; i < mono_array_length (fields); ++i) {
8027                         MonoType *ftype;
8028                         char *fname;
8029
8030                         field = mono_array_get (fields, gpointer, i);
8031                         get_field_name_and_type (field, &fname, &ftype);
8032                         *p++ = 0x53; /* FIELD signature */
8033                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8034                         g_free (fname);
8035                 }
8036         }
8037
8038         g_assert (p - buffer <= buflen);
8039         buflen = p - buffer;
8040         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8041         p = mono_array_addr (result, char, 0);
8042         memcpy (p, buffer, buflen);
8043         g_free (buffer);
8044         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8045                 g_free (sig);
8046         return result;
8047 }
8048
8049 #if HAVE_SGEN_GC
8050 static void* reflection_info_desc = NULL;
8051 #endif
8052
8053 /*
8054  * mono_reflection_setup_internal_class:
8055  * @tb: a TypeBuilder object
8056  *
8057  * Creates a MonoClass that represents the TypeBuilder.
8058  * This is a trick that lets us simplify a lot of reflection code
8059  * (and will allow us to support Build and Run assemblies easier).
8060  */
8061 void
8062 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8063 {
8064         MonoClass *klass, *parent;
8065
8066         MONO_ARCH_SAVE_REGS;
8067
8068         mono_loader_lock ();
8069
8070         if (tb->parent) {
8071                 /* check so we can compile corlib correctly */
8072                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8073                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8074                         parent = tb->parent->type->data.klass;
8075                 } else {
8076                         parent = my_mono_class_from_mono_type (tb->parent->type);
8077                 }
8078         } else {
8079                 parent = NULL;
8080         }
8081         
8082         /* the type has already being created: it means we just have to change the parent */
8083         if (tb->type.type) {
8084                 klass = mono_class_from_mono_type (tb->type.type);
8085                 klass->parent = NULL;
8086                 /* fool mono_class_setup_parent */
8087                 klass->supertypes = NULL;
8088                 mono_class_setup_parent (klass, parent);
8089                 mono_class_setup_mono_type (klass);
8090                 mono_loader_unlock ();
8091                 return;
8092         }
8093
8094         klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8095
8096         klass->image = &tb->module->dynamic_image->image;
8097
8098         klass->inited = 1; /* we lie to the runtime */
8099         klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8100         klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8101         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8102         klass->flags = tb->attrs;
8103
8104         klass->element_class = klass;
8105
8106 #if HAVE_SGEN_GC
8107         if (!reflection_info_desc) {
8108                 gsize bmap = 1;
8109                 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
8110         }
8111         mono_gc_register_root (&klass->reflection_info, sizeof (gpointer), reflection_info_desc);
8112 #endif
8113         klass->reflection_info = tb;
8114
8115         /* Put into cache so mono_class_get () will find it */
8116         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8117
8118         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8119                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8120
8121         if (parent != NULL) {
8122                 mono_class_setup_parent (klass, parent);
8123         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8124                 const char *old_n = klass->name;
8125                 /* trick to get relative numbering right when compiling corlib */
8126                 klass->name = "BuildingObject";
8127                 mono_class_setup_parent (klass, mono_defaults.object_class);
8128                 klass->name = old_n;
8129         }
8130
8131         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8132                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8133                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8134                 klass->instance_size = sizeof (MonoObject);
8135                 klass->size_inited = 1;
8136                 mono_class_setup_vtable_general (klass, NULL, 0);
8137         }
8138
8139         mono_class_setup_mono_type (klass);
8140
8141         mono_class_setup_supertypes (klass);
8142
8143         /*
8144          * FIXME: handle interfaces.
8145          */
8146
8147         tb->type.type = &klass->byval_arg;
8148
8149         if (tb->nesting_type) {
8150                 g_assert (tb->nesting_type->type);
8151                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8152         }
8153
8154         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8155
8156         mono_loader_unlock ();
8157 }
8158
8159 /*
8160  * mono_reflection_setup_generic_class:
8161  * @tb: a TypeBuilder object
8162  *
8163  * Setup the generic class before adding the first generic parameter.
8164  */
8165 void
8166 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8167 {
8168         MonoClass *klass;
8169
8170         MONO_ARCH_SAVE_REGS;
8171
8172         klass = my_mono_class_from_mono_type (tb->type.type);
8173         if (tb->generic_container)
8174                 return;
8175
8176         tb->generic_container = g_new0 (MonoGenericContainer, 1);
8177         tb->generic_container->klass = klass;
8178
8179         tb->generic_container->context.container = tb->generic_container;
8180 }
8181
8182 /*
8183  * mono_reflection_create_generic_class:
8184  * @tb: a TypeBuilder object
8185  *
8186  * Creates the generic class after all generic parameters have been added.
8187  */
8188 void
8189 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8190 {
8191         MonoClass *klass;
8192         int count, i;
8193
8194         MONO_ARCH_SAVE_REGS;
8195
8196         klass = my_mono_class_from_mono_type (tb->type.type);
8197
8198         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8199
8200         if (klass->generic_container || (count == 0))
8201                 return;
8202
8203         g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8204
8205         klass->generic_container = tb->generic_container;
8206
8207         klass->generic_container->type_argc = count;
8208         klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8209
8210         for (i = 0; i < count; i++) {
8211                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8212                 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8213                 g_assert (klass->generic_container->type_params [i].owner);
8214         }
8215
8216         klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8217 }
8218
8219 /*
8220  * mono_reflection_create_internal_class:
8221  * @tb: a TypeBuilder object
8222  *
8223  * Actually create the MonoClass that is associated with the TypeBuilder.
8224  */
8225 void
8226 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8227 {
8228         MonoClass *klass;
8229
8230         MONO_ARCH_SAVE_REGS;
8231
8232         klass = my_mono_class_from_mono_type (tb->type.type);
8233
8234         mono_loader_lock ();
8235         if (klass->enumtype && klass->enum_basetype == NULL) {
8236                 MonoReflectionFieldBuilder *fb;
8237                 MonoClass *ec;
8238
8239                 g_assert (tb->fields != NULL);
8240                 g_assert (mono_array_length (tb->fields) >= 1);
8241
8242                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8243
8244                 klass->enum_basetype = fb->type->type;
8245                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8246                 if (!klass->element_class)
8247                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8248
8249                 /*
8250                  * get the element_class from the current corlib.
8251                  */
8252                 ec = default_class_from_mono_type (klass->enum_basetype);
8253                 klass->instance_size = ec->instance_size;
8254                 klass->size_inited = 1;
8255                 /* 
8256                  * this is almost safe to do with enums and it's needed to be able
8257                  * to create objects of the enum type (for use in SetConstant).
8258                  */
8259                 /* FIXME: Does this mean enums can't have method overrides ? */
8260                 mono_class_setup_vtable_general (klass, NULL, 0);
8261         }
8262         mono_loader_unlock ();
8263 }
8264
8265 static MonoMarshalSpec*
8266 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8267                                                                 MonoReflectionMarshal *minfo)
8268 {
8269         MonoMarshalSpec *res;
8270
8271         res = g_new0 (MonoMarshalSpec, 1);
8272         res->native = minfo->type;
8273
8274         switch (minfo->type) {
8275         case MONO_NATIVE_LPARRAY:
8276                 res->data.array_data.elem_type = minfo->eltype;
8277                 if (minfo->has_size) {
8278                         res->data.array_data.param_num = minfo->param_num;
8279                         res->data.array_data.num_elem = minfo->count;
8280                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8281                 }
8282                 else {
8283                         res->data.array_data.param_num = -1;
8284                         res->data.array_data.num_elem = -1;
8285                         res->data.array_data.elem_mult = -1;
8286                 }
8287                 break;
8288
8289         case MONO_NATIVE_BYVALTSTR:
8290         case MONO_NATIVE_BYVALARRAY:
8291                 res->data.array_data.num_elem = minfo->count;
8292                 break;
8293
8294         case MONO_NATIVE_CUSTOM:
8295                 if (minfo->marshaltyperef)
8296                         res->data.custom_data.custom_name =
8297                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8298                 if (minfo->mcookie)
8299                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8300                 break;
8301
8302         default:
8303                 break;
8304         }
8305
8306         return res;
8307 }
8308
8309 MonoReflectionMarshal*
8310 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8311                                                                                    MonoMarshalSpec *spec)
8312 {
8313         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8314         MonoReflectionMarshal *minfo;
8315         MonoType *mtype;
8316
8317         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8318                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8319                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8320                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8321         }
8322
8323         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8324         minfo->type = spec->native;
8325
8326         switch (minfo->type) {
8327         case MONO_NATIVE_LPARRAY:
8328                 minfo->eltype = spec->data.array_data.elem_type;
8329                 minfo->count = spec->data.array_data.num_elem;
8330                 minfo->param_num = spec->data.array_data.param_num;
8331                 break;
8332
8333         case MONO_NATIVE_BYVALTSTR:
8334         case MONO_NATIVE_BYVALARRAY:
8335                 minfo->count = spec->data.array_data.num_elem;
8336                 break;
8337
8338         case MONO_NATIVE_CUSTOM:
8339                 if (spec->data.custom_data.custom_name) {
8340                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8341                         if (mtype)
8342                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8343
8344                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8345                 }
8346                 if (spec->data.custom_data.cookie)
8347                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8348                 break;
8349
8350         default:
8351                 break;
8352         }
8353
8354         return minfo;
8355 }
8356
8357 static MonoMethod*
8358 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8359                                          ReflectionMethodBuilder *rmb,
8360                                          MonoMethodSignature *sig)
8361 {
8362         MonoMethod *m;
8363         MonoMethodNormal *pm;
8364         MonoMarshalSpec **specs;
8365         MonoReflectionMethodAux *method_aux;
8366         MonoMemPool *mp;
8367         gboolean dynamic;
8368         int i;
8369
8370         g_assert (!klass->generic_class);
8371
8372         /*
8373          * Methods created using a MethodBuilder should have their memory allocated
8374          * inside the image mempool, while dynamic methods should have their memory
8375          * malloc'd.
8376          */
8377         dynamic = rmb->refs != NULL;
8378         mp = dynamic ? NULL : klass->image->mempool;
8379
8380         mono_loader_lock ();
8381
8382         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8383                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8384                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8385         else if (rmb->refs)
8386                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8387         else
8388                 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8389
8390         pm = (MonoMethodNormal*)m;
8391
8392         m->slot = -1;
8393         m->flags = rmb->attrs;
8394         m->iflags = rmb->iattrs;
8395         m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8396         m->klass = klass;
8397         m->signature = sig;
8398         m->skip_visibility = rmb->skip_visibility;
8399         if (rmb->table_idx)
8400                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8401
8402         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8403                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8404                         m->string_ctor = 1;
8405
8406                 m->signature->pinvoke = 1;
8407         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8408                 m->signature->pinvoke = 1;
8409
8410                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8411
8412                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8413                 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8414                 
8415                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8416
8417                 if (klass->image->dynamic)
8418                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8419
8420                 mono_loader_unlock ();
8421
8422                 return m;
8423         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8424                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8425                 MonoMethodHeader *header;
8426                 guint32 code_size;
8427                 gint32 max_stack, i;
8428                 gint32 num_locals = 0;
8429                 gint32 num_clauses = 0;
8430                 guint8 *code;
8431
8432                 if (rmb->ilgen) {
8433                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8434                         code_size = rmb->ilgen->code_len;
8435                         max_stack = rmb->ilgen->max_stack;
8436                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8437                         if (rmb->ilgen->ex_handlers)
8438                                 num_clauses = method_count_clauses (rmb->ilgen);
8439                 } else {
8440                         if (rmb->code) {
8441                                 code = mono_array_addr (rmb->code, guint8, 0);
8442                                 code_size = mono_array_length (rmb->code);
8443                                 /* we probably need to run a verifier on the code... */
8444                                 max_stack = 8; 
8445                         }
8446                         else {
8447                                 code = NULL;
8448                                 code_size = 0;
8449                                 max_stack = 8;
8450                         }
8451                 }
8452
8453                 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) + 
8454                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8455                 header->code_size = code_size;
8456                 header->code = mp_g_malloc (mp, code_size);
8457                 memcpy ((char*)header->code, code, code_size);
8458                 header->max_stack = max_stack;
8459                 header->init_locals = rmb->init_locals;
8460                 header->num_locals = num_locals;
8461
8462                 for (i = 0; i < num_locals; ++i) {
8463                         MonoReflectionLocalBuilder *lb = 
8464                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8465
8466                         header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8467                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8468                 }
8469
8470                 header->num_clauses = num_clauses;
8471                 if (num_clauses) {
8472                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8473                                  rmb->ilgen, num_clauses);
8474                 }
8475
8476                 pm->header = header;
8477         }
8478
8479         if (rmb->generic_params) {
8480                 int count = mono_array_length (rmb->generic_params);
8481                 MonoGenericContainer *container;
8482                 MonoGenericContext *context;
8483
8484                 m->generic_container = container = rmb->generic_container;
8485                 container->type_argc = count;
8486                 container->type_params = g_new0 (MonoGenericParam, count);
8487
8488                 for (i = 0; i < count; i++) {
8489                         MonoReflectionGenericParam *gp =
8490                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8491
8492                         container->type_params [i] = *gp->type.type->data.generic_param;
8493                         container->type_params [i].method = m;
8494                 }
8495
8496                 context = &container->context;
8497                 context->container = container;
8498                 if (klass->generic_container) {
8499                         container->parent = klass->generic_container;
8500                         context->gclass = klass->generic_container->context.gclass;
8501                 }
8502                 context->gmethod = mono_get_shared_generic_method (container);
8503         }
8504
8505         if (rmb->refs) {
8506                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8507                 int i;
8508                 void **data;
8509
8510                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8511
8512                 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8513                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8514                 for (i = 0; i < rmb->nrefs; ++i)
8515                         data [i + 1] = rmb->refs [i];
8516         }
8517
8518         method_aux = NULL;
8519
8520         /* Parameter info */
8521         if (rmb->pinfo) {
8522                 if (!method_aux)
8523                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8524                 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8525                 for (i = 0; i <= m->signature->param_count; ++i) {
8526                         MonoReflectionParamBuilder *pb;
8527                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8528                                 if ((i > 0) && (pb->attrs)) {
8529                                         /* Make a copy since it might point to a shared type structure */
8530                                         /* FIXME: Alloc this from a mempool */
8531                                         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)));
8532                                         m->signature->params [i - 1]->attrs = pb->attrs;
8533                                 }
8534
8535                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8536                                         MonoDynamicImage *assembly;
8537                                         guint32 idx, def_type, len;
8538                                         char *p;
8539                                         const char *p2;
8540
8541                                         if (!method_aux->param_defaults) {
8542                                                 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8543                                                 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8544                                         }
8545                                         assembly = (MonoDynamicImage*)klass->image;
8546                                         idx = encode_constant (assembly, pb->def_value, &def_type);
8547                                         /* Copy the data from the blob since it might get realloc-ed */
8548                                         p = assembly->blob.data + idx;
8549                                         len = mono_metadata_decode_blob_size (p, &p2);
8550                                         len += p2 - p;
8551                                         method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8552                                         method_aux->param_default_types [i] = def_type;
8553                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8554                                 }
8555
8556                                 if (pb->name)
8557                                         method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8558                                 if (pb->cattrs) {
8559                                         if (!method_aux->param_cattr)
8560                                                 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8561                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8562                                 }
8563                         }
8564                 }
8565         }
8566
8567         /* Parameter marshalling */
8568         specs = NULL;
8569         if (rmb->pinfo)         
8570                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8571                         MonoReflectionParamBuilder *pb;
8572                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8573                                 if (pb->marshal_info) {
8574                                         if (specs == NULL)
8575                                                 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8576                                         specs [pb->position] = 
8577                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8578                                 }
8579                         }
8580                 }
8581         if (specs != NULL) {
8582                 if (!method_aux)
8583                         method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8584                 method_aux->param_marshall = specs;
8585         }
8586
8587         if (klass->image->dynamic && method_aux)
8588                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8589
8590         mono_loader_unlock ();
8591
8592         return m;
8593 }       
8594
8595 static MonoMethod*
8596 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8597 {
8598         ReflectionMethodBuilder rmb;
8599         MonoMethodSignature *sig;
8600
8601         mono_loader_lock ();
8602         sig = ctor_builder_to_signature (klass->image->mempool, mb);
8603         mono_loader_unlock ();
8604
8605         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8606
8607         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8608         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8609
8610         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8611                 /* ilgen is no longer needed */
8612                 mb->ilgen = NULL;
8613         }
8614
8615         return mb->mhandle;
8616 }
8617
8618 static MonoMethod*
8619 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8620 {
8621         ReflectionMethodBuilder rmb;
8622         MonoMethodSignature *sig;
8623
8624         mono_loader_lock ();
8625         sig = method_builder_to_signature (klass->image->mempool, mb);
8626         mono_loader_unlock ();
8627
8628         reflection_methodbuilder_from_method_builder (&rmb, mb);
8629
8630         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8631         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8632
8633         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8634                 /* ilgen is no longer needed */
8635                 mb->ilgen = NULL;
8636         }
8637         return mb->mhandle;
8638 }
8639
8640 static MonoClassField*
8641 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8642 {
8643         MonoClassField *field;
8644         const char *p, *p2;
8645         guint32 len, idx;
8646
8647         field = g_new0 (MonoClassField, 1);
8648
8649         field->name = mono_string_to_utf8 (fb->name);
8650         if (fb->attrs) {
8651                 /* FIXME: handle type modifiers */
8652                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8653                 field->type->attrs = fb->attrs;
8654         } else {
8655                 field->type = fb->type->type;
8656         }
8657         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8658                 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8659         if (fb->offset != -1)
8660                 field->offset = fb->offset;
8661         field->parent = klass;
8662         mono_save_custom_attrs (klass->image, field, fb->cattrs);
8663
8664         if (fb->def_value) {
8665                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8666                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8667                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8668                 /* Copy the data from the blob since it might get realloc-ed */
8669                 p = assembly->blob.data + idx;
8670                 len = mono_metadata_decode_blob_size (p, &p2);
8671                 len += p2 - p;
8672                 field->data = g_malloc (len);
8673                 memcpy ((gpointer)field->data, p, len);
8674         }
8675
8676         return field;
8677 }
8678
8679 MonoType*
8680 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8681 {
8682         MonoClass *klass;
8683         MonoReflectionTypeBuilder *tb = NULL;
8684         MonoGenericClass *gclass, *cached;
8685         MonoInflatedGenericClass *igclass;
8686         MonoDynamicGenericClass *dgclass = NULL;
8687         gboolean is_dynamic = FALSE;
8688         MonoDomain *domain;
8689         MonoType *geninst;
8690         int i;
8691
8692         klass = mono_class_from_mono_type (type->type);
8693         if (!klass->generic_container && !klass->generic_class &&
8694             !(klass->nested_in && klass->nested_in->generic_container))
8695                 return NULL;
8696
8697         mono_loader_lock ();
8698
8699         domain = mono_object_domain (type);
8700
8701         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8702                 tb = (MonoReflectionTypeBuilder *) type;
8703
8704                 is_dynamic = TRUE;
8705         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8706                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8707                 MonoReflectionType *rgt = rgi->generic_type;
8708
8709                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8710                 tb = (MonoReflectionTypeBuilder *) rgt;
8711
8712                 is_dynamic = TRUE;
8713         } else if (klass->wastypebuilder) {
8714                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8715
8716                 is_dynamic = TRUE;
8717         }
8718
8719         if (is_dynamic) {
8720                 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8721                 igclass = &dgclass->generic_class;
8722                 gclass = &igclass->generic_class;
8723                 gclass->is_dynamic = TRUE;
8724                 gclass->is_inflated = TRUE;
8725         } else {
8726                 igclass = g_new0 (MonoInflatedGenericClass, 1);
8727                 gclass = &igclass->generic_class;
8728                 gclass->is_inflated = TRUE;
8729         }
8730
8731         gclass->inst = g_new0 (MonoGenericInst, 1);
8732
8733         gclass->inst->type_argc = type_argc;
8734         gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8735         gclass->inst->is_reference = 1;
8736
8737         for (i = 0; i < gclass->inst->type_argc; ++i) {
8738                 MonoType *t = dup_type (types [i]);
8739
8740                 if (!gclass->inst->is_open)
8741                         gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8742                 if (gclass->inst->is_reference)
8743                         gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8744                 gclass->inst->type_argv [i] = t;
8745         }
8746
8747         gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8748
8749         gclass->container_class = klass;
8750
8751         if (klass->generic_class) {
8752                 MonoGenericClass *kgclass = klass->generic_class;
8753                 MonoGenericClass *ogclass = gclass;
8754
8755                 ogclass->context = g_new0 (MonoGenericContext, 1);
8756                 ogclass->context->container = gclass->container_class->generic_container;
8757                 ogclass->context->gclass = gclass;
8758
8759                 if (is_dynamic) {
8760                         dgclass = g_new0 (MonoDynamicGenericClass, 1);
8761                         igclass = &dgclass->generic_class;
8762                         gclass = &igclass->generic_class;
8763                         gclass->is_dynamic = TRUE;
8764                         gclass->is_inflated = TRUE;
8765                 } else {
8766                         igclass = g_new0 (MonoInflatedGenericClass, 1);
8767                         gclass = &igclass->generic_class;
8768                         gclass->is_inflated = TRUE;
8769                 }
8770
8771                 gclass->inst = g_new0 (MonoGenericInst, 1);
8772
8773                 gclass->inst->type_argc = kgclass->inst->type_argc;
8774                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8775                 gclass->inst->is_reference = 1;
8776
8777                 for (i = 0; i < gclass->inst->type_argc; i++) {
8778                         MonoType *t = kgclass->inst->type_argv [i];
8779
8780                         t = mono_class_inflate_generic_type (t, ogclass->context);
8781
8782                         if (!gclass->inst->is_open)
8783                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8784                         if (gclass->inst->is_reference)
8785                                 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8786
8787                         gclass->inst->type_argv [i] = t;
8788                 }
8789
8790                 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8791
8792                 gclass->container_class = kgclass->container_class;
8793         }
8794
8795         geninst = g_new0 (MonoType, 1);
8796         geninst->type = MONO_TYPE_GENERICINST;
8797
8798         cached = mono_metadata_lookup_generic_class (gclass);
8799         if (cached) {
8800                 g_free (gclass);
8801                 mono_loader_unlock ();
8802                 geninst->data.generic_class = cached;
8803                 return geninst;
8804         }
8805
8806         geninst->data.generic_class = gclass;
8807
8808         gclass->context = g_new0 (MonoGenericContext, 1);
8809         gclass->context->container = gclass->container_class->generic_container;
8810         gclass->context->gclass = gclass;
8811
8812         mono_loader_unlock ();
8813
8814         return geninst;
8815 }
8816
8817 MonoType*
8818 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8819 {
8820         MonoClass *klass;
8821         MonoGenericClass *gclass, *cached;
8822         MonoInflatedGenericClass *igclass;
8823         MonoType *geninst;
8824         int i;
8825
8826         klass = mono_class_from_mono_type (type);
8827         if (!klass->generic_container && !klass->generic_class &&
8828             !(klass->nested_in && klass->nested_in->generic_container))
8829                 return NULL;
8830
8831         mono_loader_lock ();
8832
8833         igclass = g_new0 (MonoInflatedGenericClass, 1);
8834         gclass = &igclass->generic_class;
8835         gclass->is_inflated = TRUE;
8836
8837         gclass->inst = g_new0 (MonoGenericInst, 1);
8838         gclass->inst->type_argc = type_argc;
8839         gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8840         gclass->inst->is_reference = 1;
8841
8842         for (i = 0; i < gclass->inst->type_argc; ++i) {
8843                 MonoType *t = dup_type (types [i]);
8844
8845                 if (!gclass->inst->is_open)
8846                         gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8847                 if (gclass->inst->is_reference)
8848                         gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8849
8850                 gclass->inst->type_argv [i] = t;
8851         }
8852
8853         gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8854
8855         gclass->container_class = klass;
8856
8857         if (klass->generic_class) {
8858                 MonoGenericClass *kgclass = klass->generic_class;
8859                 MonoGenericClass *ogclass = gclass;
8860
8861                 gclass->context = g_new0 (MonoGenericContext, 1);
8862                 gclass->context->container = gclass->container_class->generic_container;
8863                 gclass->context->gclass = gclass;
8864
8865                 igclass = g_new0 (MonoInflatedGenericClass, 1);
8866                 gclass = &igclass->generic_class;
8867                 gclass->is_inflated = TRUE;
8868
8869                 gclass->inst = g_new0 (MonoGenericInst, 1);
8870                 gclass->inst->type_argc = kgclass->inst->type_argc;
8871                 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8872                 gclass->inst->is_reference = 1;
8873
8874                 for (i = 0; i < gclass->inst->type_argc; i++) {
8875                         MonoType *t = kgclass->inst->type_argv [i];
8876
8877                         t = mono_class_inflate_generic_type (t, ogclass->context);
8878
8879                         if (!gclass->inst->is_open)
8880                                 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8881                         if (gclass->inst->is_reference)
8882                                 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8883
8884                         gclass->inst->type_argv [i] = t;
8885                 }
8886
8887                 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8888
8889                 gclass->container_class = kgclass->container_class;
8890         }
8891
8892         geninst = g_new0 (MonoType, 1);
8893         geninst->type = MONO_TYPE_GENERICINST;
8894
8895         cached = mono_metadata_lookup_generic_class (gclass);
8896         if (cached) {
8897                 g_free (gclass);
8898                 mono_loader_unlock ();
8899                 geninst->data.generic_class = cached;
8900                 return geninst;
8901         }
8902
8903         geninst->data.generic_class = gclass;
8904
8905         gclass->context = g_new0 (MonoGenericContext, 1);
8906         gclass->context->container = gclass->container_class->generic_container;
8907         gclass->context->gclass = gclass;
8908
8909         mono_loader_unlock ();
8910
8911         return geninst;
8912 }
8913
8914 static inline MonoType*
8915 dup_type (const MonoType *original)
8916 {
8917         MonoType *r = g_new0 (MonoType, 1);
8918         *r = *original;
8919         r->attrs = original->attrs;
8920         r->byref = original->byref;
8921         if (original->type == MONO_TYPE_PTR)
8922                 r->data.type = dup_type (original->data.type);
8923         else if (original->type == MONO_TYPE_ARRAY)
8924                 r->data.array = mono_dup_array_type (original->data.array);
8925         else if (original->type == MONO_TYPE_FNPTR)
8926                 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8927         mono_stats.generics_metadata_size += sizeof (MonoType);
8928         return r;
8929 }
8930
8931 MonoReflectionMethod*
8932 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8933 {
8934         MonoMethod *method, *inflated;
8935         MonoReflectionMethodBuilder *mb = NULL;
8936         MonoGenericContainer *container;
8937         MonoGenericMethod *gmethod;
8938         MonoGenericContext *context;
8939         MonoGenericInst *ginst;
8940         int count, i;
8941
8942         MONO_ARCH_SAVE_REGS;
8943         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8944                 MonoReflectionTypeBuilder *tb;
8945                 MonoClass *klass;
8946
8947                 mb = (MonoReflectionMethodBuilder *) rmethod;
8948                 tb = (MonoReflectionTypeBuilder *) mb->type;
8949                 klass = mono_class_from_mono_type (tb->type.type);
8950
8951                 method = methodbuilder_to_mono_method (klass, mb);
8952         } else {
8953                 method = rmethod->method;
8954         }
8955
8956         method = mono_get_inflated_method (method);
8957
8958         count = mono_method_signature (method)->generic_param_count;
8959         if (count != mono_array_length (types))
8960                 return NULL;
8961
8962         container = method->generic_container;
8963         g_assert (container);
8964
8965         if (!container->method_hash)
8966                 container->method_hash = g_hash_table_new (
8967                         (GHashFunc) mono_metadata_generic_method_hash,
8968                         (GCompareFunc) mono_metadata_generic_method_equal);
8969
8970         ginst = g_new0 (MonoGenericInst,1 );
8971         ginst->type_argc = count;
8972         ginst->type_argv = g_new0 (MonoType *, count);
8973         ginst->is_reference = 1;
8974         for (i = 0; i < count; i++) {
8975                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8976                 ginst->type_argv [i] = dup_type (garg->type);
8977
8978                 if (!ginst->is_open)
8979                         ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8980                 if (ginst->is_reference)
8981                         ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8982         }
8983         ginst = mono_metadata_lookup_generic_inst (ginst);
8984
8985         gmethod = g_new0 (MonoGenericMethod, 1);
8986         gmethod->generic_class = method->klass->generic_class;
8987         gmethod->container = container;
8988         gmethod->inst = ginst;
8989
8990         inflated = g_hash_table_lookup (container->method_hash, gmethod);
8991         if (inflated) {
8992                 g_free (gmethod);
8993
8994                 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8995         }
8996
8997         gmethod->reflection_info = rmethod;
8998
8999         context = g_new0 (MonoGenericContext, 1);
9000         context->container = container;
9001         context->gclass = method->klass->generic_class;
9002         context->gmethod = gmethod;
9003
9004         if (method->is_inflated)
9005                 method = ((MonoMethodInflated *) method)->declaring;
9006
9007         inflated = mono_class_inflate_generic_method (method, context);
9008         g_hash_table_insert (container->method_hash, gmethod, inflated);
9009
9010         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9011 }
9012
9013 static MonoMethod *
9014 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
9015 {
9016         MonoGenericMethod *gmethod = NULL;
9017         MonoInflatedGenericClass *gclass;
9018         MonoGenericContext *context;
9019         MonoClass *klass;
9020         int i, n;
9021
9022         klass = mono_class_from_mono_type (type->type.type);
9023         gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
9024         n = mono_method_signature (method)->generic_param_count;
9025
9026         context = gclass->generic_class.context;
9027         g_assert (context && context->container);
9028         if (n) {
9029                 gmethod = g_new0 (MonoGenericMethod, 1);
9030                 gmethod->generic_class = &gclass->generic_class;
9031                 gmethod->container = method->generic_container;
9032                 gmethod->reflection_info = obj;
9033
9034                 gmethod->inst = g_new0 (MonoGenericInst, 1);
9035                 gmethod->inst->type_argc = n;
9036                 gmethod->inst->type_argv = g_new0 (MonoType *, n);
9037
9038                 for (i = 0; i < n; i++) {
9039                         MonoGenericParam *gparam = &method->generic_container->type_params [i];
9040                         g_assert (gparam->pklass);
9041                         gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
9042                 }
9043
9044                 g_assert (gmethod->container->parent == context->container);
9045
9046                 context = g_new0 (MonoGenericContext, 1);
9047                 context->container = gmethod->container;
9048                 context->gclass = &gclass->generic_class;
9049                 context->gmethod = gmethod;
9050         }
9051
9052         return mono_class_inflate_generic_method (method, context);
9053 }
9054
9055 static MonoMethod *
9056 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9057 {
9058         MonoMethod *method;
9059         MonoClass *gklass;
9060
9061         gklass = mono_class_from_mono_type (type->generic_type->type);
9062
9063         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9064                 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9065         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9066                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9067         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9068                 method = ((MonoReflectionMethod *) obj)->method;
9069         else {
9070                 method = NULL; /* prevent compiler warning */
9071                 g_assert_not_reached ();
9072         }
9073
9074         return inflate_mono_method (type, method, obj);
9075 }
9076
9077 void
9078 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
9079                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9080                                           MonoArray *events)
9081 {
9082         MonoGenericClass *gclass;
9083         MonoDynamicGenericClass *dgclass;
9084         MonoClass *klass, *gklass;
9085         int i;
9086
9087         MONO_ARCH_SAVE_REGS;
9088
9089         klass = mono_class_from_mono_type (type->type.type);
9090         gclass = type->type.type->data.generic_class;
9091
9092         g_assert (gclass->is_dynamic);
9093         dgclass = (MonoDynamicGenericClass *) gclass;
9094
9095         if (dgclass->initialized)
9096                 return;
9097
9098         gklass = gclass->container_class;
9099         mono_class_init (gklass);
9100
9101         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9102         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9103         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9104         dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9105         dgclass->count_events = events ? mono_array_length (events) : 0;
9106
9107         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9108         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9109         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9110         dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9111         dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9112
9113         for (i = 0; i < dgclass->count_methods; i++) {
9114                 MonoObject *obj = mono_array_get (methods, gpointer, i);
9115
9116                 dgclass->methods [i] = inflate_method (type, obj);
9117         }
9118
9119         for (i = 0; i < dgclass->count_ctors; i++) {
9120                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9121
9122                 dgclass->ctors [i] = inflate_method (type, obj);
9123         }
9124
9125         for (i = 0; i < dgclass->count_fields; i++) {
9126                 MonoObject *obj = mono_array_get (fields, gpointer, i);
9127                 MonoClassField *field;
9128                 MonoInflatedField *ifield;
9129
9130                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9131                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9132                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9133                         field = ((MonoReflectionField *) obj)->field;
9134                 else {
9135                         field = NULL; /* prevent compiler warning */
9136                         g_assert_not_reached ();
9137                 }
9138
9139                 ifield = g_new0 (MonoInflatedField, 1);
9140                 ifield->generic_type = field->type;
9141                 ifield->reflection_info = obj;
9142
9143                 dgclass->fields [i] = *field;
9144                 dgclass->fields [i].parent = klass;
9145                 dgclass->fields [i].generic_info = ifield;
9146                 dgclass->fields [i].type = mono_class_inflate_generic_type (
9147                         field->type, dgclass->generic_class.generic_class.context);
9148         }
9149
9150         for (i = 0; i < dgclass->count_properties; i++) {
9151                 MonoObject *obj = mono_array_get (properties, gpointer, i);
9152                 MonoProperty *property = &dgclass->properties [i];
9153
9154                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9155                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9156
9157                         property->parent = klass;
9158                         property->attrs = pb->attrs;
9159                         property->name = mono_string_to_utf8 (pb->name);
9160                         if (pb->get_method)
9161                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9162                         if (pb->set_method)
9163                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9164                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9165                         *property = *((MonoReflectionProperty *) obj)->property;
9166
9167                         if (property->get)
9168                                 property->get = inflate_mono_method (type, property->get, NULL);
9169                         if (property->set)
9170                                 property->set = inflate_mono_method (type, property->set, NULL);
9171                 } else
9172                         g_assert_not_reached ();
9173         }
9174
9175         for (i = 0; i < dgclass->count_events; i++) {
9176                 MonoObject *obj = mono_array_get (events, gpointer, i);
9177                 MonoEvent *event = &dgclass->events [i];
9178
9179                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9180                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9181
9182                         event->parent = klass;
9183                         event->attrs = eb->attrs;
9184                         event->name = mono_string_to_utf8 (eb->name);
9185                         if (eb->add_method)
9186                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9187                         if (eb->remove_method)
9188                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9189                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9190                         *event = *((MonoReflectionEvent *) obj)->event;
9191
9192                         if (event->add)
9193                                 event->add = inflate_mono_method (type, event->add, NULL);
9194                         if (event->remove)
9195                                 event->remove = inflate_mono_method (type, event->remove, NULL);
9196                 } else
9197                         g_assert_not_reached ();
9198         }
9199
9200         dgclass->initialized = TRUE;
9201 }
9202
9203 static void
9204 ensure_runtime_vtable (MonoClass *klass)
9205 {
9206         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9207         int i, num, j;
9208
9209         if (!tb || klass->wastypebuilder)
9210                 return;
9211         if (klass->parent)
9212                 ensure_runtime_vtable (klass->parent);
9213
9214         num = tb->ctors? mono_array_length (tb->ctors): 0;
9215         num += tb->num_methods;
9216         klass->method.count = num;
9217         klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9218         num = tb->ctors? mono_array_length (tb->ctors): 0;
9219         for (i = 0; i < num; ++i)
9220                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9221         num = tb->num_methods;
9222         j = i;
9223         for (i = 0; i < num; ++i)
9224                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9225
9226         if (tb->interfaces) {
9227                 klass->interface_count = mono_array_length (tb->interfaces);
9228                 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9229                 for (i = 0; i < klass->interface_count; ++i) {
9230                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9231                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9232                 }
9233         }
9234
9235         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9236                 for (i = 0; i < klass->method.count; ++i)
9237                         klass->methods [i]->slot = i;
9238                 
9239                 mono_class_setup_interface_offsets (klass);
9240         }
9241
9242         /*
9243          * The generic vtable is needed even if image->run is not set since some
9244          * runtime code like ves_icall_Type_GetMethodsByName depends on 
9245          * method->slot being defined.
9246          */
9247
9248         /* 
9249          * tb->methods could not be freed since it is used for determining 
9250          * overrides during dynamic vtable construction.
9251          */
9252 }
9253
9254 void
9255 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9256 {
9257         MonoReflectionTypeBuilder *tb;
9258         int i, onum;
9259
9260         *overrides = NULL;
9261         *num_overrides = 0;
9262
9263         g_assert (klass->image->dynamic);
9264
9265         if (!klass->reflection_info)
9266                 return;
9267
9268         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9269
9270         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9271
9272         onum = 0;
9273         if (tb->methods) {
9274                 for (i = 0; i < tb->num_methods; ++i) {
9275                         MonoReflectionMethodBuilder *mb = 
9276                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9277                         if (mb->override_method)
9278                                 onum ++;
9279                 }
9280         }
9281
9282         if (onum) {
9283                 *overrides = g_new0 (MonoMethod*, onum * 2);
9284
9285                 onum = 0;
9286                 for (i = 0; i < tb->num_methods; ++i) {
9287                         MonoReflectionMethodBuilder *mb = 
9288                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9289                         if (mb->override_method) {
9290                                 (*overrides) [onum * 2] = 
9291                                         mb->override_method->method;
9292                                 (*overrides) [onum * 2 + 1] =
9293                                         mb->mhandle;
9294
9295                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9296                                 g_assert (mb->override_method->method);
9297                                 g_assert (mb->mhandle);
9298
9299                                 onum ++;
9300                         }
9301                 }
9302         }
9303
9304         *num_overrides = onum;
9305 }
9306
9307 static void
9308 typebuilder_setup_fields (MonoClass *klass)
9309 {
9310         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9311         MonoReflectionFieldBuilder *fb;
9312         MonoClassField *field;
9313         const char *p, *p2;
9314         int i;
9315         guint32 len, idx;
9316
9317         klass->field.count = tb->num_fields;
9318         klass->field.first = 0;
9319
9320         if (!klass->field.count)
9321                 return;
9322         
9323         klass->fields = g_new0 (MonoClassField, klass->field.count);
9324
9325         for (i = 0; i < klass->field.count; ++i) {
9326                 fb = mono_array_get (tb->fields, gpointer, i);
9327                 field = &klass->fields [i];
9328                 field->name = mono_string_to_utf8 (fb->name);
9329                 if (fb->attrs) {
9330                         /* FIXME: handle type modifiers */
9331                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
9332                         field->type->attrs = fb->attrs;
9333                 } else {
9334                         field->type = fb->type->type;
9335                 }
9336                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9337                         field->data = mono_array_addr (fb->rva_data, char, 0);
9338                 if (fb->offset != -1)
9339                         field->offset = fb->offset;
9340                 field->parent = klass;
9341                 fb->handle = field;
9342                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9343
9344                 if (fb->def_value) {
9345                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9346                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9347                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
9348                         /* Copy the data from the blob since it might get realloc-ed */
9349                         p = assembly->blob.data + idx;
9350                         len = mono_metadata_decode_blob_size (p, &p2);
9351                         len += p2 - p;
9352                         field->data = g_malloc (len);
9353                         memcpy ((gpointer)field->data, p, len);
9354                 }
9355         }
9356         mono_class_layout_fields (klass);
9357 }
9358
9359 static void
9360 typebuilder_setup_properties (MonoClass *klass)
9361 {
9362         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9363         MonoReflectionPropertyBuilder *pb;
9364         int i;
9365
9366         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9367         klass->property.first = 0;
9368
9369         klass->properties = g_new0 (MonoProperty, klass->property.count);
9370         for (i = 0; i < klass->property.count; ++i) {
9371                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9372                 klass->properties [i].parent = klass;
9373                 klass->properties [i].attrs = pb->attrs;
9374                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9375                 if (pb->get_method)
9376                         klass->properties [i].get = pb->get_method->mhandle;
9377                 if (pb->set_method)
9378                         klass->properties [i].set = pb->set_method->mhandle;
9379
9380                 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9381         }
9382 }
9383
9384 MonoReflectionEvent *
9385 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9386 {
9387         MonoEvent *event = g_new0 (MonoEvent, 1);
9388         MonoClass *klass;
9389         int j;
9390
9391         klass = my_mono_class_from_mono_type (tb->type.type);
9392
9393         event->parent = klass;
9394         event->attrs = eb->attrs;
9395         event->name = mono_string_to_utf8 (eb->name);
9396         if (eb->add_method)
9397                 event->add = eb->add_method->mhandle;
9398         if (eb->remove_method)
9399                 event->remove = eb->remove_method->mhandle;
9400         if (eb->raise_method)
9401                 event->raise = eb->raise_method->mhandle;
9402
9403         if (eb->other_methods) {
9404                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9405                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9406                         MonoReflectionMethodBuilder *mb = 
9407                                 mono_array_get (eb->other_methods,
9408                                                 MonoReflectionMethodBuilder*, j);
9409                         event->other [j] = mb->mhandle;
9410                 }
9411         }
9412
9413         return mono_event_get_object (mono_object_domain (tb), klass, event);
9414 }
9415
9416 static void
9417 typebuilder_setup_events (MonoClass *klass)
9418 {
9419         MonoReflectionTypeBuilder *tb = klass->reflection_info;
9420         MonoReflectionEventBuilder *eb;
9421         int i, j;
9422
9423         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9424         klass->event.first = 0;
9425
9426         klass->events = g_new0 (MonoEvent, klass->event.count);
9427         for (i = 0; i < klass->event.count; ++i) {
9428                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9429                 klass->events [i].parent = klass;
9430                 klass->events [i].attrs = eb->attrs;
9431                 klass->events [i].name = mono_string_to_utf8 (eb->name);
9432                 if (eb->add_method)
9433                         klass->events [i].add = eb->add_method->mhandle;
9434                 if (eb->remove_method)
9435                         klass->events [i].remove = eb->remove_method->mhandle;
9436                 if (eb->raise_method)
9437                         klass->events [i].raise = eb->raise_method->mhandle;
9438
9439                 if (eb->other_methods) {
9440                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9441                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9442                                 MonoReflectionMethodBuilder *mb = 
9443                                         mono_array_get (eb->other_methods,
9444                                                                         MonoReflectionMethodBuilder*, j);
9445                                 klass->events [i].other [j] = mb->mhandle;
9446                         }
9447                 }
9448         }
9449 }
9450
9451 MonoReflectionType*
9452 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9453 {
9454         MonoClass *klass;
9455         MonoDomain* domain;
9456         MonoReflectionType* res;
9457         int i;
9458
9459         MONO_ARCH_SAVE_REGS;
9460
9461         domain = mono_object_domain (tb);
9462         klass = my_mono_class_from_mono_type (tb->type.type);
9463
9464         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9465         
9466         /* 
9467          * we need to lock the domain because the lock will be taken inside
9468          * So, we need to keep the locking order correct.
9469          */
9470         mono_domain_lock (domain);
9471         mono_loader_lock ();
9472         if (klass->wastypebuilder) {
9473                 mono_loader_unlock ();
9474                 mono_domain_unlock (domain);
9475                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9476         }
9477         /*
9478          * Fields to set in klass:
9479          * the various flags: delegate/unicode/contextbound etc.
9480          */
9481         klass->flags = tb->attrs;
9482         klass->has_cctor = 1;
9483         klass->has_finalize = 1;
9484
9485 #if 0
9486         if (!((MonoDynamicImage*)klass->image)->run) {
9487                 if (klass->generic_container) {
9488                         /* FIXME: The code below can't handle generic classes */
9489                         klass->wastypebuilder = TRUE;
9490                         mono_loader_unlock ();
9491                         mono_domain_unlock (domain);
9492                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9493                 }
9494         }
9495 #endif
9496
9497         /* enums are done right away */
9498         if (!klass->enumtype)
9499                 ensure_runtime_vtable (klass);
9500
9501         if (tb->subtypes) {
9502                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9503                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9504                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9505                 }
9506         }
9507
9508         /* fields and object layout */
9509         if (klass->parent) {
9510                 if (!klass->parent->size_inited)
9511                         mono_class_init (klass->parent);
9512                 klass->instance_size = klass->parent->instance_size;
9513                 klass->sizes.class_size = 0;
9514                 klass->min_align = klass->parent->min_align;
9515                 /* if the type has no fields we won't call the field_setup
9516                  * routine which sets up klass->has_references.
9517                  */
9518                 klass->has_references |= klass->parent->has_references;
9519         } else {
9520                 klass->instance_size = sizeof (MonoObject);
9521                 klass->min_align = 1;
9522         }
9523
9524         /* FIXME: handle packing_size and instance_size */
9525         typebuilder_setup_fields (klass);
9526
9527         typebuilder_setup_properties (klass);
9528
9529         typebuilder_setup_events (klass);
9530
9531         klass->wastypebuilder = TRUE;
9532         mono_loader_unlock ();
9533         mono_domain_unlock (domain);
9534
9535         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9536         g_assert (res != (MonoReflectionType*)tb);
9537
9538         return res;
9539 }
9540
9541 void
9542 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9543 {
9544         MonoGenericParam *param;
9545         MonoImage *image;
9546
9547         MONO_ARCH_SAVE_REGS;
9548
9549         param = g_new0 (MonoGenericParam, 1);
9550
9551         if (gparam->mbuilder) {
9552                 if (!gparam->mbuilder->generic_container)
9553                         gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9554                 param->owner = gparam->mbuilder->generic_container;
9555         } else if (gparam->tbuilder) {
9556                 g_assert (gparam->tbuilder->generic_container);
9557                 param->owner = gparam->tbuilder->generic_container;
9558         }
9559
9560         param->method = NULL;
9561         param->name = mono_string_to_utf8 (gparam->name);
9562         param->num = gparam->index;
9563
9564         image = &gparam->tbuilder->module->dynamic_image->image;
9565         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9566
9567         param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9568
9569         gparam->type.type = g_new0 (MonoType, 1);
9570         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9571         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9572         gparam->type.type->data.generic_param = param;
9573 }
9574
9575 MonoArray *
9576 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9577 {
9578         MonoDynamicImage *assembly = sig->module->dynamic_image;
9579         guint32 na = mono_array_length (sig->arguments);
9580         guint32 buflen, i, size;
9581         MonoArray *result;
9582         char *buf, *p;
9583
9584         MONO_ARCH_SAVE_REGS;
9585
9586         p = buf = g_malloc (size = 50 + na * 50);
9587
9588         mono_metadata_encode_value (0x07, p, &p);
9589         mono_metadata_encode_value (na, p, &p);
9590         for (i = 0; i < na; ++i) {
9591                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9592                 encode_reflection_type (assembly, type, p, &p);
9593         }
9594
9595         buflen = p - buf;
9596         g_assert (buflen < size);
9597         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9598         p = mono_array_addr (result, char, 0);
9599         memcpy (p, buf, buflen);
9600         g_free (buf);
9601
9602         return result;
9603 }
9604
9605 MonoArray *
9606 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9607 {
9608         MonoDynamicImage *assembly = sig->module->dynamic_image;
9609         guint32 na = mono_array_length (sig->arguments);
9610         guint32 buflen, i, size;
9611         MonoArray *result;
9612         char *buf, *p;
9613
9614         MONO_ARCH_SAVE_REGS;
9615
9616         p = buf = g_malloc (size = 10 + na * 10);
9617
9618         mono_metadata_encode_value (0x06, p, &p);
9619         for (i = 0; i < na; ++i) {
9620                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9621                 encode_reflection_type (assembly, type, p, &p);
9622         }
9623
9624         buflen = p - buf;
9625         g_assert (buflen < size);
9626         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9627         p = mono_array_addr (result, char, 0);
9628         memcpy (p, buf, buflen);
9629         g_free (buf);
9630
9631         return result;
9632 }
9633
9634 void 
9635 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9636 {
9637         ReflectionMethodBuilder rmb;
9638         MonoMethodSignature *sig;
9639         int i;
9640
9641         sig = dynamic_method_to_signature (mb);
9642
9643         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9644
9645         /*
9646          * Resolve references.
9647          */
9648         /* 
9649          * Every second entry in the refs array is reserved for storing handle_class,
9650          * which is needed by the ldtoken implementation in the JIT.
9651          */
9652         rmb.nrefs = mb->nrefs;
9653         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9654         for (i = 0; i < mb->nrefs; i += 2) {
9655                 MonoClass *handle_class;
9656                 gpointer ref = resolve_object (mb->module->image, 
9657                                                mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9658                 if (!ref) {
9659                         g_free (rmb.refs);
9660                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9661                         return;
9662                 }
9663                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9664                 rmb.refs [i + 1] = handle_class;
9665         }               
9666
9667         /* FIXME: class */
9668         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9669
9670         g_free (rmb.refs);
9671
9672         /* ilgen is no longer needed */
9673         mb->ilgen = NULL;
9674 }
9675
9676 /**
9677  * mono_reflection_lookup_dynamic_token:
9678  *
9679  * Finish the Builder object pointed to by TOKEN and return the corresponding
9680  * runtime structure. HANDLE_CLASS is set to the class required by 
9681  * mono_ldtoken.
9682  */
9683 gpointer
9684 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9685 {
9686         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9687         MonoObject *obj;
9688
9689         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9690         g_assert (obj);
9691
9692         return resolve_object (image, obj, handle_class);
9693 }
9694
9695 static gpointer
9696 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9697 {
9698         gpointer result = NULL;
9699
9700         if (strcmp (obj->vtable->klass->name, "String") == 0) {
9701                 result = mono_string_intern ((MonoString*)obj);
9702                 *handle_class = NULL;
9703                 g_assert (result);
9704         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9705                 MonoReflectionType *tb = (MonoReflectionType*)obj;
9706                 result = mono_class_from_mono_type (tb->type);
9707                 *handle_class = mono_defaults.typehandle_class;
9708                 g_assert (result);
9709         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9710                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9711                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9712                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9713                 result = ((MonoReflectionMethod*)obj)->method;
9714                 *handle_class = mono_defaults.methodhandle_class;
9715                 g_assert (result);
9716         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9717                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9718                 result = mb->mhandle;
9719                 if (!result) {
9720                         /* Type is not yet created */
9721                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9722
9723                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9724
9725                         /*
9726                          * Hopefully this has been filled in by calling CreateType() on the
9727                          * TypeBuilder.
9728                          */
9729                         /*
9730                          * TODO: This won't work if the application finishes another 
9731                          * TypeBuilder instance instead of this one.
9732                          */
9733                         result = mb->mhandle;
9734                 }
9735                 *handle_class = mono_defaults.methodhandle_class;
9736         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9737                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9738
9739                 result = cb->mhandle;
9740                 if (!result) {
9741                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9742
9743                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9744                         result = cb->mhandle;
9745                 }
9746                 *handle_class = mono_defaults.methodhandle_class;
9747         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9748                 result = ((MonoReflectionField*)obj)->field;
9749                 *handle_class = mono_defaults.fieldhandle_class;
9750                 g_assert (result);
9751         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9752                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9753                 result = fb->handle;
9754
9755                 if (!result) {
9756                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9757
9758                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9759                         result = fb->handle;
9760                 }
9761                 *handle_class = mono_defaults.fieldhandle_class;
9762         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9763                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9764                 MonoClass *klass;
9765
9766                 klass = tb->type.type->data.klass;
9767                 if (klass->wastypebuilder) {
9768                         /* Already created */
9769                         result = klass;
9770                 }
9771                 else {
9772                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9773                         result = tb->type.type->data.klass;
9774                         g_assert (result);
9775                 }
9776                 *handle_class = mono_defaults.typehandle_class;
9777         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9778                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9779                 MonoMethodSignature *sig;
9780                 int nargs, i;
9781
9782                 if (helper->arguments)
9783                         nargs = mono_array_length (helper->arguments);
9784                 else
9785                         nargs = 0;
9786
9787                 sig = mono_metadata_signature_alloc (image, nargs);
9788                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9789                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9790
9791                 if (helper->call_conv == 0) /* unmanaged */
9792                         sig->call_convention = helper->unmanaged_call_conv - 1;
9793                 else
9794                         if (helper->call_conv & 0x02)
9795                                 sig->call_convention = MONO_CALL_VARARG;
9796                 else
9797                         sig->call_convention = MONO_CALL_DEFAULT;
9798
9799                 sig->param_count = nargs;
9800                 /* TODO: Copy type ? */
9801                 sig->ret = helper->return_type->type;
9802                 for (i = 0; i < nargs; ++i) {
9803                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9804                         sig->params [i] = rt->type;
9805                 }
9806
9807                 result = sig;
9808                 *handle_class = NULL;
9809         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9810                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9811                 /* Already created by the managed code */
9812                 g_assert (method->mhandle);
9813                 result = method->mhandle;
9814                 *handle_class = mono_defaults.methodhandle_class;
9815         } else {
9816                 g_print (obj->vtable->klass->name);
9817                 g_assert_not_reached ();
9818         }
9819         return result;
9820 }
9821
9822
9823 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9824 const static guint32 declsec_flags_map[] = {
9825         0x00000000,                                     /* empty */
9826         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
9827         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
9828         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
9829         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
9830         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
9831         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
9832         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
9833         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
9834         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
9835         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
9836         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
9837         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
9838         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
9839         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
9840         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
9841         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
9842         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
9843         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
9844 };
9845
9846 /*
9847  * Returns flags that includes all available security action associated to the handle.
9848  * @token: metadata token (either for a class or a method)
9849  * @image: image where resides the metadata.
9850  */
9851 static guint32
9852 mono_declsec_get_flags (MonoImage *image, guint32 token)
9853 {
9854         guint32 index = mono_metadata_declsec_from_index (image, token);
9855         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9856         guint32 result = 0;
9857         guint32 action;
9858         int i;
9859
9860         for (i = index; i < t->rows; i++) {
9861                 guint32 cols [MONO_DECL_SECURITY_SIZE];
9862
9863                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9864                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9865                         break;
9866
9867                 action = cols [MONO_DECL_SECURITY_ACTION];
9868                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9869                         result |= declsec_flags_map [action];
9870                 } else {
9871                         g_assert_not_reached ();
9872                 }
9873         }
9874         return result;
9875 }
9876
9877 /*
9878  * Get the security actions (in the form of flags) associated with the specified method.
9879  *
9880  * @method: The method for which we want the declarative security flags.
9881  * Return the declarative security flags for the method (only).
9882  *
9883  * Note: To keep MonoMethod size down we do not cache the declarative security flags
9884  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
9885  */
9886 guint32
9887 mono_declsec_flags_from_method (MonoMethod *method)
9888 {
9889         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9890                 /* FIXME: No cache (for the moment) */
9891                 guint32 idx = mono_method_get_index (method);
9892                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9893                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9894                 return mono_declsec_get_flags (method->klass->image, idx);
9895         }
9896         return 0;
9897 }
9898
9899 /*
9900  * Get the security actions (in the form of flags) associated with the specified class.
9901  *
9902  * @klass: The class for which we want the declarative security flags.
9903  * Return the declarative security flags for the class.
9904  *
9905  * Note: We cache the flags inside the MonoClass structure as this will get 
9906  *       called very often (at least for each method).
9907  */
9908 guint32
9909 mono_declsec_flags_from_class (MonoClass *klass)
9910 {
9911         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9912                 if (!klass->declsec_flags) {
9913                         guint32 idx = mono_metadata_token_index (klass->type_token);
9914                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9915                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9916                         /* we cache the flags on classes */
9917                         klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9918                 }
9919                 return klass->declsec_flags;
9920         }
9921         return 0;
9922 }
9923
9924 /*
9925  * Get the security actions (in the form of flags) associated with the specified assembly.
9926  *
9927  * @assembly: The assembly for which we want the declarative security flags.
9928  * Return the declarative security flags for the assembly.
9929  */
9930 guint32
9931 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9932 {
9933         guint32 idx = 1; /* there is only one assembly */
9934         idx <<= MONO_HAS_DECL_SECURITY_BITS;
9935         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9936         return mono_declsec_get_flags (assembly->image, idx);
9937 }
9938
9939
9940 /*
9941  * Fill actions for the specific index (which may either be an encoded class token or
9942  * an encoded method token) from the metadata image.
9943  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9944  */
9945 static MonoBoolean
9946 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9947         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9948 {
9949         MonoBoolean result = FALSE;
9950         MonoTableInfo *t;
9951         guint32 cols [MONO_DECL_SECURITY_SIZE];
9952         int index = mono_metadata_declsec_from_index (image, token);
9953         int i;
9954
9955         t  = &image->tables [MONO_TABLE_DECLSECURITY];
9956         for (i = index; i < t->rows; i++) {
9957                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9958
9959                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9960                         return result;
9961
9962                 /* if present only replace (class) permissions with method permissions */
9963                 /* if empty accept either class or method permissions */
9964                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9965                         if (!actions->demand.blob) {
9966                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9967                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9968                                 actions->demand.blob = (char*) (blob + 2);
9969                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9970                                 result = TRUE;
9971                         }
9972                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9973                         if (!actions->noncasdemand.blob) {
9974                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9975                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9976                                 actions->noncasdemand.blob = (char*) (blob + 2);
9977                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9978                                 result = TRUE;
9979                         }
9980                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9981                         if (!actions->demandchoice.blob) {
9982                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9983                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9984                                 actions->demandchoice.blob = (char*) (blob + 2);
9985                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9986                                 result = TRUE;
9987                         }
9988                 }
9989         }
9990
9991         return result;
9992 }
9993
9994 static MonoBoolean
9995 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
9996         guint32 id_std, guint32 id_noncas, guint32 id_choice)
9997 {
9998         guint32 idx = mono_metadata_token_index (klass->type_token);
9999         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10000         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10001         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10002 }
10003
10004 static MonoBoolean
10005 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
10006         guint32 id_std, guint32 id_noncas, guint32 id_choice)
10007 {
10008         guint32 idx = mono_method_get_index (method);
10009         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10010         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10011         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10012 }
10013
10014 /*
10015  * Collect all actions (that requires to generate code in mini) assigned for
10016  * the specified method.
10017  * Note: Don't use the content of actions if the function return FALSE.
10018  */
10019 MonoBoolean
10020 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10021 {
10022         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
10023                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10024         MonoBoolean result = FALSE;
10025         guint32 flags;
10026
10027         /* quick exit if no declarative security is present in the metadata */
10028         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10029                 return FALSE;
10030
10031         /* we want the original as the wrapper is "free" of the security informations */
10032         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10033                 method = mono_marshal_method_from_wrapper (method);
10034                 if (!method)
10035                         return FALSE;
10036         }
10037
10038         /* First we look for method-level attributes */
10039         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10040                 mono_class_init (method->klass);
10041                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10042
10043                 result = mono_declsec_get_method_demands_params (method, demands, 
10044                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10045         }
10046
10047         /* Here we use (or create) the class declarative cache to look for demands */
10048         flags = mono_declsec_flags_from_class (method->klass);
10049         if (flags & mask) {
10050                 if (!result) {
10051                         mono_class_init (method->klass);
10052                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
10053                 }
10054                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
10055                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10056         }
10057
10058         /* The boolean return value is used as a shortcut in case nothing needs to
10059            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10060         return result;
10061 }
10062
10063
10064 /*
10065  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10066  *
10067  * Note: Don't use the content of actions if the function return FALSE.
10068  */
10069 MonoBoolean
10070 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10071 {
10072         MonoBoolean result = FALSE;
10073         guint32 flags;
10074
10075         /* quick exit if no declarative security is present in the metadata */
10076         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10077                 return FALSE;
10078
10079         /* we want the original as the wrapper is "free" of the security informations */
10080         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10081                 method = mono_marshal_method_from_wrapper (method);
10082                 if (!method)
10083                         return FALSE;
10084         }
10085
10086         /* results are independant - zeroize both */
10087         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10088         memset (klass, 0, sizeof (MonoDeclSecurityActions));
10089
10090         /* First we look for method-level attributes */
10091         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10092                 mono_class_init (method->klass);
10093
10094                 result = mono_declsec_get_method_demands_params (method, cmethod, 
10095                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10096         }
10097
10098         /* Here we use (or create) the class declarative cache to look for demands */
10099         flags = mono_declsec_flags_from_class (method->klass);
10100         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10101                 mono_class_init (method->klass);
10102
10103                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
10104                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10105         }
10106
10107         return result;
10108 }
10109
10110 /*
10111  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10112  *
10113  * @klass       The inherited class - this is the class that provides the security check (attributes)
10114  * @demans      
10115  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10116  * 
10117  * Note: Don't use the content of actions if the function return FALSE.
10118  */
10119 MonoBoolean
10120 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10121 {
10122         MonoBoolean result = FALSE;
10123         guint32 flags;
10124
10125         /* quick exit if no declarative security is present in the metadata */
10126         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10127                 return FALSE;
10128
10129         /* Here we use (or create) the class declarative cache to look for demands */
10130         flags = mono_declsec_flags_from_class (klass);
10131         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10132                 mono_class_init (klass);
10133                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10134
10135                 result |= mono_declsec_get_class_demands_params (klass, demands, 
10136                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10137         }
10138
10139         return result;
10140 }
10141
10142 /*
10143  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10144  *
10145  * Note: Don't use the content of actions if the function return FALSE.
10146  */
10147 MonoBoolean
10148 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10149 {
10150         /* quick exit if no declarative security is present in the metadata */
10151         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10152                 return FALSE;
10153
10154         /* we want the original as the wrapper is "free" of the security informations */
10155         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10156                 method = mono_marshal_method_from_wrapper (method);
10157                 if (!method)
10158                         return FALSE;
10159         }
10160
10161         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10162                 mono_class_init (method->klass);
10163                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10164
10165                 return mono_declsec_get_method_demands_params (method, demands, 
10166                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10167         }
10168         return FALSE;
10169 }
10170
10171
10172 static MonoBoolean
10173 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10174 {
10175         guint32 cols [MONO_DECL_SECURITY_SIZE];
10176         MonoTableInfo *t;
10177         int i;
10178
10179         int index = mono_metadata_declsec_from_index (image, token);
10180         if (index == -1)
10181                 return FALSE;
10182
10183         t =  &image->tables [MONO_TABLE_DECLSECURITY];
10184         for (i = index; i < t->rows; i++) {
10185                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10186
10187                 /* shortcut - index are ordered */
10188                 if (token != cols [MONO_DECL_SECURITY_PARENT])
10189                         return FALSE;
10190
10191                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10192                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10193                         entry->blob = (char*) (metadata + 2);
10194                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10195                         return TRUE;
10196                 }
10197         }
10198
10199         return FALSE;
10200 }
10201
10202 MonoBoolean
10203 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10204 {
10205         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10206                 guint32 idx = mono_method_get_index (method);
10207                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10208                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10209                 return get_declsec_action (method->klass->image, idx, action, entry);
10210         }
10211         return FALSE;
10212 }
10213
10214 MonoBoolean
10215 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10216 {
10217         /* use cache */
10218         guint32 flags = mono_declsec_flags_from_class (klass);
10219         if (declsec_flags_map [action] & flags) {
10220                 guint32 idx = mono_metadata_token_index (klass->type_token);
10221                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10222                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10223                 return get_declsec_action (klass->image, idx, action, entry);
10224         }
10225         return FALSE;
10226 }
10227
10228 MonoBoolean
10229 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10230 {
10231         guint32 idx = 1; /* there is only one assembly */
10232         idx <<= MONO_HAS_DECL_SECURITY_BITS;
10233         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10234
10235         return get_declsec_action (assembly->image, idx, action, entry);
10236 }
10237
10238 gboolean
10239 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10240 {
10241         MonoObject *res, *exc;
10242         void *params [1];
10243         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10244         static MonoMethod *method = NULL;
10245
10246         if (!System_Reflection_Emit_TypeBuilder) {
10247                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10248                 g_assert (System_Reflection_Emit_TypeBuilder);
10249         }
10250         if (method == NULL) {
10251                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10252                 g_assert (method);
10253         }
10254
10255         /* 
10256          * The result of mono_type_get_object () might be a System.MonoType but we
10257          * need a TypeBuilder so use klass->reflection_info.
10258          */
10259         g_assert (klass->reflection_info);
10260         g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10261
10262         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10263
10264         res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10265         if (exc)
10266                 return FALSE;
10267         else
10268                 return *(MonoBoolean*)mono_object_unbox (res);
10269 }