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