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