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