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