2010-01-20 Zoltan Varga <vargaz@gmail.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 (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2569         if (token)
2570                 return token;
2571
2572         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2573         mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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         mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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         mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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         mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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         mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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         mono_g_hash_table_insert (assembly->handleref_managed, 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 (mono_g_hash_table_lookup (assembly->handleref_managed, 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         mono_g_hash_table_insert (assembly->handleref_managed, 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->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4952         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4953         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4954         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
4955         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4956         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4957         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4958         image->gen_params = g_ptr_array_new ();
4959
4960         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4961         string_heap_init (&image->sheap);
4962         mono_image_add_stream_data (&image->us, "", 1);
4963         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4964         /* import tables... */
4965         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4966         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4967         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4968         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4969         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4970         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4971         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4972         stream_data_align (&image->code);
4973
4974         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4975
4976         for (i=0; i < MONO_TABLE_NUM; ++i) {
4977                 image->tables [i].next_idx = 1;
4978                 image->tables [i].columns = table_sizes [i];
4979         }
4980
4981         image->image.assembly = (MonoAssembly*)assembly;
4982         image->run = assembly->run;
4983         image->save = assembly->save;
4984         image->pe_kind = 0x1; /* ILOnly */
4985         image->machine = 0x14c; /* I386 */
4986         
4987         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4988
4989         return image;
4990 }
4991 #endif
4992
4993 static void
4994 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4995 {
4996         g_free (key);
4997 }
4998
4999 void
5000 mono_dynamic_image_free (MonoDynamicImage *image)
5001 {
5002         MonoDynamicImage *di = image;
5003         GList *list;
5004         int i;
5005
5006         if (di->methodspec)
5007                 mono_g_hash_table_destroy (di->methodspec);
5008         if (di->typespec)
5009                 g_hash_table_destroy (di->typespec);
5010         if (di->typeref)
5011                 g_hash_table_destroy (di->typeref);
5012         if (di->handleref)
5013                 g_hash_table_destroy (di->handleref);
5014         if (di->handleref_managed)
5015                 mono_g_hash_table_destroy (di->handleref_managed);
5016         if (di->tokens)
5017                 mono_g_hash_table_destroy (di->tokens);
5018         if (di->generic_def_objects)
5019                 mono_g_hash_table_destroy (di->generic_def_objects);
5020         if (di->blob_cache) {
5021                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5022                 g_hash_table_destroy (di->blob_cache);
5023         }
5024         if (di->standalonesig_cache)
5025                 g_hash_table_destroy (di->standalonesig_cache);
5026         for (list = di->array_methods; list; list = list->next) {
5027                 ArrayMethod *am = (ArrayMethod *)list->data;
5028                 g_free (am->sig);
5029                 g_free (am->name);
5030                 g_free (am);
5031         }
5032         g_list_free (di->array_methods);
5033         if (di->gen_params) {
5034                 for (i = 0; i < di->gen_params->len; i++) {
5035                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5036                         if (entry->gparam->type.type) {
5037                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5038                                 g_free ((char*)mono_generic_param_info (param)->name);
5039                                 g_free (param);
5040                         }
5041                         mono_gc_deregister_root ((char*) &entry->gparam);
5042                         g_free (entry);
5043                 }
5044                 g_ptr_array_free (di->gen_params, TRUE);
5045         }
5046         if (di->token_fixups)
5047                 mono_g_hash_table_destroy (di->token_fixups);
5048         if (di->method_to_table_idx)
5049                 g_hash_table_destroy (di->method_to_table_idx);
5050         if (di->field_to_table_idx)
5051                 g_hash_table_destroy (di->field_to_table_idx);
5052         if (di->method_aux_hash)
5053                 g_hash_table_destroy (di->method_aux_hash);
5054         g_free (di->strong_name);
5055         g_free (di->win32_res);
5056         if (di->public_key)
5057                 g_free (di->public_key);
5058
5059         /*g_print ("string heap destroy for image %p\n", di);*/
5060         mono_dynamic_stream_reset (&di->sheap);
5061         mono_dynamic_stream_reset (&di->code);
5062         mono_dynamic_stream_reset (&di->resources);
5063         mono_dynamic_stream_reset (&di->us);
5064         mono_dynamic_stream_reset (&di->blob);
5065         mono_dynamic_stream_reset (&di->tstream);
5066         mono_dynamic_stream_reset (&di->guid);
5067         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5068                 g_free (di->tables [i].values);
5069         }
5070 }       
5071
5072 #ifndef DISABLE_REFLECTION_EMIT
5073
5074 /*
5075  * mono_image_basic_init:
5076  * @assembly: an assembly builder object
5077  *
5078  * Create the MonoImage that represents the assembly builder and setup some
5079  * of the helper hash table and the basic metadata streams.
5080  */
5081 void
5082 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5083 {
5084         MonoDynamicAssembly *assembly;
5085         MonoDynamicImage *image;
5086         MonoDomain *domain = mono_object_domain (assemblyb);
5087         
5088         MONO_ARCH_SAVE_REGS;
5089
5090         if (assemblyb->dynamic_assembly)
5091                 return;
5092
5093 #if HAVE_BOEHM_GC
5094         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5095 #else
5096         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5097 #endif
5098
5099         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5100         
5101         assembly->assembly.ref_count = 1;
5102         assembly->assembly.dynamic = TRUE;
5103         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5104         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5105         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5106         if (assemblyb->culture)
5107                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5108         else
5109                 assembly->assembly.aname.culture = g_strdup ("");
5110
5111         if (assemblyb->version) {
5112                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5113                         char **version = g_strsplit (vstr, ".", 4);
5114                         char **parts = version;
5115                         assembly->assembly.aname.major = atoi (*parts++);
5116                         assembly->assembly.aname.minor = atoi (*parts++);
5117                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5118                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5119
5120                         g_strfreev (version);
5121                         g_free (vstr);
5122         } else {
5123                         assembly->assembly.aname.major = 0;
5124                         assembly->assembly.aname.minor = 0;
5125                         assembly->assembly.aname.build = 0;
5126                         assembly->assembly.aname.revision = 0;
5127         }
5128
5129         assembly->run = assemblyb->access != 2;
5130         assembly->save = assemblyb->access != 1;
5131         assembly->domain = domain;
5132
5133         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5134         image->initial_image = TRUE;
5135         assembly->assembly.aname.name = image->image.name;
5136         assembly->assembly.image = &image->image;
5137         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5138                 /* -1 to correct for the trailing NULL byte */
5139                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5140                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5141                 }
5142                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5143         }
5144
5145         mono_domain_assemblies_lock (domain);
5146         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5147         mono_domain_assemblies_unlock (domain);
5148
5149         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5150         
5151         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5152         
5153         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5154 }
5155
5156 #endif /* !DISABLE_REFLECTION_EMIT */
5157
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5159
5160 static int
5161 calc_section_size (MonoDynamicImage *assembly)
5162 {
5163         int nsections = 0;
5164
5165         /* alignment constraints */
5166         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5167         g_assert ((assembly->code.index % 4) == 0);
5168         assembly->meta_size += 3;
5169         assembly->meta_size &= ~3;
5170         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5171         g_assert ((assembly->resources.index % 4) == 0);
5172
5173         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5174         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5175         nsections++;
5176
5177         if (assembly->win32_res) {
5178                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5179
5180                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5181                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5182                 nsections++;
5183         }
5184
5185         assembly->sections [MONO_SECTION_RELOC].size = 12;
5186         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5187         nsections++;
5188
5189         return nsections;
5190 }
5191
5192 typedef struct {
5193         guint32 id;
5194         guint32 offset;
5195         GSList *children;
5196         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5197 } ResTreeNode;
5198
5199 static int
5200 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5201 {
5202         ResTreeNode *t1 = (ResTreeNode*)a;
5203         ResTreeNode *t2 = (ResTreeNode*)b;
5204
5205         return t1->id - t2->id;
5206 }
5207
5208 /*
5209  * resource_tree_create:
5210  *
5211  *  Organize the resources into a resource tree.
5212  */
5213 static ResTreeNode *
5214 resource_tree_create (MonoArray *win32_resources)
5215 {
5216         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5217         GSList *l;
5218         int i;
5219
5220         tree = g_new0 (ResTreeNode, 1);
5221         
5222         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5223                 MonoReflectionWin32Resource *win32_res =
5224                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5225
5226                 /* Create node */
5227
5228                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5229                 lang_node = g_new0 (ResTreeNode, 1);
5230                 lang_node->id = win32_res->lang_id;
5231                 lang_node->win32_res = win32_res;
5232
5233                 /* Create type node if neccesary */
5234                 type_node = NULL;
5235                 for (l = tree->children; l; l = l->next)
5236                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5237                                 type_node = (ResTreeNode*)l->data;
5238                                 break;
5239                         }
5240
5241                 if (!type_node) {
5242                         type_node = g_new0 (ResTreeNode, 1);
5243                         type_node->id = win32_res->res_type;
5244
5245                         /* 
5246                          * The resource types have to be sorted otherwise
5247                          * Windows Explorer can't display the version information.
5248                          */
5249                         tree->children = g_slist_insert_sorted (tree->children, 
5250                                 type_node, resource_tree_compare_by_id);
5251                 }
5252
5253                 /* Create res node if neccesary */
5254                 res_node = NULL;
5255                 for (l = type_node->children; l; l = l->next)
5256                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5257                                 res_node = (ResTreeNode*)l->data;
5258                                 break;
5259                         }
5260
5261                 if (!res_node) {
5262                         res_node = g_new0 (ResTreeNode, 1);
5263                         res_node->id = win32_res->res_id;
5264                         type_node->children = g_slist_append (type_node->children, res_node);
5265                 }
5266
5267                 res_node->children = g_slist_append (res_node->children, lang_node);
5268         }
5269
5270         return tree;
5271 }
5272
5273 /*
5274  * resource_tree_encode:
5275  * 
5276  *   Encode the resource tree into the format used in the PE file.
5277  */
5278 static void
5279 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5280 {
5281         char *entries;
5282         MonoPEResourceDir dir;
5283         MonoPEResourceDirEntry dir_entry;
5284         MonoPEResourceDataEntry data_entry;
5285         GSList *l;
5286         guint32 res_id_entries;
5287
5288         /*
5289          * For the format of the resource directory, see the article
5290          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5291          * Matt Pietrek
5292          */
5293
5294         memset (&dir, 0, sizeof (dir));
5295         memset (&dir_entry, 0, sizeof (dir_entry));
5296         memset (&data_entry, 0, sizeof (data_entry));
5297
5298         g_assert (sizeof (dir) == 16);
5299         g_assert (sizeof (dir_entry) == 8);
5300         g_assert (sizeof (data_entry) == 16);
5301
5302         node->offset = p - begin;
5303
5304         /* IMAGE_RESOURCE_DIRECTORY */
5305         res_id_entries = g_slist_length (node->children);
5306         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5307
5308         memcpy (p, &dir, sizeof (dir));
5309         p += sizeof (dir);
5310
5311         /* Reserve space for entries */
5312         entries = p;
5313         p += sizeof (dir_entry) * res_id_entries;
5314
5315         /* Write children */
5316         for (l = node->children; l; l = l->next) {
5317                 ResTreeNode *child = (ResTreeNode*)l->data;
5318
5319                 if (child->win32_res) {
5320                         guint32 size;
5321
5322                         child->offset = p - begin;
5323
5324                         /* IMAGE_RESOURCE_DATA_ENTRY */
5325                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5326                         size = mono_array_length (child->win32_res->res_data);
5327                         data_entry.rde_size = GUINT32_TO_LE (size);
5328
5329                         memcpy (p, &data_entry, sizeof (data_entry));
5330                         p += sizeof (data_entry);
5331
5332                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5333                         p += size;
5334                 } else {
5335                         resource_tree_encode (child, begin, p, &p);
5336                 }
5337         }
5338
5339         /* IMAGE_RESOURCE_ENTRY */
5340         for (l = node->children; l; l = l->next) {
5341                 ResTreeNode *child = (ResTreeNode*)l->data;
5342
5343                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5344                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5345
5346                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5347                 entries += sizeof (dir_entry);
5348         }
5349
5350         *endbuf = p;
5351 }
5352
5353 static void
5354 resource_tree_free (ResTreeNode * node)
5355 {
5356         GSList * list;
5357         for (list = node->children; list; list = list->next)
5358                 resource_tree_free ((ResTreeNode*)list->data);
5359         g_slist_free(node->children);
5360         g_free (node);
5361 }
5362
5363 static void
5364 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5365 {
5366         char *buf;
5367         char *p;
5368         guint32 size, i;
5369         MonoReflectionWin32Resource *win32_res;
5370         ResTreeNode *tree;
5371
5372         if (!assemblyb->win32_resources)
5373                 return;
5374
5375         /*
5376          * Resources are stored in a three level tree inside the PE file.
5377          * - level one contains a node for each type of resource
5378          * - level two contains a node for each resource
5379          * - level three contains a node for each instance of a resource for a
5380          *   specific language.
5381          */
5382
5383         tree = resource_tree_create (assemblyb->win32_resources);
5384
5385         /* Estimate the size of the encoded tree */
5386         size = 0;
5387         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5388                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5389                 size += mono_array_length (win32_res->res_data);
5390         }
5391         /* Directory structure */
5392         size += mono_array_length (assemblyb->win32_resources) * 256;
5393         p = buf = g_malloc (size);
5394
5395         resource_tree_encode (tree, p, p, &p);
5396
5397         g_assert (p - buf <= size);
5398
5399         assembly->win32_res = g_malloc (p - buf);
5400         assembly->win32_res_size = p - buf;
5401         memcpy (assembly->win32_res, buf, p - buf);
5402
5403         g_free (buf);
5404         resource_tree_free (tree);
5405 }
5406
5407 static void
5408 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5409 {
5410         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5411         int i;
5412
5413         p += sizeof (MonoPEResourceDir);
5414         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5415                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5416                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5417                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5418                         fixup_resource_directory (res_section, child, rva);
5419                 } else {
5420                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5421                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5422                 }
5423
5424                 p += sizeof (MonoPEResourceDirEntry);
5425         }
5426 }
5427
5428 static void
5429 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5430 {
5431         guint32 dummy;
5432         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5433                 g_error ("WriteFile returned %d\n", GetLastError ());
5434 }
5435
5436 /*
5437  * mono_image_create_pefile:
5438  * @mb: a module builder object
5439  * 
5440  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5441  * assembly->pefile where it can be easily retrieved later in chunks.
5442  */
5443 void
5444 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5445 {
5446         MonoMSDOSHeader *msdos;
5447         MonoDotNetHeader *header;
5448         MonoSectionTable *section;
5449         MonoCLIHeader *cli_header;
5450         guint32 size, image_size, virtual_base, text_offset;
5451         guint32 header_start, section_start, file_offset, virtual_offset;
5452         MonoDynamicImage *assembly;
5453         MonoReflectionAssemblyBuilder *assemblyb;
5454         MonoDynamicStream pefile_stream = {0};
5455         MonoDynamicStream *pefile = &pefile_stream;
5456         int i, nsections;
5457         guint32 *rva, value;
5458         guchar *p;
5459         static const unsigned char msheader[] = {
5460                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5461                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5462                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5463                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5464                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5465                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5466                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5467                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5468         };
5469
5470         assemblyb = mb->assemblyb;
5471
5472         mono_image_basic_init (assemblyb);
5473         assembly = mb->dynamic_image;
5474
5475         assembly->pe_kind = assemblyb->pe_kind;
5476         assembly->machine = assemblyb->machine;
5477         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5478         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5479         
5480         mono_image_build_metadata (mb);
5481
5482         if (mb->is_main && assemblyb->resources) {
5483                 int len = mono_array_length (assemblyb->resources);
5484                 for (i = 0; i < len; ++i)
5485                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5486         }
5487
5488         if (mb->resources) {
5489                 int len = mono_array_length (mb->resources);
5490                 for (i = 0; i < len; ++i)
5491                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5492         }
5493
5494         build_compressed_metadata (assembly);
5495
5496         if (mb->is_main)
5497                 assembly_add_win32_resources (assembly, assemblyb);
5498
5499         nsections = calc_section_size (assembly);
5500         
5501         /* The DOS header and stub */
5502         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5503         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5504
5505         /* the dotnet header */
5506         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5507
5508         /* the section tables */
5509         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5510
5511         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5512         virtual_offset = VIRT_ALIGN;
5513         image_size = 0;
5514
5515         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5516                 if (!assembly->sections [i].size)
5517                         continue;
5518                 /* align offsets */
5519                 file_offset += FILE_ALIGN - 1;
5520                 file_offset &= ~(FILE_ALIGN - 1);
5521                 virtual_offset += VIRT_ALIGN - 1;
5522                 virtual_offset &= ~(VIRT_ALIGN - 1);
5523
5524                 assembly->sections [i].offset = file_offset;
5525                 assembly->sections [i].rva = virtual_offset;
5526
5527                 file_offset += assembly->sections [i].size;
5528                 virtual_offset += assembly->sections [i].size;
5529                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5530         }
5531
5532         file_offset += FILE_ALIGN - 1;
5533         file_offset &= ~(FILE_ALIGN - 1);
5534
5535         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5536
5537         /* back-patch info */
5538         msdos = (MonoMSDOSHeader*)pefile->data;
5539         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5540
5541         header = (MonoDotNetHeader*)(pefile->data + header_start);
5542         header->pesig [0] = 'P';
5543         header->pesig [1] = 'E';
5544         
5545         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5546         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5547         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5548         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5549         if (assemblyb->pekind == 1) {
5550                 /* it's a dll */
5551                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5552         } else {
5553                 /* it's an exe */
5554                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5555         }
5556
5557         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5558
5559         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5560         header->pe.pe_major = 6;
5561         header->pe.pe_minor = 0;
5562         size = assembly->sections [MONO_SECTION_TEXT].size;
5563         size += FILE_ALIGN - 1;
5564         size &= ~(FILE_ALIGN - 1);
5565         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5566         size = assembly->sections [MONO_SECTION_RSRC].size;
5567         size += FILE_ALIGN - 1;
5568         size &= ~(FILE_ALIGN - 1);
5569         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5570         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5571         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5572         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5573         /* pe_rva_entry_point always at the beginning of the text section */
5574         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5575
5576         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5577         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5578         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5579         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5580         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5581         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5582         size = section_start;
5583         size += FILE_ALIGN - 1;
5584         size &= ~(FILE_ALIGN - 1);
5585         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5586         size = image_size;
5587         size += VIRT_ALIGN - 1;
5588         size &= ~(VIRT_ALIGN - 1);
5589         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5590
5591         /*
5592         // Translate the PEFileKind value to the value expected by the Windows loader
5593         */
5594         {
5595                 short kind;
5596
5597                 /*
5598                 // PEFileKinds.Dll == 1
5599                 // PEFileKinds.ConsoleApplication == 2
5600                 // PEFileKinds.WindowApplication == 3
5601                 //
5602                 // need to get:
5603                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5604                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5605                 */
5606                 if (assemblyb->pekind == 3)
5607                         kind = 2;
5608                 else
5609                         kind = 3;
5610                 
5611                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5612         }    
5613         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5614         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5615         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5616         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5617         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5618         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5619
5620         /* fill data directory entries */
5621
5622         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5623         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5624
5625         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5626         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5627
5628         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5629         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5630         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5631         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5632         /* patch entrypoint name */
5633         if (assemblyb->pekind == 1)
5634                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5635         else
5636                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5637         /* patch imported function RVA name */
5638         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5639         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5640
5641         /* the import table */
5642         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5643         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5644         /* patch imported dll RVA name and other entries in the dir */
5645         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5646         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5647         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5648         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5649         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5650         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5651
5652         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5653         value = (assembly->text_rva + assembly->imp_names_offset);
5654         *p++ = (value) & 0xff;
5655         *p++ = (value >> 8) & (0xff);
5656         *p++ = (value >> 16) & (0xff);
5657         *p++ = (value >> 24) & (0xff);
5658
5659         /* the CLI header info */
5660         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5661         cli_header->ch_size = GUINT32_FROM_LE (72);
5662         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5663         if (mono_framework_version () > 1)
5664                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5665         else 
5666                 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5667         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5668         if (assemblyb->entry_point) {
5669                 guint32 table_idx = 0;
5670                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5671                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5672                         table_idx = methodb->table_idx;
5673                 } else {
5674                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5675                 }
5676                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5677         } else {
5678                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5679         }
5680         /* The embedded managed resources */
5681         text_offset = assembly->text_rva + assembly->code.index;
5682         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5683         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5684         text_offset += assembly->resources.index;
5685         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5686         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5687         text_offset += assembly->meta_size;
5688         if (assembly->strong_name_size) {
5689                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5690                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5691                 text_offset += assembly->strong_name_size;
5692         }
5693
5694         /* write the section tables and section content */
5695         section = (MonoSectionTable*)(pefile->data + section_start);
5696         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5697                 static const char section_names [][7] = {
5698                         ".text", ".rsrc", ".reloc"
5699                 };
5700                 if (!assembly->sections [i].size)
5701                         continue;
5702                 strcpy (section->st_name, section_names [i]);
5703                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5704                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5705                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5706                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5707                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5708                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5709                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5710                 section ++;
5711         }
5712         
5713         checked_write_file (file, pefile->data, pefile->index);
5714         
5715         mono_dynamic_stream_reset (pefile);
5716         
5717         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5718                 if (!assembly->sections [i].size)
5719                         continue;
5720                 
5721                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5722                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5723                 
5724                 switch (i) {
5725                 case MONO_SECTION_TEXT:
5726                         /* patch entry point */
5727                         p = (guchar*)(assembly->code.data + 2);
5728                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5729                         *p++ = (value) & 0xff;
5730                         *p++ = (value >> 8) & 0xff;
5731                         *p++ = (value >> 16) & 0xff;
5732                         *p++ = (value >> 24) & 0xff;
5733                 
5734                         checked_write_file (file, assembly->code.data, assembly->code.index);
5735                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5736                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5737                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5738                                 
5739
5740                         g_free (assembly->image.raw_metadata);
5741                         break;
5742                 case MONO_SECTION_RELOC: {
5743                         struct {
5744                                 guint32 page_rva;
5745                                 guint32 block_size;
5746                                 guint16 type_and_offset;
5747                                 guint16 term;
5748                         } reloc;
5749                         
5750                         g_assert (sizeof (reloc) == 12);
5751                         
5752                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5753                         reloc.block_size = GUINT32_FROM_LE (12);
5754                         
5755                         /* 
5756                          * the entrypoint is always at the start of the text section 
5757                          * 3 is IMAGE_REL_BASED_HIGHLOW
5758                          * 2 is patch_size_rva - text_rva
5759                          */
5760                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5761                         reloc.term = 0;
5762                         
5763                         checked_write_file (file, &reloc, sizeof (reloc));
5764                         
5765                         break;
5766                 }
5767                 case MONO_SECTION_RSRC:
5768                         if (assembly->win32_res) {
5769
5770                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5771                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5772                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5773                         }
5774                         break;
5775                 default:
5776                         g_assert_not_reached ();
5777                 }
5778         }
5779         
5780         /* check that the file is properly padded */
5781         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5782                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5783         if (! SetEndOfFile (file))
5784                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5785         
5786         mono_dynamic_stream_reset (&assembly->code);
5787         mono_dynamic_stream_reset (&assembly->us);
5788         mono_dynamic_stream_reset (&assembly->blob);
5789         mono_dynamic_stream_reset (&assembly->guid);
5790         mono_dynamic_stream_reset (&assembly->sheap);
5791
5792         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5793         g_hash_table_destroy (assembly->blob_cache);
5794         assembly->blob_cache = NULL;
5795 }
5796
5797 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5798
5799 void
5800 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5801 {
5802         g_assert_not_reached ();
5803 }
5804
5805 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5806
5807 #ifndef DISABLE_REFLECTION_EMIT
5808
5809 MonoReflectionModule *
5810 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5811 {
5812         char *name;
5813         MonoImage *image;
5814         MonoImageOpenStatus status;
5815         MonoDynamicAssembly *assembly;
5816         guint32 module_count;
5817         MonoImage **new_modules;
5818         gboolean *new_modules_loaded;
5819         
5820         name = mono_string_to_utf8 (fileName);
5821
5822         image = mono_image_open (name, &status);
5823         if (!image) {
5824                 MonoException *exc;
5825                 if (status == MONO_IMAGE_ERROR_ERRNO)
5826                         exc = mono_get_exception_file_not_found (fileName);
5827                 else
5828                         exc = mono_get_exception_bad_image_format (name);
5829                 g_free (name);
5830                 mono_raise_exception (exc);
5831         }
5832
5833         g_free (name);
5834
5835         assembly = ab->dynamic_assembly;
5836         image->assembly = (MonoAssembly*)assembly;
5837
5838         module_count = image->assembly->image->module_count;
5839         new_modules = g_new0 (MonoImage *, module_count + 1);
5840         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5841
5842         if (image->assembly->image->modules)
5843                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5844         if (image->assembly->image->modules_loaded)
5845                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5846         new_modules [module_count] = image;
5847         new_modules_loaded [module_count] = TRUE;
5848         mono_image_addref (image);
5849
5850         g_free (image->assembly->image->modules);
5851         image->assembly->image->modules = new_modules;
5852         image->assembly->image->modules_loaded = new_modules_loaded;
5853         image->assembly->image->module_count ++;
5854
5855         mono_assembly_load_references (image, &status);
5856         if (status) {
5857                 mono_image_close (image);
5858                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5859         }
5860
5861         return mono_module_get_object (mono_domain_get (), image);
5862 }
5863
5864 #endif /* DISABLE_REFLECTION_EMIT */
5865
5866 /*
5867  * We need to return always the same object for MethodInfo, FieldInfo etc..
5868  * but we need to consider the reflected type.
5869  * type uses a different hash, since it uses custom hash/equal functions.
5870  */
5871
5872 typedef struct {
5873         gpointer item;
5874         MonoClass *refclass;
5875 } ReflectedEntry;
5876
5877 static gboolean
5878 reflected_equal (gconstpointer a, gconstpointer b) {
5879         const ReflectedEntry *ea = a;
5880         const ReflectedEntry *eb = b;
5881
5882         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5883 }
5884
5885 static guint
5886 reflected_hash (gconstpointer a) {
5887         const ReflectedEntry *ea = a;
5888         return mono_aligned_addr_hash (ea->item);
5889 }
5890
5891 #define CHECK_OBJECT(t,p,k)     \
5892         do {    \
5893                 t _obj; \
5894                 ReflectedEntry e;       \
5895                 e.item = (p);   \
5896                 e.refclass = (k);       \
5897                 mono_domain_lock (domain);      \
5898                 if (!domain->refobject_hash)    \
5899                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5900                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5901                         mono_domain_unlock (domain);    \
5902                         return _obj;    \
5903                 }       \
5904         mono_domain_unlock (domain); \
5905         } while (0)
5906
5907 #ifdef HAVE_BOEHM_GC
5908 /* ReflectedEntry doesn't need to be GC tracked */
5909 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5910 #define FREE_REFENTRY(entry) g_free ((entry))
5911 #define REFENTRY_REQUIRES_CLEANUP
5912 #else
5913 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5914 /* FIXME: */
5915 #define FREE_REFENTRY(entry)
5916 #endif
5917
5918 #define CACHE_OBJECT(t,p,o,k)   \
5919         do {    \
5920                 t _obj; \
5921         ReflectedEntry pe; \
5922         pe.item = (p); \
5923         pe.refclass = (k); \
5924         mono_domain_lock (domain); \
5925                 if (!domain->refobject_hash)    \
5926                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5927         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5928         if (!_obj) { \
5929                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5930                     e->item = (p);      \
5931                     e->refclass = (k);  \
5932                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5933             _obj = o; \
5934         } \
5935                 mono_domain_unlock (domain);    \
5936         return _obj; \
5937         } while (0)
5938
5939 static void
5940 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5941 {
5942         mono_domain_lock (domain);
5943         if (domain->refobject_hash) {
5944         ReflectedEntry pe;
5945                 gpointer orig_pe, orig_value;
5946
5947                 pe.item = o;
5948                 pe.refclass = klass;
5949                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5950                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
5951                         FREE_REFENTRY (orig_pe);
5952                 }
5953         }
5954         mono_domain_unlock (domain);
5955 }
5956
5957 #ifdef REFENTRY_REQUIRES_CLEANUP
5958 static void
5959 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
5960 {
5961         FREE_REFENTRY (key);
5962 }
5963 #endif
5964
5965 void
5966 mono_reflection_cleanup_domain (MonoDomain *domain)
5967 {
5968         if (domain->refobject_hash) {
5969 /*let's avoid scanning the whole hashtable if not needed*/
5970 #ifdef REFENTRY_REQUIRES_CLEANUP
5971                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
5972 #endif
5973                 mono_g_hash_table_destroy (domain->refobject_hash);
5974                 domain->refobject_hash = NULL;
5975         }
5976 }
5977
5978 #ifndef DISABLE_REFLECTION_EMIT
5979 static gpointer
5980 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5981 {
5982         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5983 }
5984
5985 static gpointer
5986 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5987 {
5988         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5989 }
5990
5991 void
5992 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5993 {
5994         MonoDynamicImage *image = moduleb->dynamic_image;
5995         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5996         if (!image) {
5997                 MonoError error;
5998                 int module_count;
5999                 MonoImage **new_modules;
6000                 MonoImage *ass;
6001                 char *name, *fqname;
6002                 /*
6003                  * FIXME: we already created an image in mono_image_basic_init (), but
6004                  * we don't know which module it belongs to, since that is only 
6005                  * determined at assembly save time.
6006                  */
6007                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6008                 name = mono_string_to_utf8 (ab->name);
6009                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6010                 if (!mono_error_ok (&error)) {
6011                         g_free (name);
6012                         mono_error_raise_exception (&error);
6013                 }
6014                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6015
6016                 moduleb->module.image = &image->image;
6017                 moduleb->dynamic_image = image;
6018                 register_module (mono_object_domain (moduleb), moduleb, image);
6019
6020                 /* register the module with the assembly */
6021                 ass = ab->dynamic_assembly->assembly.image;
6022                 module_count = ass->module_count;
6023                 new_modules = g_new0 (MonoImage *, module_count + 1);
6024
6025                 if (ass->modules)
6026                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6027                 new_modules [module_count] = &image->image;
6028                 mono_image_addref (&image->image);
6029
6030                 g_free (ass->modules);
6031                 ass->modules = new_modules;
6032                 ass->module_count ++;
6033         }
6034 }
6035
6036 void
6037 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6038 {
6039         MonoDynamicImage *image = moduleb->dynamic_image;
6040
6041         g_assert (type->type);
6042         image->wrappers_type = mono_class_from_mono_type (type->type);
6043 }
6044
6045 #endif
6046
6047 /*
6048  * mono_assembly_get_object:
6049  * @domain: an app domain
6050  * @assembly: an assembly
6051  *
6052  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6053  */
6054 MonoReflectionAssembly*
6055 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6056 {
6057         static MonoClass *System_Reflection_Assembly;
6058         MonoReflectionAssembly *res;
6059         
6060         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6061         if (!System_Reflection_Assembly)
6062                 System_Reflection_Assembly = mono_class_from_name (
6063                         mono_defaults.corlib, "System.Reflection", "Assembly");
6064         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
6065         res->assembly = assembly;
6066
6067         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6068 }
6069
6070
6071
6072 MonoReflectionModule*   
6073 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6074 {
6075         static MonoClass *System_Reflection_Module;
6076         MonoReflectionModule *res;
6077         char* basename;
6078         
6079         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6080         if (!System_Reflection_Module)
6081                 System_Reflection_Module = mono_class_from_name (
6082                         mono_defaults.corlib, "System.Reflection", "Module");
6083         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6084
6085         res->image = image;
6086         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6087
6088         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6089         basename = g_path_get_basename (image->name);
6090         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6091         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6092         
6093         g_free (basename);
6094
6095         if (image->assembly->image == image) {
6096                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6097         } else {
6098                 int i;
6099                 res->token = 0;
6100                 if (image->assembly->image->modules) {
6101                         for (i = 0; i < image->assembly->image->module_count; i++) {
6102                                 if (image->assembly->image->modules [i] == image)
6103                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6104                         }
6105                         g_assert (res->token);
6106                 }
6107         }
6108
6109         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6110 }
6111
6112 MonoReflectionModule*   
6113 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6114 {
6115         static MonoClass *System_Reflection_Module;
6116         MonoReflectionModule *res;
6117         MonoTableInfo *table;
6118         guint32 cols [MONO_FILE_SIZE];
6119         const char *name;
6120         guint32 i, name_idx;
6121         const char *val;
6122         
6123         if (!System_Reflection_Module)
6124                 System_Reflection_Module = mono_class_from_name (
6125                         mono_defaults.corlib, "System.Reflection", "Module");
6126         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
6127
6128         table = &image->tables [MONO_TABLE_FILE];
6129         g_assert (table_index < table->rows);
6130         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6131
6132         res->image = NULL;
6133         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6134         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6135
6136         /* Check whenever the row has a corresponding row in the moduleref table */
6137         table = &image->tables [MONO_TABLE_MODULEREF];
6138         for (i = 0; i < table->rows; ++i) {
6139                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6140                 val = mono_metadata_string_heap (image, name_idx);
6141                 if (strcmp (val, name) == 0)
6142                         res->image = image->modules [i];
6143         }
6144
6145         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6146         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6147         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6148         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6149         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6150
6151         return res;
6152 }
6153
6154 static gboolean
6155 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6156 {
6157         if ((t1->type != t2->type) ||
6158             (t1->byref != t2->byref))
6159                 return FALSE;
6160
6161         switch (t1->type) {
6162         case MONO_TYPE_VOID:
6163         case MONO_TYPE_BOOLEAN:
6164         case MONO_TYPE_CHAR:
6165         case MONO_TYPE_I1:
6166         case MONO_TYPE_U1:
6167         case MONO_TYPE_I2:
6168         case MONO_TYPE_U2:
6169         case MONO_TYPE_I4:
6170         case MONO_TYPE_U4:
6171         case MONO_TYPE_I8:
6172         case MONO_TYPE_U8:
6173         case MONO_TYPE_R4:
6174         case MONO_TYPE_R8:
6175         case MONO_TYPE_STRING:
6176         case MONO_TYPE_I:
6177         case MONO_TYPE_U:
6178         case MONO_TYPE_OBJECT:
6179         case MONO_TYPE_TYPEDBYREF:
6180                 return TRUE;
6181         case MONO_TYPE_VALUETYPE:
6182         case MONO_TYPE_CLASS:
6183         case MONO_TYPE_SZARRAY:
6184                 return t1->data.klass == t2->data.klass;
6185         case MONO_TYPE_PTR:
6186                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6187         case MONO_TYPE_ARRAY:
6188                 if (t1->data.array->rank != t2->data.array->rank)
6189                         return FALSE;
6190                 return t1->data.array->eklass == t2->data.array->eklass;
6191         case MONO_TYPE_GENERICINST: {
6192                 int i;
6193                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6194                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6195                 if (i1->type_argc != i2->type_argc)
6196                         return FALSE;
6197                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6198                                                &t2->data.generic_class->container_class->byval_arg))
6199                         return FALSE;
6200                 /* FIXME: we should probably just compare the instance pointers directly.  */
6201                 for (i = 0; i < i1->type_argc; ++i) {
6202                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6203                                 return FALSE;
6204                 }
6205                 return TRUE;
6206         }
6207         case MONO_TYPE_VAR:
6208         case MONO_TYPE_MVAR:
6209                 return t1->data.generic_param == t2->data.generic_param;
6210         default:
6211                 g_error ("implement type compare for %0x!", t1->type);
6212                 return FALSE;
6213         }
6214
6215         return FALSE;
6216 }
6217
6218 static guint
6219 mymono_metadata_type_hash (MonoType *t1)
6220 {
6221         guint hash;
6222
6223         hash = t1->type;
6224
6225         hash |= t1->byref << 6; /* do not collide with t1->type values */
6226         switch (t1->type) {
6227         case MONO_TYPE_VALUETYPE:
6228         case MONO_TYPE_CLASS:
6229         case MONO_TYPE_SZARRAY:
6230                 /* check if the distribution is good enough */
6231                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6232         case MONO_TYPE_PTR:
6233                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6234         case MONO_TYPE_GENERICINST: {
6235                 int i;
6236                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6237                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6238                 hash *= 13;
6239                 for (i = 0; i < inst->type_argc; ++i) {
6240                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6241                         hash *= 13;
6242                 }
6243                 return hash;
6244         }
6245         }
6246         return hash;
6247 }
6248
6249 static MonoReflectionGenericClass*
6250 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6251 {
6252         static MonoClass *System_Reflection_MonoGenericClass;
6253         MonoReflectionGenericClass *res;
6254         MonoClass *klass, *gklass;
6255         MonoGenericInst *ginst;
6256         MonoArray *type_args;
6257         int i;
6258
6259         g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
6260
6261         if (!System_Reflection_MonoGenericClass) {
6262                 System_Reflection_MonoGenericClass = mono_class_from_name (
6263                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6264                 g_assert (System_Reflection_MonoGenericClass);
6265         }
6266
6267         klass = mono_class_from_mono_type (geninst);
6268         gklass = klass->generic_class->container_class;
6269
6270         mono_class_init (klass);
6271
6272 #ifdef HAVE_SGEN_GC
6273         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6274 #else
6275         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6276 #endif
6277
6278         res->type.type = geninst;
6279         g_assert (gklass->reflection_info);
6280         g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6281         MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6282
6283         ginst = klass->generic_class->context.class_inst;
6284         type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6285         for (i = 0; i < ginst->type_argc; ++i)
6286                 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6287         MONO_OBJECT_SETREF (res, type_arguments, type_args);
6288
6289         return res;
6290 }
6291
6292 static gboolean
6293 verify_safe_for_managed_space (MonoType *type)
6294 {
6295         switch (type->type) {
6296 #ifdef DEBUG_HARDER
6297         case MONO_TYPE_ARRAY:
6298                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6299         case MONO_TYPE_PTR:
6300                 return verify_safe_for_managed_space (type->data.type);
6301         case MONO_TYPE_SZARRAY:
6302                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6303         case MONO_TYPE_GENERICINST: {
6304                 MonoGenericInst *inst = type->data.generic_class->inst;
6305                 int i;
6306                 if (!inst->is_open)
6307                         break;
6308                 for (i = 0; i < inst->type_argc; ++i)
6309                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6310                                 return FALSE;
6311                 break;
6312         }
6313 #endif
6314         case MONO_TYPE_VAR:
6315         case MONO_TYPE_MVAR:
6316                 return TRUE;
6317         }
6318         return TRUE;
6319 }
6320
6321 /*
6322  * mono_type_get_object:
6323  * @domain: an app domain
6324  * @type: a type
6325  *
6326  * Return an System.MonoType object representing the type @type.
6327  */
6328 MonoReflectionType*
6329 mono_type_get_object (MonoDomain *domain, MonoType *type)
6330 {
6331         MonoReflectionType *res;
6332         MonoClass *klass = mono_class_from_mono_type (type);
6333
6334         /*we must avoid using @type as it might have come
6335          * from a mono_metadata_type_dup and the caller
6336          * expects that is can be freed.
6337          * Using the right type from 
6338          */
6339         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6340
6341         /* void is very common */
6342         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6343                 return (MonoReflectionType*)domain->typeof_void;
6344
6345         /*
6346          * If the vtable of the given class was already created, we can use
6347          * the MonoType from there and avoid all locking and hash table lookups.
6348          * 
6349          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6350          * that the resulting object is different.   
6351          */
6352         if (type == &klass->byval_arg && !klass->image->dynamic) {
6353                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6354                 if (vtable && vtable->type)
6355                         return vtable->type;
6356         }
6357
6358         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6359         mono_domain_lock (domain);
6360         if (!domain->type_hash)
6361                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6362                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6363         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6364                 mono_domain_unlock (domain);
6365                 mono_loader_unlock ();
6366                 return res;
6367         }
6368         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6369         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6370                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6371                 mono_g_hash_table_insert (domain->type_hash, type, res);
6372                 mono_domain_unlock (domain);
6373                 mono_loader_unlock ();
6374                 return res;
6375         }
6376
6377         if (!verify_safe_for_managed_space (type)) {
6378                 mono_domain_unlock (domain);
6379                 mono_loader_unlock ();
6380                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6381         }
6382
6383         if (klass->reflection_info && !klass->wastypebuilder) {
6384                 gboolean is_type_done = TRUE;
6385                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6386                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6387                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6388                 */
6389                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6390                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6391
6392                         if (gparam->owner && gparam->owner->is_method) {
6393                                 MonoMethod *method = gparam->owner->owner.method;
6394                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6395                                         is_type_done = FALSE;
6396                         } else if (gparam->owner && !gparam->owner->is_method) {
6397                                 MonoClass *klass = gparam->owner->owner.klass;
6398                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6399                                         is_type_done = FALSE;
6400                         }
6401                 } 
6402
6403                 /* g_assert_not_reached (); */
6404                 /* should this be considered an error condition? */
6405                 if (is_type_done && !type->byref) {
6406                         mono_domain_unlock (domain);
6407                         mono_loader_unlock ();
6408                         return klass->reflection_info;
6409                 }
6410         }
6411         // FIXME: Get rid of this, do it in the icalls for Type
6412         mono_class_init (klass);
6413 #ifdef HAVE_SGEN_GC
6414         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6415 #else
6416         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6417 #endif
6418         res->type = type;
6419         mono_g_hash_table_insert (domain->type_hash, type, res);
6420
6421         if (type->type == MONO_TYPE_VOID)
6422                 domain->typeof_void = (MonoObject*)res;
6423
6424         mono_domain_unlock (domain);
6425         mono_loader_unlock ();
6426         return res;
6427 }
6428
6429 /*
6430  * mono_method_get_object:
6431  * @domain: an app domain
6432  * @method: a method
6433  * @refclass: the reflected type (can be NULL)
6434  *
6435  * Return an System.Reflection.MonoMethod object representing the method @method.
6436  */
6437 MonoReflectionMethod*
6438 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6439 {
6440         /*
6441          * We use the same C representation for methods and constructors, but the type 
6442          * name in C# is different.
6443          */
6444         static MonoClass *System_Reflection_MonoMethod = NULL;
6445         static MonoClass *System_Reflection_MonoCMethod = NULL;
6446         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6447         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6448         MonoClass *klass;
6449         MonoReflectionMethod *ret;
6450
6451         if (method->is_inflated) {
6452                 MonoReflectionGenericMethod *gret;
6453
6454                 refclass = method->klass;
6455                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6456                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6457                         if (!System_Reflection_MonoGenericCMethod)
6458                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6459                         klass = System_Reflection_MonoGenericCMethod;
6460                 } else {
6461                         if (!System_Reflection_MonoGenericMethod)
6462                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6463                         klass = System_Reflection_MonoGenericMethod;
6464                 }
6465                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6466                 gret->method.method = method;
6467                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6468                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6469                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6470         }
6471
6472         if (!refclass)
6473                 refclass = method->klass;
6474
6475         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6476         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6477                 if (!System_Reflection_MonoCMethod)
6478                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6479                 klass = System_Reflection_MonoCMethod;
6480         }
6481         else {
6482                 if (!System_Reflection_MonoMethod)
6483                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6484                 klass = System_Reflection_MonoMethod;
6485         }
6486         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6487         ret->method = method;
6488         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6489         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6490 }
6491
6492 /*
6493  * mono_method_clear_object:
6494  *
6495  *   Clear the cached reflection objects for the dynamic method METHOD.
6496  */
6497 void
6498 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6499 {
6500         MonoClass *klass;
6501         g_assert (method->dynamic);
6502
6503         klass = method->klass;
6504         while (klass) {
6505                 clear_cached_object (domain, method, klass);
6506                 klass = klass->parent;
6507         }
6508         /* Added by mono_param_get_objects () */
6509         clear_cached_object (domain, &(method->signature), NULL);
6510         klass = method->klass;
6511         while (klass) {
6512                 clear_cached_object (domain, &(method->signature), klass);
6513                 klass = klass->parent;
6514         }
6515 }
6516
6517 /*
6518  * mono_field_get_object:
6519  * @domain: an app domain
6520  * @klass: a type
6521  * @field: a field
6522  *
6523  * Return an System.Reflection.MonoField object representing the field @field
6524  * in class @klass.
6525  */
6526 MonoReflectionField*
6527 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6528 {
6529         MonoReflectionField *res;
6530         static MonoClass *monofield_klass;
6531
6532         CHECK_OBJECT (MonoReflectionField *, field, klass);
6533         if (!monofield_klass)
6534                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6535         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6536         res->klass = klass;
6537         res->field = field;
6538         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6539         if (is_field_on_inst (field))
6540                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6541         else
6542                 res->attrs = field->type->attrs;
6543         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6544         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6545 }
6546
6547 /*
6548  * mono_property_get_object:
6549  * @domain: an app domain
6550  * @klass: a type
6551  * @property: a property
6552  *
6553  * Return an System.Reflection.MonoProperty object representing the property @property
6554  * in class @klass.
6555  */
6556 MonoReflectionProperty*
6557 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6558 {
6559         MonoReflectionProperty *res;
6560         static MonoClass *monoproperty_klass;
6561
6562         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6563         if (!monoproperty_klass)
6564                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6565         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6566         res->klass = klass;
6567         res->property = property;
6568         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6569 }
6570
6571 /*
6572  * mono_event_get_object:
6573  * @domain: an app domain
6574  * @klass: a type
6575  * @event: a event
6576  *
6577  * Return an System.Reflection.MonoEvent object representing the event @event
6578  * in class @klass.
6579  */
6580 MonoReflectionEvent*
6581 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6582 {
6583         MonoReflectionEvent *res;
6584         MonoReflectionMonoEvent *mono_event;
6585         static MonoClass *monoevent_klass;
6586
6587         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6588         if (!monoevent_klass)
6589                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6590         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6591         mono_event->klass = klass;
6592         mono_event->event = event;
6593         res = (MonoReflectionEvent*)mono_event;
6594         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6595 }
6596
6597 /**
6598  * mono_get_reflection_missing_object:
6599  * @domain: Domain where the object lives
6600  *
6601  * Returns the System.Reflection.Missing.Value singleton object
6602  * (of type System.Reflection.Missing).
6603  *
6604  * Used as the value for ParameterInfo.DefaultValue when Optional
6605  * is present
6606  */
6607 static MonoObject *
6608 mono_get_reflection_missing_object (MonoDomain *domain)
6609 {
6610         MonoObject *obj;
6611         static MonoClassField *missing_value_field = NULL;
6612         
6613         if (!missing_value_field) {
6614                 MonoClass *missing_klass;
6615                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6616                 mono_class_init (missing_klass);
6617                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6618                 g_assert (missing_value_field);
6619         }
6620         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6621         g_assert (obj);
6622         return obj;
6623 }
6624
6625 static MonoObject*
6626 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6627 {
6628         if (!*dbnull)
6629                 *dbnull = mono_get_dbnull_object (domain);
6630         return *dbnull;
6631 }
6632
6633 static MonoObject*
6634 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6635 {
6636         if (!*reflection_missing)
6637                 *reflection_missing = mono_get_reflection_missing_object (domain);
6638         return *reflection_missing;
6639 }
6640
6641 /*
6642  * mono_param_get_objects:
6643  * @domain: an app domain
6644  * @method: a method
6645  *
6646  * Return an System.Reflection.ParameterInfo array object representing the parameters
6647  * in the method @method.
6648  */
6649 MonoArray*
6650 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6651 {
6652         static MonoClass *System_Reflection_ParameterInfo;
6653         static MonoClass *System_Reflection_ParameterInfo_array;
6654         MonoArray *res = NULL;
6655         MonoReflectionMethod *member = NULL;
6656         MonoReflectionParameter *param = NULL;
6657         char **names, **blobs = NULL;
6658         guint32 *types = NULL;
6659         MonoType *type = NULL;
6660         MonoObject *dbnull = NULL;
6661         MonoObject *missing = NULL;
6662         MonoMarshalSpec **mspecs;
6663         MonoMethodSignature *sig;
6664         MonoVTable *pinfo_vtable;
6665         int i;
6666
6667         if (!System_Reflection_ParameterInfo_array) {
6668                 MonoClass *klass;
6669
6670                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6671                 mono_memory_barrier ();
6672                 System_Reflection_ParameterInfo = klass; 
6673         
6674                 klass = mono_array_class_get (klass, 1);
6675                 mono_memory_barrier ();
6676                 System_Reflection_ParameterInfo_array = klass;
6677         }
6678         
6679         if (!mono_method_signature (method)->param_count)
6680                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6681
6682         /* Note: the cache is based on the address of the signature into the method
6683          * since we already cache MethodInfos with the method as keys.
6684          */
6685         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6686
6687         sig = mono_method_signature (method);
6688         member = mono_method_get_object (domain, method, refclass);
6689         names = g_new (char *, sig->param_count);
6690         mono_method_get_param_names (method, (const char **) names);
6691
6692         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6693         mono_method_get_marshal_info (method, mspecs);
6694
6695         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6696         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6697         for (i = 0; i < sig->param_count; ++i) {
6698                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6699                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6700                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6701                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6702                 param->PositionImpl = i;
6703                 param->AttrsImpl = sig->params [i]->attrs;
6704
6705                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6706                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6707                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6708                         else
6709                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6710                 } else {
6711
6712                         if (!blobs) {
6713                                 blobs = g_new0 (char *, sig->param_count);
6714                                 types = g_new0 (guint32, sig->param_count);
6715                                 get_default_param_value_blobs (method, blobs, types); 
6716                         }
6717
6718                         /* Build MonoType for the type from the Constant Table */
6719                         if (!type)
6720                                 type = g_new0 (MonoType, 1);
6721                         type->type = types [i];
6722                         type->data.klass = NULL;
6723                         if (types [i] == MONO_TYPE_CLASS)
6724                                 type->data.klass = mono_defaults.object_class;
6725                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6726                                 /* For enums, types [i] contains the base type */
6727
6728                                         type->type = MONO_TYPE_VALUETYPE;
6729                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6730                         } else
6731                                 type->data.klass = mono_class_from_mono_type (type);
6732
6733                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6734
6735                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6736                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6737                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6738                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6739                                 else
6740                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6741                         }
6742                         
6743                 }
6744
6745                 if (mspecs [i + 1])
6746                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6747                 
6748                 mono_array_setref (res, i, param);
6749         }
6750         g_free (names);
6751         g_free (blobs);
6752         g_free (types);
6753         g_free (type);
6754
6755         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6756                 if (mspecs [i])
6757                         mono_metadata_free_marshal_spec (mspecs [i]);
6758         g_free (mspecs);
6759         
6760         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6761 }
6762
6763 MonoArray*
6764 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6765 {
6766         return mono_param_get_objects_internal (domain, method, NULL);
6767 }
6768
6769 /*
6770  * mono_method_body_get_object:
6771  * @domain: an app domain
6772  * @method: a method
6773  *
6774  * Return an System.Reflection.MethodBody object representing the method @method.
6775  */
6776 MonoReflectionMethodBody*
6777 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6778 {
6779         static MonoClass *System_Reflection_MethodBody = NULL;
6780         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6781         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6782         MonoReflectionMethodBody *ret;
6783         MonoMethodNormal *mn;
6784         MonoMethodHeader *header;
6785         guint32 method_rva, local_var_sig_token;
6786     char *ptr;
6787         unsigned char format, flags;
6788         int i;
6789
6790         if (!System_Reflection_MethodBody)
6791                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6792         if (!System_Reflection_LocalVariableInfo)
6793                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6794         if (!System_Reflection_ExceptionHandlingClause)
6795                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6796
6797         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6798
6799         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6800                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6801             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6802             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6803                 return NULL;
6804         mn = (MonoMethodNormal *)method;
6805         header = mono_method_get_header (method);
6806         
6807         /* Obtain local vars signature token */
6808         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6809         ptr = mono_image_rva_map (method->klass->image, method_rva);
6810         flags = *(const unsigned char *) ptr;
6811         format = flags & METHOD_HEADER_FORMAT_MASK;
6812         switch (format){
6813         case METHOD_HEADER_TINY_FORMAT:
6814                 local_var_sig_token = 0;
6815                 break;
6816         case METHOD_HEADER_FAT_FORMAT:
6817                 ptr += 2;
6818                 ptr += 2;
6819                 ptr += 4;
6820                 local_var_sig_token = read32 (ptr);
6821                 break;
6822         default:
6823                 g_assert_not_reached ();
6824         }
6825
6826         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6827
6828         ret->init_locals = header->init_locals;
6829         ret->max_stack = header->max_stack;
6830         ret->local_var_sig_token = local_var_sig_token;
6831         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6832         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6833
6834         /* Locals */
6835         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6836         for (i = 0; i < header->num_locals; ++i) {
6837                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6838                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6839                 info->is_pinned = header->locals [i]->pinned;
6840                 info->local_index = i;
6841                 mono_array_setref (ret->locals, i, info);
6842         }
6843
6844         /* Exceptions */
6845         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6846         for (i = 0; i < header->num_clauses; ++i) {
6847                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6848                 MonoExceptionClause *clause = &header->clauses [i];
6849
6850                 info->flags = clause->flags;
6851                 info->try_offset = clause->try_offset;
6852                 info->try_length = clause->try_len;
6853                 info->handler_offset = clause->handler_offset;
6854                 info->handler_length = clause->handler_len;
6855                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6856                         info->filter_offset = clause->data.filter_offset;
6857                 else if (clause->data.catch_class)
6858                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6859
6860                 mono_array_setref (ret->clauses, i, info);
6861         }
6862
6863         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6864         return ret;
6865 }
6866
6867 /**
6868  * mono_get_dbnull_object:
6869  * @domain: Domain where the object lives
6870  *
6871  * Returns the System.DBNull.Value singleton object
6872  *
6873  * Used as the value for ParameterInfo.DefaultValue 
6874  */
6875 MonoObject *
6876 mono_get_dbnull_object (MonoDomain *domain)
6877 {
6878         MonoObject *obj;
6879         static MonoClassField *dbnull_value_field = NULL;
6880         
6881         if (!dbnull_value_field) {
6882                 MonoClass *dbnull_klass;
6883                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6884                 mono_class_init (dbnull_klass);
6885                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6886                 g_assert (dbnull_value_field);
6887         }
6888         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6889         g_assert (obj);
6890         return obj;
6891 }
6892
6893 static void
6894 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6895 {
6896         guint32 param_index, i, lastp, crow = 0;
6897         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6898         gint32 idx;
6899
6900         MonoClass *klass = method->klass;
6901         MonoImage *image = klass->image;
6902         MonoMethodSignature *methodsig = mono_method_signature (method);
6903
6904         MonoTableInfo *constt;
6905         MonoTableInfo *methodt;
6906         MonoTableInfo *paramt;
6907
6908         if (!methodsig->param_count)
6909                 return;
6910
6911         mono_class_init (klass);
6912
6913         if (klass->image->dynamic) {
6914                 MonoReflectionMethodAux *aux;
6915                 if (method->is_inflated)
6916                         method = ((MonoMethodInflated*)method)->declaring;
6917                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6918                 if (aux && aux->param_defaults) {
6919                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6920                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6921                 }
6922                 return;
6923         }
6924
6925         methodt = &klass->image->tables [MONO_TABLE_METHOD];
6926         paramt = &klass->image->tables [MONO_TABLE_PARAM];
6927         constt = &image->tables [MONO_TABLE_CONSTANT];
6928
6929         idx = mono_method_get_index (method) - 1;
6930         g_assert (idx != -1);
6931
6932         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6933         if (idx + 1 < methodt->rows)
6934                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6935         else
6936                 lastp = paramt->rows + 1;
6937
6938         for (i = param_index; i < lastp; ++i) {
6939                 guint32 paramseq;
6940
6941                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6942                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6943
6944                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
6945                         continue;
6946
6947                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6948                 if (!crow) {
6949                         continue;
6950                 }
6951         
6952                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6953                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6954                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6955         }
6956
6957         return;
6958 }
6959
6960 static MonoObject *
6961 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6962 {
6963         void *retval;
6964         MonoClass *klass;
6965         MonoObject *object;
6966         MonoType *basetype = type;
6967
6968         if (!blob)
6969                 return NULL;
6970         
6971         klass = mono_class_from_mono_type (type);
6972         if (klass->valuetype) {
6973                 object = mono_object_new (domain, klass);
6974                 retval = ((gchar *) object + sizeof (MonoObject));
6975                 if (klass->enumtype)
6976                         basetype = mono_class_enum_basetype (klass);
6977         } else {
6978                 retval = &object;
6979         }
6980                         
6981         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
6982                 return object;
6983         else
6984                 return NULL;
6985 }
6986
6987 static int
6988 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6989         int found_sep;
6990         char *s;
6991
6992         memset (assembly, 0, sizeof (MonoAssemblyName));
6993         assembly->name = p;
6994         assembly->culture = "";
6995         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6996
6997         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6998                 p++;
6999         found_sep = 0;
7000         while (g_ascii_isspace (*p) || *p == ',') {
7001                 *p++ = 0;
7002                 found_sep = 1;
7003                 continue;
7004         }
7005         /* failed */
7006         if (!found_sep)
7007                 return 1;
7008         while (*p) {
7009                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7010                         p += 8;
7011                         assembly->major = strtoul (p, &s, 10);
7012                         if (s == p || *s != '.')
7013                                 return 1;
7014                         p = ++s;
7015                         assembly->minor = strtoul (p, &s, 10);
7016                         if (s == p || *s != '.')
7017                                 return 1;
7018                         p = ++s;
7019                         assembly->build = strtoul (p, &s, 10);
7020                         if (s == p || *s != '.')
7021                                 return 1;
7022                         p = ++s;
7023                         assembly->revision = strtoul (p, &s, 10);
7024                         if (s == p)
7025                                 return 1;
7026                         p = s;
7027                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7028                         p += 8;
7029                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7030                                 assembly->culture = "";
7031                                 p += 7;
7032                         } else {
7033                                 assembly->culture = p;
7034                                 while (*p && *p != ',') {
7035                                         p++;
7036                                 }
7037                         }
7038                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7039                         p += 15;
7040                         if (strncmp (p, "null", 4) == 0) {
7041                                 p += 4;
7042                         } else {
7043                                 int len;
7044                                 gchar *start = p;
7045                                 while (*p && *p != ',') {
7046                                         p++;
7047                                 }
7048                                 len = (p - start + 1);
7049                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7050                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7051                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7052                         }
7053                 } else {
7054                         while (*p && *p != ',')
7055                                 p++;
7056                 }
7057                 found_sep = 0;
7058                 while (g_ascii_isspace (*p) || *p == ',') {
7059                         *p++ = 0;
7060                         found_sep = 1;
7061                         continue;
7062                 }
7063                 /* failed */
7064                 if (!found_sep)
7065                         return 1;
7066         }
7067
7068         return 0;
7069 }
7070
7071 /*
7072  * mono_reflection_parse_type:
7073  * @name: type name
7074  *
7075  * Parse a type name as accepted by the GetType () method and output the info
7076  * extracted in the info structure.
7077  * the name param will be mangled, so, make a copy before passing it to this function.
7078  * The fields in info will be valid until the memory pointed to by name is valid.
7079  *
7080  * See also mono_type_get_name () below.
7081  *
7082  * Returns: 0 on parse error.
7083  */
7084 static int
7085 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7086                              MonoTypeNameParse *info)
7087 {
7088         char *start, *p, *w, *temp, *last_point, *startn;
7089         int in_modifiers = 0;
7090         int isbyref = 0, rank, arity = 0, i;
7091
7092         start = p = w = name;
7093
7094         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7095         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7096         info->name = info->name_space = NULL;
7097         info->nested = NULL;
7098         info->modifiers = NULL;
7099         info->type_arguments = NULL;
7100
7101         /* last_point separates the namespace from the name */
7102         last_point = NULL;
7103         /* Skips spaces */
7104         while (*p == ' ') p++, start++, w++, name++;
7105
7106         while (*p) {
7107                 switch (*p) {
7108                 case '+':
7109                         *p = 0; /* NULL terminate the name */
7110                         startn = p + 1;
7111                         info->nested = g_list_append (info->nested, startn);
7112                         /* we have parsed the nesting namespace + name */
7113                         if (info->name)
7114                                 break;
7115                         if (last_point) {
7116                                 info->name_space = start;
7117                                 *last_point = 0;
7118                                 info->name = last_point + 1;
7119                         } else {
7120                                 info->name_space = (char *)"";
7121                                 info->name = start;
7122                         }
7123                         break;
7124                 case '.':
7125                         last_point = p;
7126                         break;
7127                 case '\\':
7128                         ++p;
7129                         break;
7130                 case '&':
7131                 case '*':
7132                 case '[':
7133                 case ',':
7134                 case ']':
7135                         in_modifiers = 1;
7136                         break;
7137                 case '`':
7138                         ++p;
7139                         i = strtol (p, &temp, 10);
7140                         arity += i;
7141                         if (p == temp)
7142                                 return 0;
7143                         p = temp-1;
7144                         break;
7145                 default:
7146                         break;
7147                 }
7148                 if (in_modifiers)
7149                         break;
7150                 // *w++ = *p++;
7151                 p++;
7152         }
7153         
7154         if (!info->name) {
7155                 if (last_point) {
7156                         info->name_space = start;
7157                         *last_point = 0;
7158                         info->name = last_point + 1;
7159                 } else {
7160                         info->name_space = (char *)"";
7161                         info->name = start;
7162                 }
7163         }
7164         while (*p) {
7165                 switch (*p) {
7166                 case '&':
7167                         if (isbyref) /* only one level allowed by the spec */
7168                                 return 0;
7169                         isbyref = 1;
7170                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7171                         *p++ = 0;
7172                         break;
7173                 case '*':
7174                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7175                         *p++ = 0;
7176                         break;
7177                 case '[':
7178                         if (arity != 0) {
7179                                 *p++ = 0;
7180                                 info->type_arguments = g_ptr_array_new ();
7181                                 for (i = 0; i < arity; i++) {
7182                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7183                                         gboolean fqname = FALSE;
7184
7185                                         g_ptr_array_add (info->type_arguments, subinfo);
7186
7187                                         if (*p == '[') {
7188                                                 p++;
7189                                                 fqname = TRUE;
7190                                         }
7191
7192                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7193                                                 return 0;
7194
7195                                         if (fqname) {
7196                                                 char *aname;
7197
7198                                                 if (*p != ',')
7199                                                         return 0;
7200                                                 *p++ = 0;
7201
7202                                                 aname = p;
7203                                                 while (*p && (*p != ']'))
7204                                                         p++;
7205
7206                                                 if (*p != ']')
7207                                                         return 0;
7208
7209                                                 *p++ = 0;
7210                                                 while (*aname) {
7211                                                         if (g_ascii_isspace (*aname)) {
7212                                                                 ++aname;
7213                                                                 continue;
7214                                                         }
7215                                                         break;
7216                                                 }
7217                                                 if (!*aname ||
7218                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7219                                                         return 0;
7220                                         }
7221
7222                                         if (i + 1 < arity) {
7223                                                 if (*p != ',')
7224                                                         return 0;
7225                                         } else {
7226                                                 if (*p != ']')
7227                                                         return 0;
7228                                         }
7229                                         *p++ = 0;
7230                                 }
7231
7232                                 arity = 0;
7233                                 break;
7234                         }
7235                         rank = 1;
7236                         *p++ = 0;
7237                         while (*p) {
7238                                 if (*p == ']')
7239                                         break;
7240                                 if (*p == ',')
7241                                         rank++;
7242                                 else if (*p == '*') /* '*' means unknown lower bound */
7243                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7244                                 else
7245                                         return 0;
7246                                 ++p;
7247                         }
7248                         if (*p++ != ']')
7249                                 return 0;
7250                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7251                         break;
7252                 case ']':
7253                         if (is_recursed)
7254                                 goto end;
7255                         return 0;
7256                 case ',':
7257                         if (is_recursed)
7258                                 goto end;
7259                         *p++ = 0;
7260                         while (*p) {
7261                                 if (g_ascii_isspace (*p)) {
7262                                         ++p;
7263                                         continue;
7264                                 }
7265                                 break;
7266                         }
7267                         if (!*p)
7268                                 return 0; /* missing assembly name */
7269                         if (!assembly_name_to_aname (&info->assembly, p))
7270                                 return 0;
7271                         break;
7272                 default:
7273                         return 0;
7274                 }
7275                 if (info->assembly.name)
7276                         break;
7277         }
7278         // *w = 0; /* terminate class name */
7279  end:
7280         if (!info->name || !*info->name)
7281                 return 0;
7282         if (endptr)
7283                 *endptr = p;
7284         /* add other consistency checks */
7285         return 1;
7286 }
7287
7288 int
7289 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7290 {
7291         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7292 }
7293
7294 static MonoType*
7295 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7296 {
7297         gboolean type_resolve = FALSE;
7298         MonoType *type;
7299         MonoImage *rootimage = image;
7300
7301         if (info->assembly.name) {
7302                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7303                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7304                         /* 
7305                          * This could happen in the AOT compiler case when the search hook is not
7306                          * installed.
7307                          */
7308                         assembly = image->assembly;
7309                 if (!assembly) {
7310                         /* then we must load the assembly ourselve - see #60439 */
7311                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7312                         if (!assembly)
7313                                 return NULL;
7314                 }
7315                 image = assembly->image;
7316         } else if (!image) {
7317                 image = mono_defaults.corlib;
7318         }
7319
7320         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7321         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7322                 image = mono_defaults.corlib;
7323                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7324         }
7325
7326         return type;
7327 }
7328
7329 static MonoType*
7330 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7331 {
7332         MonoClass *klass;
7333         GList *mod;
7334         int modval;
7335         gboolean bounded = FALSE;
7336         
7337         if (!image)
7338                 image = mono_defaults.corlib;
7339
7340         if (ignorecase)
7341                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7342         else
7343                 klass = mono_class_from_name (image, info->name_space, info->name);
7344         if (!klass)
7345                 return NULL;
7346         for (mod = info->nested; mod; mod = mod->next) {
7347                 gpointer iter = NULL;
7348                 MonoClass *parent;
7349
7350                 parent = klass;
7351                 mono_class_init (parent);
7352
7353                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7354                         if (ignorecase) {
7355                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7356                                         break;
7357                         } else {
7358                                 if (strcmp (klass->name, mod->data) == 0)
7359                                         break;
7360                         }
7361                 }
7362                 if (!klass)
7363                         break;
7364         }
7365         if (!klass)
7366                 return NULL;
7367         mono_class_init (klass);
7368
7369         if (info->type_arguments) {
7370                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7371                 MonoReflectionType *the_type;
7372                 MonoType *instance;
7373                 int i;
7374
7375                 for (i = 0; i < info->type_arguments->len; i++) {
7376                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7377
7378                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7379                         if (!type_args [i]) {
7380                                 g_free (type_args);
7381                                 return NULL;
7382                         }
7383                 }
7384
7385                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7386
7387                 instance = mono_reflection_bind_generic_parameters (
7388                         the_type, info->type_arguments->len, type_args);
7389
7390                 g_free (type_args);
7391                 if (!instance)
7392                         return NULL;
7393
7394                 klass = mono_class_from_mono_type (instance);
7395         }
7396
7397         for (mod = info->modifiers; mod; mod = mod->next) {
7398                 modval = GPOINTER_TO_UINT (mod->data);
7399                 if (!modval) { /* byref: must be last modifier */
7400                         return &klass->this_arg;
7401                 } else if (modval == -1) {
7402                         klass = mono_ptr_class_get (&klass->byval_arg);
7403                 } else if (modval == -2) {
7404                         bounded = TRUE;
7405                 } else { /* array rank */
7406                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7407                 }
7408                 mono_class_init (klass);
7409         }
7410
7411         return &klass->byval_arg;
7412 }
7413
7414 /*
7415  * mono_reflection_get_type:
7416  * @image: a metadata context
7417  * @info: type description structure
7418  * @ignorecase: flag for case-insensitive string compares
7419  * @type_resolve: whenever type resolve was already tried
7420  *
7421  * Build a MonoType from the type description in @info.
7422  * 
7423  */
7424
7425 MonoType*
7426 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7427         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7428 }
7429
7430 static MonoType*
7431 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7432 {
7433         MonoReflectionAssemblyBuilder *abuilder;
7434         MonoType *type;
7435         int i;
7436
7437         g_assert (assembly->dynamic);
7438         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7439
7440         /* Enumerate all modules */
7441
7442         type = NULL;
7443         if (abuilder->modules) {
7444                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7445                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7446                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7447                         if (type)
7448                                 break;
7449                 }
7450         }
7451
7452         if (!type && abuilder->loaded_modules) {
7453                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7454                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7455                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7456                         if (type)
7457                                 break;
7458                 }
7459         }
7460
7461         return type;
7462 }
7463         
7464 MonoType*
7465 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7466 {
7467         MonoType *type;
7468         MonoReflectionAssembly *assembly;
7469         GString *fullName;
7470         GList *mod;
7471
7472         if (image && image->dynamic)
7473                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7474         else
7475                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7476         if (type)
7477                 return type;
7478         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7479                 return NULL;
7480
7481         if (type_resolve) {
7482                 if (*type_resolve) 
7483                         return NULL;
7484                 else
7485                         *type_resolve = TRUE;
7486         }
7487         
7488         /* Reconstruct the type name */
7489         fullName = g_string_new ("");
7490         if (info->name_space && (info->name_space [0] != '\0'))
7491                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7492         else
7493                 g_string_printf (fullName, "%s", info->name);
7494         for (mod = info->nested; mod; mod = mod->next)
7495                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7496
7497         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7498         if (assembly) {
7499                 if (assembly->assembly->dynamic)
7500                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7501                 else
7502                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7503                                                                                                           info, ignorecase);
7504         }
7505         g_string_free (fullName, TRUE);
7506         return type;
7507 }
7508
7509 void
7510 mono_reflection_free_type_info (MonoTypeNameParse *info)
7511 {
7512         g_list_free (info->modifiers);
7513         g_list_free (info->nested);
7514
7515         if (info->type_arguments) {
7516                 int i;
7517
7518                 for (i = 0; i < info->type_arguments->len; i++) {
7519                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7520
7521                         mono_reflection_free_type_info (subinfo);
7522                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7523                         g_free (subinfo);
7524                 }
7525
7526                 g_ptr_array_free (info->type_arguments, TRUE);
7527         }
7528 }
7529
7530 /*
7531  * mono_reflection_type_from_name:
7532  * @name: type name.
7533  * @image: a metadata context (can be NULL).
7534  *
7535  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7536  * it defaults to get the type from @image or, if @image is NULL or loading
7537  * from it fails, uses corlib.
7538  * 
7539  */
7540 MonoType*
7541 mono_reflection_type_from_name (char *name, MonoImage *image)
7542 {
7543         MonoType *type = NULL;
7544         MonoTypeNameParse info;
7545         char *tmp;
7546
7547         /* Make a copy since parse_type modifies its argument */
7548         tmp = g_strdup (name);
7549         
7550         /*g_print ("requested type %s\n", str);*/
7551         if (mono_reflection_parse_type (tmp, &info)) {
7552                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7553         }
7554
7555         g_free (tmp);
7556         mono_reflection_free_type_info (&info);
7557         return type;
7558 }
7559
7560 /*
7561  * mono_reflection_get_token:
7562  *
7563  *   Return the metadata token of OBJ which should be an object
7564  * representing a metadata element.
7565  */
7566 guint32
7567 mono_reflection_get_token (MonoObject *obj)
7568 {
7569         MonoClass *klass;
7570         guint32 token = 0;
7571
7572         klass = obj->vtable->klass;
7573
7574         if (strcmp (klass->name, "MethodBuilder") == 0) {
7575                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7576
7577                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7578         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7579                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7580
7581                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7582         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7583                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7584
7585                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7586                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7587         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7588                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7589                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7590         } else if (strcmp (klass->name, "MonoType") == 0) {
7591                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7592                 token = mono_class_from_mono_type (type)->type_token;
7593         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7594                    strcmp (klass->name, "MonoMethod") == 0 ||
7595                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7596                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7597                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7598                 if (m->method->is_inflated) {
7599                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7600                         return inflated->declaring->token;
7601                 } else {
7602                         token = m->method->token;
7603                 }
7604         } else if (strcmp (klass->name, "MonoField") == 0) {
7605                 MonoReflectionField *f = (MonoReflectionField*)obj;
7606
7607                 if (is_field_on_inst (f->field)) {
7608                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7609                         int field_index = f->field - dgclass->fields;
7610                         MonoObject *obj;
7611
7612                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7613                         obj = dgclass->field_objects [field_index];
7614                         return mono_reflection_get_token (obj);
7615                 }
7616                 token = mono_class_get_field_token (f->field);
7617         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7618                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7619
7620                 token = mono_class_get_property_token (p->property);
7621         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7622                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7623
7624                 token = mono_class_get_event_token (p->event);
7625         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7626                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7627
7628                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7629         } else if (strcmp (klass->name, "Module") == 0) {
7630                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7631
7632                 token = m->token;
7633         } else if (strcmp (klass->name, "Assembly") == 0) {
7634                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7635         } else {
7636                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7637                 MonoException *ex = mono_get_exception_not_implemented (msg);
7638                 g_free (msg);
7639                 mono_raise_exception (ex);
7640         }
7641
7642         return token;
7643 }
7644
7645 static void*
7646 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7647 {
7648         int slen, type = t->type;
7649         MonoClass *tklass = t->data.klass;
7650
7651 handle_enum:
7652         switch (type) {
7653         case MONO_TYPE_U1:
7654         case MONO_TYPE_I1:
7655         case MONO_TYPE_BOOLEAN: {
7656                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7657                 *bval = *p;
7658                 *end = p + 1;
7659                 return bval;
7660         }
7661         case MONO_TYPE_CHAR:
7662         case MONO_TYPE_U2:
7663         case MONO_TYPE_I2: {
7664                 guint16 *val = g_malloc (sizeof (guint16));
7665                 *val = read16 (p);
7666                 *end = p + 2;
7667                 return val;
7668         }
7669 #if SIZEOF_VOID_P == 4
7670         case MONO_TYPE_U:
7671         case MONO_TYPE_I:
7672 #endif
7673         case MONO_TYPE_R4:
7674         case MONO_TYPE_U4:
7675         case MONO_TYPE_I4: {
7676                 guint32 *val = g_malloc (sizeof (guint32));
7677                 *val = read32 (p);
7678                 *end = p + 4;
7679                 return val;
7680         }
7681 #if SIZEOF_VOID_P == 8
7682         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7683         case MONO_TYPE_I:
7684 #endif
7685         case MONO_TYPE_U8:
7686         case MONO_TYPE_I8: {
7687                 guint64 *val = g_malloc (sizeof (guint64));
7688                 *val = read64 (p);
7689                 *end = p + 8;
7690                 return val;
7691         }
7692         case MONO_TYPE_R8: {
7693                 double *val = g_malloc (sizeof (double));
7694                 readr8 (p, val);
7695                 *end = p + 8;
7696                 return val;
7697         }
7698         case MONO_TYPE_VALUETYPE:
7699                 if (t->data.klass->enumtype) {
7700                         type = mono_class_enum_basetype (t->data.klass)->type;
7701                         goto handle_enum;
7702                 } else {
7703                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7704                 }
7705                 break;
7706         case MONO_TYPE_STRING:
7707                 if (*p == (char)0xFF) {
7708                         *end = p + 1;
7709                         return NULL;
7710                 }
7711                 slen = mono_metadata_decode_value (p, &p);
7712                 *end = p + slen;
7713                 return mono_string_new_len (mono_domain_get (), p, slen);
7714         case MONO_TYPE_CLASS: {
7715                 char *n;
7716                 MonoType *t;
7717                 if (*p == (char)0xFF) {
7718                         *end = p + 1;
7719                         return NULL;
7720                 }
7721 handle_type:
7722                 slen = mono_metadata_decode_value (p, &p);
7723                 n = g_memdup (p, slen + 1);
7724                 n [slen] = 0;
7725                 t = mono_reflection_type_from_name (n, image);
7726                 if (!t)
7727                         g_warning ("Cannot load type '%s'", n);
7728                 g_free (n);
7729                 *end = p + slen;
7730                 if (t)
7731                         return mono_type_get_object (mono_domain_get (), t);
7732                 else
7733                         return NULL;
7734         }
7735         case MONO_TYPE_OBJECT: {
7736                 char subt = *p++;
7737                 MonoObject *obj;
7738                 MonoClass *subc = NULL;
7739                 void *val;
7740
7741                 if (subt == 0x50) {
7742                         goto handle_type;
7743                 } else if (subt == 0x0E) {
7744                         type = MONO_TYPE_STRING;
7745                         goto handle_enum;
7746                 } else if (subt == 0x1D) {
7747                         MonoType simple_type = {{0}};
7748                         int etype = *p;
7749                         p ++;
7750
7751                         if (etype == 0x51)
7752                                 /* See Partition II, Appendix B3 */
7753                                 etype = MONO_TYPE_OBJECT;
7754                         type = MONO_TYPE_SZARRAY;
7755                         simple_type.type = etype;
7756                         tklass = mono_class_from_mono_type (&simple_type);
7757                         goto handle_enum;
7758                 } else if (subt == 0x55) {
7759                         char *n;
7760                         MonoType *t;
7761                         slen = mono_metadata_decode_value (p, &p);
7762                         n = g_memdup (p, slen + 1);
7763                         n [slen] = 0;
7764                         t = mono_reflection_type_from_name (n, image);
7765                         if (!t)
7766                                 g_error ("Cannot load type '%s'", n);
7767                         g_free (n);
7768                         p += slen;
7769                         subc = mono_class_from_mono_type (t);
7770                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7771                         MonoType simple_type = {{0}};
7772                         simple_type.type = subt;
7773                         subc = mono_class_from_mono_type (&simple_type);
7774                 } else {
7775                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7776                 }
7777                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7778                 obj = mono_object_new (mono_domain_get (), subc);
7779                 g_assert (!subc->has_references);
7780                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7781                 g_free (val);
7782                 return obj;
7783         }
7784         case MONO_TYPE_SZARRAY: {
7785                 MonoArray *arr;
7786                 guint32 i, alen, basetype;
7787                 alen = read32 (p);
7788                 p += 4;
7789                 if (alen == 0xffffffff) {
7790                         *end = p;
7791                         return NULL;
7792                 }
7793                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7794                 basetype = tklass->byval_arg.type;
7795                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7796                         basetype = mono_class_enum_basetype (tklass)->type;
7797                 switch (basetype)
7798                 {
7799                         case MONO_TYPE_U1:
7800                         case MONO_TYPE_I1:
7801                         case MONO_TYPE_BOOLEAN:
7802                                 for (i = 0; i < alen; i++) {
7803                                         MonoBoolean val = *p++;
7804                                         mono_array_set (arr, MonoBoolean, i, val);
7805                                 }
7806                                 break;
7807                         case MONO_TYPE_CHAR:
7808                         case MONO_TYPE_U2:
7809                         case MONO_TYPE_I2:
7810                                 for (i = 0; i < alen; i++) {
7811                                         guint16 val = read16 (p);
7812                                         mono_array_set (arr, guint16, i, val);
7813                                         p += 2;
7814                                 }
7815                                 break;
7816                         case MONO_TYPE_R4:
7817                         case MONO_TYPE_U4:
7818                         case MONO_TYPE_I4:
7819                                 for (i = 0; i < alen; i++) {
7820                                         guint32 val = read32 (p);
7821                                         mono_array_set (arr, guint32, i, val);
7822                                         p += 4;
7823                                 }
7824                                 break;
7825                         case MONO_TYPE_R8:
7826                                 for (i = 0; i < alen; i++) {
7827                                         double val;
7828                                         readr8 (p, &val);
7829                                         mono_array_set (arr, double, i, val);
7830                                         p += 8;
7831                                 }
7832                                 break;
7833                         case MONO_TYPE_U8:
7834                         case MONO_TYPE_I8:
7835                                 for (i = 0; i < alen; i++) {
7836                                         guint64 val = read64 (p);
7837                                         mono_array_set (arr, guint64, i, val);
7838                                         p += 8;
7839                                 }
7840                                 break;
7841                         case MONO_TYPE_CLASS:
7842                         case MONO_TYPE_OBJECT:
7843                         case MONO_TYPE_STRING:
7844                                 for (i = 0; i < alen; i++) {
7845                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7846                                         mono_array_setref (arr, i, item);
7847                                 }
7848                                 break;
7849                         default:
7850                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7851                 }
7852                 *end=p;
7853                 return arr;
7854         }
7855         default:
7856                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7857         }
7858         return NULL;
7859 }
7860
7861 static MonoObject*
7862 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7863 {
7864         static MonoClass *klass;
7865         static MonoMethod *ctor;
7866         MonoObject *retval;
7867         void *params [2], *unboxed;
7868
7869         if (!klass)
7870                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7871         if (!ctor)
7872                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7873         
7874         params [0] = mono_type_get_object (mono_domain_get (), t);
7875         params [1] = val;
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 MonoObject*
7884 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7885 {
7886         static MonoClass *klass;
7887         static MonoMethod *ctor;
7888         MonoObject *retval;
7889         void *unboxed, *params [2];
7890
7891         if (!klass)
7892                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7893         if (!ctor)
7894                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7895
7896         params [0] = minfo;
7897         params [1] = typedarg;
7898         retval = mono_object_new (mono_domain_get (), klass);
7899         unboxed = mono_object_unbox (retval);
7900         mono_runtime_invoke (ctor, unboxed, params, NULL);
7901
7902         return retval;
7903 }
7904
7905 static gboolean
7906 type_is_reference (MonoType *type)
7907 {
7908         switch (type->type) {
7909         case MONO_TYPE_BOOLEAN:
7910         case MONO_TYPE_CHAR:
7911         case MONO_TYPE_U:
7912         case MONO_TYPE_I:
7913         case MONO_TYPE_U1:
7914         case MONO_TYPE_I1:
7915         case MONO_TYPE_U2:
7916         case MONO_TYPE_I2:
7917         case MONO_TYPE_U4:
7918         case MONO_TYPE_I4:
7919         case MONO_TYPE_U8:
7920         case MONO_TYPE_I8:
7921         case MONO_TYPE_R8:
7922         case MONO_TYPE_R4:
7923         case MONO_TYPE_VALUETYPE:
7924                 return FALSE;
7925         default:
7926                 return TRUE;
7927         }
7928 }
7929
7930 static void
7931 free_param_data (MonoMethodSignature *sig, void **params) {
7932         int i;
7933         for (i = 0; i < sig->param_count; ++i) {
7934                 if (!type_is_reference (sig->params [i]))
7935                         g_free (params [i]);
7936         }
7937 }
7938
7939 /*
7940  * Find the field index in the metadata FieldDef table.
7941  */
7942 static guint32
7943 find_field_index (MonoClass *klass, MonoClassField *field) {
7944         int i;
7945
7946         for (i = 0; i < klass->field.count; ++i) {
7947                 if (field == &klass->fields [i])
7948                         return klass->field.first + 1 + i;
7949         }
7950         return 0;
7951 }
7952
7953 /*
7954  * Find the property index in the metadata Property table.
7955  */
7956 static guint32
7957 find_property_index (MonoClass *klass, MonoProperty *property) {
7958         int i;
7959
7960         for (i = 0; i < klass->ext->property.count; ++i) {
7961                 if (property == &klass->ext->properties [i])
7962                         return klass->ext->property.first + 1 + i;
7963         }
7964         return 0;
7965 }
7966
7967 /*
7968  * Find the event index in the metadata Event table.
7969  */
7970 static guint32
7971 find_event_index (MonoClass *klass, MonoEvent *event) {
7972         int i;
7973
7974         for (i = 0; i < klass->ext->event.count; ++i) {
7975                 if (event == &klass->ext->events [i])
7976                         return klass->ext->event.first + 1 + i;
7977         }
7978         return 0;
7979 }
7980
7981 static MonoObject*
7982 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7983 {
7984         const char *p = (const char*)data;
7985         const char *named;
7986         guint32 i, j, num_named;
7987         MonoObject *attr;
7988         void *params_buf [32];
7989         void **params;
7990         MonoMethodSignature *sig;
7991
7992         mono_class_init (method->klass);
7993
7994         if (len == 0) {
7995                 attr = mono_object_new (mono_domain_get (), method->klass);
7996                 mono_runtime_invoke (method, attr, NULL, NULL);
7997                 return attr;
7998         }
7999
8000         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8001                 return NULL;
8002
8003         /*g_print ("got attr %s\n", method->klass->name);*/
8004
8005         sig = mono_method_signature (method);
8006         if (sig->param_count < 32)
8007                 params = params_buf;
8008         else
8009                 /* Allocate using GC so it gets GC tracking */
8010                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8011
8012         /* skip prolog */
8013         p += 2;
8014         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8015                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8016         }
8017
8018         named = p;
8019         attr = mono_object_new (mono_domain_get (), method->klass);
8020         mono_runtime_invoke (method, attr, params, NULL);
8021         free_param_data (method->signature, params);
8022         num_named = read16 (named);
8023         named += 2;
8024         for (j = 0; j < num_named; j++) {
8025                 gint name_len;
8026                 char *name, named_type, data_type;
8027                 named_type = *named++;
8028                 data_type = *named++; /* type of data */
8029                 if (data_type == MONO_TYPE_SZARRAY)
8030                         data_type = *named++;
8031                 if (data_type == MONO_TYPE_ENUM) {
8032                         gint type_len;
8033                         char *type_name;
8034                         type_len = mono_metadata_decode_blob_size (named, &named);
8035                         type_name = g_malloc (type_len + 1);
8036                         memcpy (type_name, named, type_len);
8037                         type_name [type_len] = 0;
8038                         named += type_len;
8039                         /* FIXME: lookup the type and check type consistency */
8040                         g_free (type_name);
8041                 }
8042                 name_len = mono_metadata_decode_blob_size (named, &named);
8043                 name = g_malloc (name_len + 1);
8044                 memcpy (name, named, name_len);
8045                 name [name_len] = 0;
8046                 named += name_len;
8047                 if (named_type == 0x53) {
8048                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8049                         void *val = load_cattr_value (image, field->type, named, &named);
8050                         mono_field_set_value (attr, field, val);
8051                         if (!type_is_reference (field->type))
8052                                 g_free (val);
8053                 } else if (named_type == 0x54) {
8054                         MonoProperty *prop;
8055                         void *pparams [1];
8056                         MonoType *prop_type;
8057
8058                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8059                         /* can we have more that 1 arg in a custom attr named property? */
8060                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8061                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8062                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8063                         mono_property_set_value (prop, attr, pparams, NULL);
8064                         if (!type_is_reference (prop_type))
8065                                 g_free (pparams [0]);
8066                 }
8067                 g_free (name);
8068         }
8069
8070         if (params != params_buf)
8071                 mono_gc_free_fixed (params);
8072
8073         return attr;
8074 }
8075         
8076 /*
8077  * mono_reflection_create_custom_attr_data_args:
8078  *
8079  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8080  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8081  * NAMED_ARG_INFO will contain information about the named arguments.
8082  */
8083 void
8084 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)
8085 {
8086         MonoArray *typedargs, *namedargs;
8087         MonoClass *attrklass;
8088         MonoDomain *domain;
8089         const char *p = (const char*)data;
8090         const char *named;
8091         guint32 i, j, num_named;
8092         CattrNamedArg *arginfo = NULL;
8093
8094         mono_class_init (method->klass);
8095
8096         *typed_args = NULL;
8097         *named_args = NULL;
8098         *named_arg_info = NULL;
8099         
8100         domain = mono_domain_get ();
8101
8102         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8103                 return;
8104
8105         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8106         
8107         /* skip prolog */
8108         p += 2;
8109         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8110                 MonoObject *obj;
8111                 void *val;
8112
8113                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8114                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8115                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8116                 mono_array_setref (typedargs, i, obj);
8117
8118                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8119                         g_free (val);
8120         }
8121
8122         named = p;
8123         num_named = read16 (named);
8124         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8125         named += 2;
8126         attrklass = method->klass;
8127
8128         arginfo = g_new0 (CattrNamedArg, num_named);
8129         *named_arg_info = arginfo;
8130
8131         for (j = 0; j < num_named; j++) {
8132                 gint name_len;
8133                 char *name, named_type, data_type;
8134                 named_type = *named++;
8135                 data_type = *named++; /* type of data */
8136                 if (data_type == MONO_TYPE_SZARRAY)
8137                         data_type = *named++;
8138                 if (data_type == MONO_TYPE_ENUM) {
8139                         gint type_len;
8140                         char *type_name;
8141                         type_len = mono_metadata_decode_blob_size (named, &named);
8142                         type_name = g_malloc (type_len + 1);
8143                         memcpy (type_name, named, type_len);
8144                         type_name [type_len] = 0;
8145                         named += type_len;
8146                         /* FIXME: lookup the type and check type consistency */
8147                         g_free (type_name);
8148                 }
8149                 name_len = mono_metadata_decode_blob_size (named, &named);
8150                 name = g_malloc (name_len + 1);
8151                 memcpy (name, named, name_len);
8152                 name [name_len] = 0;
8153                 named += name_len;
8154                 if (named_type == 0x53) {
8155                         MonoObject *obj;
8156                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8157                         void *val;
8158
8159                         arginfo [j].type = field->type;
8160                         arginfo [j].field = field;
8161
8162                         val = load_cattr_value (image, field->type, named, &named);
8163                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8164                         mono_array_setref (namedargs, j, obj);
8165                         if (!type_is_reference (field->type))
8166                                 g_free (val);
8167                 } else if (named_type == 0x54) {
8168                         MonoObject *obj;
8169                         MonoType *prop_type;
8170                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8171                         void *val;
8172
8173                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8174                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8175
8176                         arginfo [j].type = prop_type;
8177                         arginfo [j].prop = prop;
8178
8179                         val = load_cattr_value (image, prop_type, named, &named);
8180                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8181                         mono_array_setref (namedargs, j, obj);
8182                         if (!type_is_reference (prop_type))
8183                                 g_free (val);
8184                 }
8185                 g_free (name);
8186         }
8187
8188         *typed_args = typedargs;
8189         *named_args = namedargs;
8190 }
8191
8192 static MonoObject*
8193 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8194 {
8195         MonoArray *typedargs, *namedargs;
8196         static MonoMethod *ctor;
8197         MonoDomain *domain;
8198         MonoObject *attr;
8199         void *params [3];
8200         CattrNamedArg *arginfo;
8201         int i;
8202
8203         mono_class_init (method->klass);
8204
8205         if (!ctor)
8206                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8207
8208         domain = mono_domain_get ();
8209         if (len == 0) {
8210                 /* This is for Attributes with no parameters */
8211                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8212                 params [0] = mono_method_get_object (domain, method, NULL);
8213                 params [1] = params [2] = NULL;
8214                 mono_runtime_invoke (method, attr, params, NULL);
8215                 return attr;
8216         }
8217
8218         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8219         if (!typedargs || !namedargs)
8220                 return NULL;
8221
8222         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8223                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8224                 MonoObject *typedarg;
8225
8226                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8227                 mono_array_setref (typedargs, i, typedarg);
8228         }
8229
8230         for (i = 0; i < mono_array_length (namedargs); ++i) {
8231                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8232                 MonoObject *typedarg, *namedarg, *minfo;
8233
8234                 if (arginfo [i].prop)
8235                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8236                 else
8237                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8238
8239                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8240                 namedarg = create_cattr_named_arg (minfo, typedarg);
8241
8242                 mono_array_setref (namedargs, i, namedarg);
8243         }
8244
8245         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8246         params [0] = mono_method_get_object (domain, method, NULL);
8247         params [1] = typedargs;
8248         params [2] = namedargs;
8249         mono_runtime_invoke (ctor, attr, params, NULL);
8250         return attr;
8251 }
8252
8253 MonoArray*
8254 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8255 {
8256         MonoArray *result;
8257         MonoObject *attr;
8258         int i;
8259
8260         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8261         for (i = 0; i < cinfo->num_attrs; ++i) {
8262                 if (!cinfo->attrs [i].ctor)
8263                         /* The cattr type is not finished yet */
8264                         /* We should include the type name but cinfo doesn't contain it */
8265                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8266                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8267                 mono_array_setref (result, i, attr);
8268         }
8269         return result;
8270 }
8271
8272 static MonoArray*
8273 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8274 {
8275         MonoArray *result;
8276         MonoObject *attr;
8277         int i, n;
8278
8279         n = 0;
8280         for (i = 0; i < cinfo->num_attrs; ++i) {
8281                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8282                         n ++;
8283         }
8284
8285         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8286         n = 0;
8287         for (i = 0; i < cinfo->num_attrs; ++i) {
8288                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8289                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8290                         mono_array_setref (result, n, attr);
8291                         n ++;
8292                 }
8293         }
8294         return result;
8295 }
8296
8297 static MonoArray*
8298 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8299 {
8300         MonoArray *result;
8301         MonoObject *attr;
8302         int i;
8303         
8304         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8305         for (i = 0; i < cinfo->num_attrs; ++i) {
8306                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8307                 mono_array_setref (result, i, attr);
8308         }
8309         return result;
8310 }
8311
8312 /**
8313  * mono_custom_attrs_from_index:
8314  *
8315  * Returns: NULL if no attributes are found or if a loading error occurs.
8316  */
8317 MonoCustomAttrInfo*
8318 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8319 {
8320         guint32 mtoken, i, len;
8321         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8322         MonoTableInfo *ca;
8323         MonoCustomAttrInfo *ainfo;
8324         GList *tmp, *list = NULL;
8325         const char *data;
8326
8327         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8328
8329         i = mono_metadata_custom_attrs_from_index (image, idx);
8330         if (!i)
8331                 return NULL;
8332         i --;
8333         while (i < ca->rows) {
8334                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8335                         break;
8336                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8337                 ++i;
8338         }
8339         len = g_list_length (list);
8340         if (!len)
8341                 return NULL;
8342         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8343         ainfo->num_attrs = len;
8344         ainfo->image = image;
8345         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8346                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8347                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8348                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8349                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8350                         mtoken |= MONO_TOKEN_METHOD_DEF;
8351                         break;
8352                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8353                         mtoken |= MONO_TOKEN_MEMBER_REF;
8354                         break;
8355                 default:
8356                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8357                         break;
8358                 }
8359                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8360                 if (!ainfo->attrs [i].ctor) {
8361                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8362                         g_list_free (list);
8363                         g_free (ainfo);
8364                         return NULL;
8365                 }
8366                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8367                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8368                 ainfo->attrs [i].data = (guchar*)data;
8369         }
8370         g_list_free (list);
8371
8372         return ainfo;
8373 }
8374
8375 MonoCustomAttrInfo*
8376 mono_custom_attrs_from_method (MonoMethod *method)
8377 {
8378         guint32 idx;
8379
8380         /*
8381          * An instantiated method has the same cattrs as the generic method definition.
8382          *
8383          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8384          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8385          */
8386         if (method->is_inflated)
8387                 method = ((MonoMethodInflated *) method)->declaring;
8388         
8389         if (method->dynamic || method->klass->image->dynamic)
8390                 return lookup_custom_attr (method->klass->image, method);
8391
8392         if (!method->token)
8393                 /* Synthetic methods */
8394                 return NULL;
8395
8396         idx = mono_method_get_index (method);
8397         idx <<= MONO_CUSTOM_ATTR_BITS;
8398         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8399         return mono_custom_attrs_from_index (method->klass->image, idx);
8400 }
8401
8402 MonoCustomAttrInfo*
8403 mono_custom_attrs_from_class (MonoClass *klass)
8404 {
8405         guint32 idx;
8406
8407         if (klass->generic_class)
8408                 klass = klass->generic_class->container_class;
8409
8410         if (klass->image->dynamic)
8411                 return lookup_custom_attr (klass->image, klass);
8412
8413         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8414                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8415                 idx <<= MONO_CUSTOM_ATTR_BITS;
8416                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8417         } else {
8418                 idx = mono_metadata_token_index (klass->type_token);
8419                 idx <<= MONO_CUSTOM_ATTR_BITS;
8420                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8421         }
8422         return mono_custom_attrs_from_index (klass->image, idx);
8423 }
8424
8425 MonoCustomAttrInfo*
8426 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8427 {
8428         guint32 idx;
8429         
8430         if (assembly->image->dynamic)
8431                 return lookup_custom_attr (assembly->image, assembly);
8432         idx = 1; /* there is only one assembly */
8433         idx <<= MONO_CUSTOM_ATTR_BITS;
8434         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8435         return mono_custom_attrs_from_index (assembly->image, idx);
8436 }
8437
8438 static MonoCustomAttrInfo*
8439 mono_custom_attrs_from_module (MonoImage *image)
8440 {
8441         guint32 idx;
8442         
8443         if (image->dynamic)
8444                 return lookup_custom_attr (image, image);
8445         idx = 1; /* there is only one module */
8446         idx <<= MONO_CUSTOM_ATTR_BITS;
8447         idx |= MONO_CUSTOM_ATTR_MODULE;
8448         return mono_custom_attrs_from_index (image, idx);
8449 }
8450
8451 MonoCustomAttrInfo*
8452 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8453 {
8454         guint32 idx;
8455         
8456         if (klass->image->dynamic) {
8457                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8458                 return lookup_custom_attr (klass->image, property);
8459         }
8460         idx = find_property_index (klass, property);
8461         idx <<= MONO_CUSTOM_ATTR_BITS;
8462         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8463         return mono_custom_attrs_from_index (klass->image, idx);
8464 }
8465
8466 MonoCustomAttrInfo*
8467 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8468 {
8469         guint32 idx;
8470         
8471         if (klass->image->dynamic) {
8472                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8473                 return lookup_custom_attr (klass->image, event);
8474         }
8475         idx = find_event_index (klass, event);
8476         idx <<= MONO_CUSTOM_ATTR_BITS;
8477         idx |= MONO_CUSTOM_ATTR_EVENT;
8478         return mono_custom_attrs_from_index (klass->image, idx);
8479 }
8480
8481 MonoCustomAttrInfo*
8482 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8483 {
8484         guint32 idx;
8485         if (klass->image->dynamic) {
8486                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8487                 return lookup_custom_attr (klass->image, field);
8488         }
8489         idx = find_field_index (klass, field);
8490         idx <<= MONO_CUSTOM_ATTR_BITS;
8491         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8492         return mono_custom_attrs_from_index (klass->image, idx);
8493 }
8494
8495 MonoCustomAttrInfo*
8496 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8497 {
8498         MonoTableInfo *ca;
8499         guint32 i, idx, method_index;
8500         guint32 param_list, param_last, param_pos, found;
8501         MonoImage *image;
8502         MonoReflectionMethodAux *aux;
8503
8504         /*
8505          * An instantiated method has the same cattrs as the generic method definition.
8506          *
8507          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8508          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8509          */
8510         if (method->is_inflated)
8511                 method = ((MonoMethodInflated *) method)->declaring;
8512
8513         if (method->klass->image->dynamic) {
8514                 MonoCustomAttrInfo *res, *ainfo;
8515                 int size;
8516
8517                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8518                 if (!aux || !aux->param_cattr)
8519                         return NULL;
8520
8521                 /* Need to copy since it will be freed later */
8522                 ainfo = aux->param_cattr [param];
8523                 if (!ainfo)
8524                         return NULL;
8525                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8526                 res = g_malloc0 (size);
8527                 memcpy (res, ainfo, size);
8528                 return res;
8529         }
8530
8531         image = method->klass->image;
8532         method_index = mono_method_get_index (method);
8533         ca = &image->tables [MONO_TABLE_METHOD];
8534
8535         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8536         if (method_index == ca->rows) {
8537                 ca = &image->tables [MONO_TABLE_PARAM];
8538                 param_last = ca->rows + 1;
8539         } else {
8540                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8541                 ca = &image->tables [MONO_TABLE_PARAM];
8542         }
8543         found = FALSE;
8544         for (i = param_list; i < param_last; ++i) {
8545                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8546                 if (param_pos == param) {
8547                         found = TRUE;
8548                         break;
8549                 }
8550         }
8551         if (!found)
8552                 return NULL;
8553         idx = i;
8554         idx <<= MONO_CUSTOM_ATTR_BITS;
8555         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8556         return mono_custom_attrs_from_index (image, idx);
8557 }
8558
8559 gboolean
8560 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8561 {
8562         int i;
8563         MonoClass *klass;
8564         for (i = 0; i < ainfo->num_attrs; ++i) {
8565                 klass = ainfo->attrs [i].ctor->klass;
8566                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8567                         return TRUE;
8568         }
8569         return FALSE;
8570 }
8571
8572 MonoObject*
8573 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8574 {
8575         int i, attr_index;
8576         MonoClass *klass;
8577         MonoArray *attrs;
8578
8579         attr_index = -1;
8580         for (i = 0; i < ainfo->num_attrs; ++i) {
8581                 klass = ainfo->attrs [i].ctor->klass;
8582                 if (mono_class_has_parent (klass, attr_klass)) {
8583                         attr_index = i;
8584                         break;
8585                 }
8586         }
8587         if (attr_index == -1)
8588                 return NULL;
8589
8590         attrs = mono_custom_attrs_construct (ainfo);
8591         if (attrs)
8592                 return mono_array_get (attrs, MonoObject*, attr_index);
8593         else
8594                 return NULL;
8595 }
8596
8597 /*
8598  * mono_reflection_get_custom_attrs_info:
8599  * @obj: a reflection object handle
8600  *
8601  * Return the custom attribute info for attributes defined for the
8602  * reflection handle @obj. The objects.
8603  *
8604  * FIXME this function leaks like a sieve for SRE objects.
8605  */
8606 MonoCustomAttrInfo*
8607 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8608 {
8609         MonoClass *klass;
8610         MonoCustomAttrInfo *cinfo = NULL;
8611         
8612         klass = obj->vtable->klass;
8613         if (klass == mono_defaults.monotype_class) {
8614                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8615                 klass = mono_class_from_mono_type (type);
8616                 cinfo = mono_custom_attrs_from_class (klass);
8617         } else if (strcmp ("Assembly", klass->name) == 0) {
8618                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8619                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8620         } else if (strcmp ("Module", klass->name) == 0) {
8621                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8622                 cinfo = mono_custom_attrs_from_module (module->image);
8623         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8624                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8625                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8626         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8627                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8628                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8629         } else if (strcmp ("MonoField", klass->name) == 0) {
8630                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8631                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8632         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8633                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8634                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8635         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8636                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8637                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8638         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8639                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8640                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8641                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8642         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8643                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8644                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8645         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8646                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8647                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8648         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8649                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8650                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8651         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8652                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8653                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8654         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8655                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8656                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8657         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8658                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8659                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8660         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8661                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8662                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8663         } else { /* handle other types here... */
8664                 g_error ("get custom attrs not yet supported for %s", klass->name);
8665         }
8666
8667         return cinfo;
8668 }
8669
8670 /*
8671  * mono_reflection_get_custom_attrs_by_type:
8672  * @obj: a reflection object handle
8673  *
8674  * Return an array with all the custom attributes defined of the
8675  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8676  * of that type are returned. The objects are fully build. Return NULL if a loading error
8677  * occurs.
8678  */
8679 MonoArray*
8680 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8681 {
8682         MonoArray *result;
8683         MonoCustomAttrInfo *cinfo;
8684
8685         cinfo = mono_reflection_get_custom_attrs_info (obj);
8686         if (cinfo) {
8687                 if (attr_klass)
8688                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8689                 else
8690                         result = mono_custom_attrs_construct (cinfo);
8691                 if (!cinfo->cached)
8692                         mono_custom_attrs_free (cinfo);
8693         } else {
8694                 if (mono_loader_get_last_error ())
8695                         return NULL;
8696                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8697         }
8698
8699         return result;
8700 }
8701
8702 /*
8703  * mono_reflection_get_custom_attrs:
8704  * @obj: a reflection object handle
8705  *
8706  * Return an array with all the custom attributes defined of the
8707  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8708  * occurs.
8709  */
8710 MonoArray*
8711 mono_reflection_get_custom_attrs (MonoObject *obj)
8712 {
8713         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8714 }
8715
8716 /*
8717  * mono_reflection_get_custom_attrs_data:
8718  * @obj: a reflection obj handle
8719  *
8720  * Returns an array of System.Reflection.CustomAttributeData,
8721  * which include information about attributes reflected on
8722  * types loaded using the Reflection Only methods
8723  */
8724 MonoArray*
8725 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8726 {
8727         MonoArray *result;
8728         MonoCustomAttrInfo *cinfo;
8729
8730         cinfo = mono_reflection_get_custom_attrs_info (obj);
8731         if (cinfo) {
8732                 result = mono_custom_attrs_data_construct (cinfo);
8733                 if (!cinfo->cached)
8734                         mono_custom_attrs_free (cinfo);
8735         } else
8736                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8737
8738         return result;
8739 }
8740
8741 static MonoReflectionType*
8742 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8743 {
8744         static MonoMethod *method_get_underlying_system_type = NULL;
8745         MonoMethod *usertype_method;
8746
8747         if (!method_get_underlying_system_type)
8748                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8749         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8750         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8751 }
8752
8753 #ifndef DISABLE_REFLECTION_EMIT
8754
8755 static gboolean
8756 is_corlib_type (MonoClass *class)
8757 {
8758         return class->image == mono_defaults.corlib;
8759 }
8760
8761 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8762         static MonoClass *cached_class; \
8763         if (cached_class) \
8764                 return cached_class == _class; \
8765         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8766                 cached_class = _class; \
8767                 return TRUE; \
8768         } \
8769         return FALSE; \
8770 } while (0) \
8771
8772 static gboolean
8773 is_sre_array (MonoClass *class)
8774 {
8775         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8776 }
8777
8778 static gboolean
8779 is_sre_byref (MonoClass *class)
8780 {
8781         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8782 }
8783
8784 static gboolean
8785 is_sre_pointer (MonoClass *class)
8786 {
8787         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8788 }
8789
8790 static gboolean
8791 is_sre_generic_instance (MonoClass *class)
8792 {
8793         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8794 }
8795
8796 static gboolean
8797 is_sre_type_builder (MonoClass *class)
8798 {
8799         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8800 }
8801
8802 static gboolean
8803 is_sre_method_builder (MonoClass *class)
8804 {
8805         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8806 }
8807
8808 static gboolean
8809 is_sre_ctor_builder (MonoClass *class)
8810 {
8811         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8812 }
8813
8814 static gboolean
8815 is_sre_field_builder (MonoClass *class)
8816 {
8817         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8818 }
8819
8820 static gboolean
8821 is_sr_mono_method (MonoClass *class)
8822 {
8823         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
8824 }
8825
8826 static gboolean
8827 is_sr_mono_cmethod (MonoClass *class)
8828 {
8829         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
8830 }
8831
8832 static gboolean
8833 is_sr_mono_field (MonoClass *class)
8834 {
8835         check_corlib_type_cached (class, "System.Reflection", "MonoField");
8836 }
8837
8838
8839 MonoType*
8840 mono_reflection_type_get_handle (MonoReflectionType* ref)
8841 {
8842         MonoClass *class;
8843         if (!ref)
8844                 return NULL;
8845         if (ref->type)
8846                 return ref->type;
8847
8848         if (is_usertype (ref)) {
8849                 ref = mono_reflection_type_get_underlying_system_type (ref);
8850                 if (ref == NULL || is_usertype (ref))
8851                         return NULL;
8852                 if (ref->type)
8853                         return ref->type;
8854         }
8855
8856         class = mono_object_class (ref);
8857
8858         if (is_sre_array (class)) {
8859                 MonoType *res;
8860                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
8861                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
8862                 g_assert (base);
8863                 if (sre_array->rank == 0) //single dimentional array
8864                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
8865                 else
8866                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
8867                 sre_array->type.type = res;
8868                 return res;
8869         } else if (is_sre_byref (class)) {
8870                 MonoType *res;
8871                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
8872                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
8873                 g_assert (base);
8874                 res = &mono_class_from_mono_type (base)->this_arg;
8875                 sre_byref->type.type = res;
8876                 return res;
8877         } else if (is_sre_pointer (class)) {
8878                 MonoType *res;
8879                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
8880                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
8881                 g_assert (base);
8882                 res = &mono_ptr_class_get (base)->byval_arg;
8883                 sre_pointer->type.type = res;
8884                 return res;
8885         } else if (is_sre_generic_instance (class)) {
8886                 MonoType *res, **types;
8887                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
8888                 int i, count;
8889
8890                 count = mono_array_length (gclass->type_arguments);
8891                 types = g_new0 (MonoType*, count);
8892                 for (i = 0; i < count; ++i) {
8893                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
8894                         types [i] = mono_reflection_type_get_handle (t);
8895                         if (!types[i]) {
8896                                 g_free (types);
8897                                 return NULL;
8898                         }
8899                 }
8900
8901                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
8902                 g_free (types);
8903                 g_assert (res);
8904                 gclass->type.type = res;
8905                 return res;
8906         }
8907
8908         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
8909         return NULL;
8910 }
8911
8912
8913
8914 void
8915 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
8916 {
8917         mono_reflection_type_get_handle (type);
8918 }
8919
8920 void
8921 mono_reflection_register_with_runtime (MonoReflectionType *type)
8922 {
8923         MonoType *res = mono_reflection_type_get_handle (type);
8924         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
8925         MonoClass *class;
8926
8927         if (!res)
8928                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
8929
8930         class = mono_class_from_mono_type (res);
8931
8932         mono_loader_lock (); /*same locking as mono_type_get_object*/
8933         mono_domain_lock (domain);
8934
8935         if (!class->image->dynamic) {
8936                 mono_class_setup_supertypes (class);
8937         } else {
8938                 if (!domain->type_hash)
8939                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
8940                                         (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
8941                 mono_g_hash_table_insert (domain->type_hash, res, type);
8942         }
8943         mono_domain_unlock (domain);
8944         mono_loader_unlock ();
8945 }
8946
8947 /**
8948  * LOCKING: Assumes the loader lock is held.
8949  */
8950 static MonoMethodSignature*
8951 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8952         MonoMethodSignature *sig;
8953         int count, i;
8954
8955         count = parameters? mono_array_length (parameters): 0;
8956
8957         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
8958         sig->param_count = count;
8959         sig->sentinelpos = -1; /* FIXME */
8960         for (i = 0; i < count; ++i)
8961                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
8962         return sig;
8963 }
8964
8965 /**
8966  * LOCKING: Assumes the loader lock is held.
8967  */
8968 static MonoMethodSignature*
8969 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8970         MonoMethodSignature *sig;
8971
8972         sig = parameters_to_signature (image, ctor->parameters);
8973         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8974         sig->ret = &mono_defaults.void_class->byval_arg;
8975         return sig;
8976 }
8977
8978 /**
8979  * LOCKING: Assumes the loader lock is held.
8980  */
8981 static MonoMethodSignature*
8982 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8983         MonoMethodSignature *sig;
8984
8985         sig = parameters_to_signature (image, method->parameters);
8986         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8987         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
8988         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8989         return sig;
8990 }
8991
8992 static MonoMethodSignature*
8993 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8994         MonoMethodSignature *sig;
8995
8996         sig = parameters_to_signature (NULL, method->parameters);
8997         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8998         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
8999         sig->generic_param_count = 0;
9000         return sig;
9001 }
9002
9003 static void
9004 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9005 {
9006         MonoClass *klass = mono_object_class (prop);
9007         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9008                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9009                 *name = mono_string_to_utf8 (pb->name);
9010                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9011         } else {
9012                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9013                 *name = g_strdup (p->property->name);
9014                 if (p->property->get)
9015                         *type = mono_method_signature (p->property->get)->ret;
9016                 else
9017                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9018         }
9019 }
9020
9021 static void
9022 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9023 {
9024         MonoClass *klass = mono_object_class (field);
9025         if (strcmp (klass->name, "FieldBuilder") == 0) {
9026                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9027                 *name = mono_string_to_utf8 (fb->name);
9028                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9029         } else {
9030                 MonoReflectionField *f = (MonoReflectionField *)field;
9031                 *name = g_strdup (mono_field_get_name (f->field));
9032                 *type = f->field->type;
9033         }
9034 }
9035
9036 #else /* DISABLE_REFLECTION_EMIT */
9037
9038 void
9039 mono_reflection_register_with_runtime (MonoReflectionType *type)
9040 {
9041         /* This is empty */
9042 }
9043
9044 static gboolean
9045 is_sre_type_builder (MonoClass *class)
9046 {
9047         return FALSE;
9048 }
9049
9050 static gboolean
9051 is_sre_generic_instance (MonoClass *class)
9052 {
9053         return FALSE;
9054 }
9055
9056 #endif /* !DISABLE_REFLECTION_EMIT */
9057
9058 static gboolean
9059 is_usertype (MonoReflectionType *ref)
9060 {
9061         MonoClass *class = mono_object_class (ref);
9062         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9063 }
9064
9065 static MonoReflectionType*
9066 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9067 {
9068         if (!type || type->type)
9069                 return type;
9070
9071         if (is_usertype (type)) {
9072                 type = mono_reflection_type_get_underlying_system_type (type);
9073                 if (is_usertype (type))
9074                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9075         }
9076
9077         return type;
9078 }
9079 /*
9080  * Encode a value in a custom attribute stream of bytes.
9081  * The value to encode is either supplied as an object in argument val
9082  * (valuetypes are boxed), or as a pointer to the data in the
9083  * argument argval.
9084  * @type represents the type of the value
9085  * @buffer is the start of the buffer
9086  * @p the current position in the buffer
9087  * @buflen contains the size of the buffer and is used to return the new buffer size
9088  * if this needs to be realloced.
9089  * @retbuffer and @retp return the start and the position of the buffer
9090  */
9091 static void
9092 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9093 {
9094         MonoTypeEnum simple_type;
9095         
9096         if ((p-buffer) + 10 >= *buflen) {
9097                 char *newbuf;
9098                 *buflen *= 2;
9099                 newbuf = g_realloc (buffer, *buflen);
9100                 p = newbuf + (p-buffer);
9101                 buffer = newbuf;
9102         }
9103         if (!argval)
9104                 argval = ((char*)arg + sizeof (MonoObject));
9105         simple_type = type->type;
9106 handle_enum:
9107         switch (simple_type) {
9108         case MONO_TYPE_BOOLEAN:
9109         case MONO_TYPE_U1:
9110         case MONO_TYPE_I1:
9111                 *p++ = *argval;
9112                 break;
9113         case MONO_TYPE_CHAR:
9114         case MONO_TYPE_U2:
9115         case MONO_TYPE_I2:
9116                 swap_with_size (p, argval, 2, 1);
9117                 p += 2;
9118                 break;
9119         case MONO_TYPE_U4:
9120         case MONO_TYPE_I4:
9121         case MONO_TYPE_R4:
9122                 swap_with_size (p, argval, 4, 1);
9123                 p += 4;
9124                 break;
9125         case MONO_TYPE_R8:
9126 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9127                 p [0] = argval [4];
9128                 p [1] = argval [5];
9129                 p [2] = argval [6];
9130                 p [3] = argval [7];
9131                 p [4] = argval [0];
9132                 p [5] = argval [1];
9133                 p [6] = argval [2];
9134                 p [7] = argval [3];
9135 #else
9136                 swap_with_size (p, argval, 8, 1);
9137 #endif
9138                 p += 8;
9139                 break;
9140         case MONO_TYPE_U8:
9141         case MONO_TYPE_I8:
9142                 swap_with_size (p, argval, 8, 1);
9143                 p += 8;
9144                 break;
9145         case MONO_TYPE_VALUETYPE:
9146                 if (type->data.klass->enumtype) {
9147                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9148                         goto handle_enum;
9149                 } else {
9150                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9151                 }
9152                 break;
9153         case MONO_TYPE_STRING: {
9154                 char *str;
9155                 guint32 slen;
9156                 if (!arg) {
9157                         *p++ = 0xFF;
9158                         break;
9159                 }
9160                 str = mono_string_to_utf8 ((MonoString*)arg);
9161                 slen = strlen (str);
9162                 if ((p-buffer) + 10 + slen >= *buflen) {
9163                         char *newbuf;
9164                         *buflen *= 2;
9165                         *buflen += slen;
9166                         newbuf = g_realloc (buffer, *buflen);
9167                         p = newbuf + (p-buffer);
9168                         buffer = newbuf;
9169                 }
9170                 mono_metadata_encode_value (slen, p, &p);
9171                 memcpy (p, str, slen);
9172                 p += slen;
9173                 g_free (str);
9174                 break;
9175         }
9176         case MONO_TYPE_CLASS: {
9177                 char *str;
9178                 guint32 slen;
9179                 if (!arg) {
9180                         *p++ = 0xFF;
9181                         break;
9182                 }
9183 handle_type:
9184                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9185                 slen = strlen (str);
9186                 if ((p-buffer) + 10 + slen >= *buflen) {
9187                         char *newbuf;
9188                         *buflen *= 2;
9189                         *buflen += slen;
9190                         newbuf = g_realloc (buffer, *buflen);
9191                         p = newbuf + (p-buffer);
9192                         buffer = newbuf;
9193                 }
9194                 mono_metadata_encode_value (slen, p, &p);
9195                 memcpy (p, str, slen);
9196                 p += slen;
9197                 g_free (str);
9198                 break;
9199         }
9200         case MONO_TYPE_SZARRAY: {
9201                 int len, i;
9202                 MonoClass *eclass, *arg_eclass;
9203
9204                 if (!arg) {
9205                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9206                         break;
9207                 }
9208                 len = mono_array_length ((MonoArray*)arg);
9209                 *p++ = len & 0xff;
9210                 *p++ = (len >> 8) & 0xff;
9211                 *p++ = (len >> 16) & 0xff;
9212                 *p++ = (len >> 24) & 0xff;
9213                 *retp = p;
9214                 *retbuffer = buffer;
9215                 eclass = type->data.klass;
9216                 arg_eclass = mono_object_class (arg)->element_class;
9217
9218                 if (!eclass) {
9219                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9220                         eclass = mono_defaults.object_class;
9221                 }
9222                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9223                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9224                         int elsize = mono_class_array_element_size (arg_eclass);
9225                         for (i = 0; i < len; ++i) {
9226                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9227                                 elptr += elsize;
9228                         }
9229                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9230                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9231                         int elsize = mono_class_array_element_size (eclass);
9232                         for (i = 0; i < len; ++i) {
9233                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9234                                 elptr += elsize;
9235                         }
9236                 } else {
9237                         for (i = 0; i < len; ++i) {
9238                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9239                         }
9240                 }
9241                 break;
9242         }
9243         case MONO_TYPE_OBJECT: {
9244                 MonoClass *klass;
9245                 char *str;
9246                 guint32 slen;
9247
9248                 /*
9249                  * The parameter type is 'object' but the type of the actual
9250                  * argument is not. So we have to add type information to the blob
9251                  * too. This is completely undocumented in the spec.
9252                  */
9253
9254                 if (arg == NULL) {
9255                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9256                         *p++ = 0xFF;
9257                         break;
9258                 }
9259                 
9260                 klass = mono_object_class (arg);
9261
9262                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9263                         *p++ = 0x50;
9264                         goto handle_type;
9265                 } else if (klass->enumtype) {
9266                         *p++ = 0x55;
9267                 } else if (klass == mono_defaults.string_class) {
9268                         simple_type = MONO_TYPE_STRING;
9269                         *p++ = 0x0E;
9270                         goto handle_enum;
9271                 } else if (klass->rank == 1) {
9272                         *p++ = 0x1D;
9273                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9274                                 /* See Partition II, Appendix B3 */
9275                                 *p++ = 0x51;
9276                         else
9277                                 *p++ = klass->element_class->byval_arg.type;
9278                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9279                         break;
9280                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9281                         *p++ = simple_type = klass->byval_arg.type;
9282                         goto handle_enum;
9283                 } else {
9284                         g_error ("unhandled type in custom attr");
9285                 }
9286                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9287                 slen = strlen (str);
9288                 if ((p-buffer) + 10 + slen >= *buflen) {
9289                         char *newbuf;
9290                         *buflen *= 2;
9291                         *buflen += slen;
9292                         newbuf = g_realloc (buffer, *buflen);
9293                         p = newbuf + (p-buffer);
9294                         buffer = newbuf;
9295                 }
9296                 mono_metadata_encode_value (slen, p, &p);
9297                 memcpy (p, str, slen);
9298                 p += slen;
9299                 g_free (str);
9300                 simple_type = mono_class_enum_basetype (klass)->type;
9301                 goto handle_enum;
9302         }
9303         default:
9304                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9305         }
9306         *retp = p;
9307         *retbuffer = buffer;
9308 }
9309
9310 static void
9311 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9312 {
9313         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9314                 char *str = type_get_qualified_name (type, NULL);
9315                 int slen = strlen (str);
9316
9317                 *p++ = 0x55;
9318                 /*
9319                  * This seems to be optional...
9320                  * *p++ = 0x80;
9321                  */
9322                 mono_metadata_encode_value (slen, p, &p);
9323                 memcpy (p, str, slen);
9324                 p += slen;
9325                 g_free (str);
9326         } else if (type->type == MONO_TYPE_OBJECT) {
9327                 *p++ = 0x51;
9328         } else if (type->type == MONO_TYPE_CLASS) {
9329                 /* it should be a type: encode_cattr_value () has the check */
9330                 *p++ = 0x50;
9331         } else {
9332                 mono_metadata_encode_value (type->type, p, &p);
9333                 if (type->type == MONO_TYPE_SZARRAY)
9334                         /* See the examples in Partition VI, Annex B */
9335                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9336         }
9337
9338         *retp = p;
9339 }
9340
9341 #ifndef DISABLE_REFLECTION_EMIT
9342 static void
9343 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9344 {
9345         int len;
9346         /* Preallocate a large enough buffer */
9347         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9348                 char *str = type_get_qualified_name (type, NULL);
9349                 len = strlen (str);
9350                 g_free (str);
9351         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9352                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9353                 len = strlen (str);
9354                 g_free (str);
9355         } else {
9356                 len = 0;
9357         }
9358         len += strlen (name);
9359
9360         if ((p-buffer) + 20 + len >= *buflen) {
9361                 char *newbuf;
9362                 *buflen *= 2;
9363                 *buflen += len;
9364                 newbuf = g_realloc (buffer, *buflen);
9365                 p = newbuf + (p-buffer);
9366                 buffer = newbuf;
9367         }
9368
9369         encode_field_or_prop_type (type, p, &p);
9370
9371         len = strlen (name);
9372         mono_metadata_encode_value (len, p, &p);
9373         memcpy (p, name, len);
9374         p += len;
9375         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9376         *retp = p;
9377         *retbuffer = buffer;
9378 }
9379
9380 /*
9381  * mono_reflection_get_custom_attrs_blob:
9382  * @ctor: custom attribute constructor
9383  * @ctorArgs: arguments o the constructor
9384  * @properties:
9385  * @propValues:
9386  * @fields:
9387  * @fieldValues:
9388  * 
9389  * Creates the blob of data that needs to be saved in the metadata and that represents
9390  * the custom attributed described by @ctor, @ctorArgs etc.
9391  * Returns: a Byte array representing the blob of data.
9392  */
9393 MonoArray*
9394 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9395 {
9396         MonoArray *result;
9397         MonoMethodSignature *sig;
9398         MonoObject *arg;
9399         char *buffer, *p;
9400         guint32 buflen, i;
9401
9402         MONO_ARCH_SAVE_REGS;
9403
9404         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9405                 /* sig is freed later so allocate it in the heap */
9406                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9407         } else {
9408                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9409         }
9410
9411         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9412         buflen = 256;
9413         p = buffer = g_malloc (buflen);
9414         /* write the prolog */
9415         *p++ = 1;
9416         *p++ = 0;
9417         for (i = 0; i < sig->param_count; ++i) {
9418                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9419                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9420         }
9421         i = 0;
9422         if (properties)
9423                 i += mono_array_length (properties);
9424         if (fields)
9425                 i += mono_array_length (fields);
9426         *p++ = i & 0xff;
9427         *p++ = (i >> 8) & 0xff;
9428         if (properties) {
9429                 MonoObject *prop;
9430                 for (i = 0; i < mono_array_length (properties); ++i) {
9431                         MonoType *ptype;
9432                         char *pname;
9433
9434                         prop = mono_array_get (properties, gpointer, i);
9435                         get_prop_name_and_type (prop, &pname, &ptype);
9436                         *p++ = 0x54; /* PROPERTY signature */
9437                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9438                         g_free (pname);
9439                 }
9440         }
9441
9442         if (fields) {
9443                 MonoObject *field;
9444                 for (i = 0; i < mono_array_length (fields); ++i) {
9445                         MonoType *ftype;
9446                         char *fname;
9447
9448                         field = mono_array_get (fields, gpointer, i);
9449                         get_field_name_and_type (field, &fname, &ftype);
9450                         *p++ = 0x53; /* FIELD signature */
9451                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9452                         g_free (fname);
9453                 }
9454         }
9455
9456         g_assert (p - buffer <= buflen);
9457         buflen = p - buffer;
9458         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9459         p = mono_array_addr (result, char, 0);
9460         memcpy (p, buffer, buflen);
9461         g_free (buffer);
9462         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9463                 g_free (sig);
9464         return result;
9465 }
9466
9467 /*
9468  * mono_reflection_setup_internal_class:
9469  * @tb: a TypeBuilder object
9470  *
9471  * Creates a MonoClass that represents the TypeBuilder.
9472  * This is a trick that lets us simplify a lot of reflection code
9473  * (and will allow us to support Build and Run assemblies easier).
9474  */
9475 void
9476 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9477 {
9478         MonoError error;
9479         MonoClass *klass, *parent;
9480
9481         MONO_ARCH_SAVE_REGS;
9482
9483         RESOLVE_TYPE (tb->parent);
9484
9485         mono_loader_lock ();
9486
9487         if (tb->parent) {
9488                 /* check so we can compile corlib correctly */
9489                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9490                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9491                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9492                 } else {
9493                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9494                 }
9495         } else {
9496                 parent = NULL;
9497         }
9498         
9499         /* the type has already being created: it means we just have to change the parent */
9500         if (tb->type.type) {
9501                 klass = mono_class_from_mono_type (tb->type.type);
9502                 klass->parent = NULL;
9503                 /* fool mono_class_setup_parent */
9504                 klass->supertypes = NULL;
9505                 mono_class_setup_parent (klass, parent);
9506                 mono_class_setup_mono_type (klass);
9507                 mono_loader_unlock ();
9508                 return;
9509         }
9510
9511         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9512
9513         klass->image = &tb->module->dynamic_image->image;
9514
9515         klass->inited = 1; /* we lie to the runtime */
9516         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9517         if (!mono_error_ok (&error))
9518                 goto failure;
9519         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9520         if (!mono_error_ok (&error))
9521                 goto failure;
9522         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9523         klass->flags = tb->attrs;
9524         
9525         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9526
9527         klass->element_class = klass;
9528
9529         if (klass->reflection_info == NULL) {
9530
9531                 MOVING_GC_REGISTER (&klass->reflection_info);
9532                 klass->reflection_info = tb;
9533
9534                 /* Put into cache so mono_class_get () will find it.
9535                 Skip nested types as those should not be available on the global scope. */
9536                 if (!tb->nesting_type) {
9537                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9538                 } else {
9539                         klass->image->reflection_info_unregister_classes =
9540                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9541                 }
9542         } else {
9543                 g_assert (klass->reflection_info == tb);
9544         }
9545
9546         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9547                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9548
9549         if (parent != NULL) {
9550                 mono_class_setup_parent (klass, parent);
9551         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9552                 const char *old_n = klass->name;
9553                 /* trick to get relative numbering right when compiling corlib */
9554                 klass->name = "BuildingObject";
9555                 mono_class_setup_parent (klass, mono_defaults.object_class);
9556                 klass->name = old_n;
9557         }
9558
9559         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9560                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9561                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9562                 klass->instance_size = sizeof (MonoObject);
9563                 klass->size_inited = 1;
9564                 mono_class_setup_vtable_general (klass, NULL, 0);
9565         }
9566
9567         mono_class_setup_mono_type (klass);
9568
9569         mono_class_setup_supertypes (klass);
9570
9571         /*
9572          * FIXME: handle interfaces.
9573          */
9574
9575         tb->type.type = &klass->byval_arg;
9576
9577         if (tb->nesting_type) {
9578                 g_assert (tb->nesting_type->type);
9579                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9580         }
9581
9582         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9583
9584         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9585         
9586         mono_loader_unlock ();
9587         return;
9588
9589 failure:
9590         mono_loader_unlock ();
9591         mono_error_raise_exception (&error);
9592 }
9593
9594 /*
9595  * mono_reflection_setup_generic_class:
9596  * @tb: a TypeBuilder object
9597  *
9598  * Setup the generic class before adding the first generic parameter.
9599  */
9600 void
9601 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9602 {
9603 }
9604
9605 /*
9606  * mono_reflection_create_generic_class:
9607  * @tb: a TypeBuilder object
9608  *
9609  * Creates the generic class after all generic parameters have been added.
9610  */
9611 void
9612 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9613 {
9614         MonoClass *klass;
9615         int count, i;
9616
9617         MONO_ARCH_SAVE_REGS;
9618
9619         klass = mono_class_from_mono_type (tb->type.type);
9620
9621         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9622
9623         if (klass->generic_container || (count == 0))
9624                 return;
9625
9626         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9627
9628         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9629
9630         klass->generic_container->owner.klass = klass;
9631         klass->generic_container->type_argc = count;
9632         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9633
9634         klass->is_generic = 1;
9635
9636         for (i = 0; i < count; i++) {
9637                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9638                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9639                 klass->generic_container->type_params [i] = *param;
9640                 /*Make sure we are a diferent type instance */
9641                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9642                 klass->generic_container->type_params [i].info.pklass = NULL;
9643
9644                 g_assert (klass->generic_container->type_params [i].param.owner);
9645         }
9646
9647         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9648 }
9649
9650 /*
9651  * mono_reflection_create_internal_class:
9652  * @tb: a TypeBuilder object
9653  *
9654  * Actually create the MonoClass that is associated with the TypeBuilder.
9655  */
9656 void
9657 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9658 {
9659         MonoClass *klass;
9660
9661         MONO_ARCH_SAVE_REGS;
9662
9663         klass = mono_class_from_mono_type (tb->type.type);
9664
9665         mono_loader_lock ();
9666         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9667                 MonoReflectionFieldBuilder *fb;
9668                 MonoClass *ec;
9669                 MonoType *enum_basetype;
9670
9671                 g_assert (tb->fields != NULL);
9672                 g_assert (mono_array_length (tb->fields) >= 1);
9673
9674                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9675
9676                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9677                         mono_loader_unlock ();
9678                         return;
9679                 }
9680
9681                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9682                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9683                 if (!klass->element_class)
9684                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9685
9686                 /*
9687                  * get the element_class from the current corlib.
9688                  */
9689                 ec = default_class_from_mono_type (enum_basetype);
9690                 klass->instance_size = ec->instance_size;
9691                 klass->size_inited = 1;
9692                 /* 
9693                  * this is almost safe to do with enums and it's needed to be able
9694                  * to create objects of the enum type (for use in SetConstant).
9695                  */
9696                 /* FIXME: Does this mean enums can't have method overrides ? */
9697                 mono_class_setup_vtable_general (klass, NULL, 0);
9698         }
9699         mono_loader_unlock ();
9700 }
9701
9702 static MonoMarshalSpec*
9703 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9704                                                                 MonoReflectionMarshal *minfo)
9705 {
9706         MonoMarshalSpec *res;
9707
9708         res = image_g_new0 (image, MonoMarshalSpec, 1);
9709         res->native = minfo->type;
9710
9711         switch (minfo->type) {
9712         case MONO_NATIVE_LPARRAY:
9713                 res->data.array_data.elem_type = minfo->eltype;
9714                 if (minfo->has_size) {
9715                         res->data.array_data.param_num = minfo->param_num;
9716                         res->data.array_data.num_elem = minfo->count;
9717                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9718                 }
9719                 else {
9720                         res->data.array_data.param_num = -1;
9721                         res->data.array_data.num_elem = -1;
9722                         res->data.array_data.elem_mult = -1;
9723                 }
9724                 break;
9725
9726         case MONO_NATIVE_BYVALTSTR:
9727         case MONO_NATIVE_BYVALARRAY:
9728                 res->data.array_data.num_elem = minfo->count;
9729                 break;
9730
9731         case MONO_NATIVE_CUSTOM:
9732                 if (minfo->marshaltyperef)
9733                         res->data.custom_data.custom_name =
9734                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9735                 if (minfo->mcookie)
9736                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9737                 break;
9738
9739         default:
9740                 break;
9741         }
9742
9743         return res;
9744 }
9745 #endif /* !DISABLE_REFLECTION_EMIT */
9746
9747 MonoReflectionMarshal*
9748 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9749                                                                                    MonoMarshalSpec *spec)
9750 {
9751         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9752         MonoReflectionMarshal *minfo;
9753         MonoType *mtype;
9754
9755         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9756                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9757                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9758                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9759         }
9760
9761         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9762         minfo->type = spec->native;
9763
9764         switch (minfo->type) {
9765         case MONO_NATIVE_LPARRAY:
9766                 minfo->eltype = spec->data.array_data.elem_type;
9767                 minfo->count = spec->data.array_data.num_elem;
9768                 minfo->param_num = spec->data.array_data.param_num;
9769                 break;
9770
9771         case MONO_NATIVE_BYVALTSTR:
9772         case MONO_NATIVE_BYVALARRAY:
9773                 minfo->count = spec->data.array_data.num_elem;
9774                 break;
9775
9776         case MONO_NATIVE_CUSTOM:
9777                 if (spec->data.custom_data.custom_name) {
9778                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9779                         if (mtype)
9780                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9781
9782                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9783                 }
9784                 if (spec->data.custom_data.cookie)
9785                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9786                 break;
9787
9788         default:
9789                 break;
9790         }
9791
9792         return minfo;
9793 }
9794
9795 #ifndef DISABLE_REFLECTION_EMIT
9796 static MonoMethod*
9797 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9798                                          ReflectionMethodBuilder *rmb,
9799                                          MonoMethodSignature *sig)
9800 {
9801         MonoError error;
9802         MonoMethod *m;
9803         MonoMethodNormal *pm;
9804         MonoMarshalSpec **specs;
9805         MonoReflectionMethodAux *method_aux;
9806         MonoImage *image;
9807         gboolean dynamic;
9808         int i;
9809
9810         mono_error_init (&error);
9811         /*
9812          * Methods created using a MethodBuilder should have their memory allocated
9813          * inside the image mempool, while dynamic methods should have their memory
9814          * malloc'd.
9815          */
9816         dynamic = rmb->refs != NULL;
9817         image = dynamic ? NULL : klass->image;
9818
9819         if (!dynamic)
9820                 g_assert (!klass->generic_class);
9821
9822         mono_loader_lock ();
9823
9824         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9825                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9826                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9827         else if (rmb->refs)
9828                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9829         else
9830                 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9831
9832         pm = (MonoMethodNormal*)m;
9833
9834         m->dynamic = dynamic;
9835         m->slot = -1;
9836         m->flags = rmb->attrs;
9837         m->iflags = rmb->iattrs;
9838         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
9839         g_assert (mono_error_ok (&error));
9840         m->klass = klass;
9841         m->signature = sig;
9842         m->skip_visibility = rmb->skip_visibility;
9843         if (rmb->table_idx)
9844                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9845
9846         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9847                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9848                         m->string_ctor = 1;
9849
9850                 m->signature->pinvoke = 1;
9851         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9852                 m->signature->pinvoke = 1;
9853
9854                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9855
9856                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
9857                 g_assert (mono_error_ok (&error));
9858                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
9859                 g_assert (mono_error_ok (&error));
9860                 
9861                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9862
9863                 if (klass->image->dynamic)
9864                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9865
9866                 mono_loader_unlock ();
9867
9868                 return m;
9869         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9870                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9871                 MonoMethodHeader *header;
9872                 guint32 code_size;
9873                 gint32 max_stack, i;
9874                 gint32 num_locals = 0;
9875                 gint32 num_clauses = 0;
9876                 guint8 *code;
9877
9878                 if (rmb->ilgen) {
9879                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9880                         code_size = rmb->ilgen->code_len;
9881                         max_stack = rmb->ilgen->max_stack;
9882                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9883                         if (rmb->ilgen->ex_handlers)
9884                                 num_clauses = method_count_clauses (rmb->ilgen);
9885                 } else {
9886                         if (rmb->code) {
9887                                 code = mono_array_addr (rmb->code, guint8, 0);
9888                                 code_size = mono_array_length (rmb->code);
9889                                 /* we probably need to run a verifier on the code... */
9890                                 max_stack = 8; 
9891                         }
9892                         else {
9893                                 code = NULL;
9894                                 code_size = 0;
9895                                 max_stack = 8;
9896                         }
9897                 }
9898
9899                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
9900                 header->code_size = code_size;
9901                 header->code = image_g_malloc (image, code_size);
9902                 memcpy ((char*)header->code, code, code_size);
9903                 header->max_stack = max_stack;
9904                 header->init_locals = rmb->init_locals;
9905                 header->num_locals = num_locals;
9906
9907                 for (i = 0; i < num_locals; ++i) {
9908                         MonoReflectionLocalBuilder *lb = 
9909                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9910
9911                         header->locals [i] = image_g_new0 (image, MonoType, 1);
9912                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
9913                 }
9914
9915                 header->num_clauses = num_clauses;
9916                 if (num_clauses) {
9917                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9918                                  rmb->ilgen, num_clauses);
9919                 }
9920
9921                 pm->header = header;
9922         }
9923
9924         if (rmb->generic_params) {
9925                 int count = mono_array_length (rmb->generic_params);
9926                 MonoGenericContainer *container = rmb->generic_container;
9927
9928                 g_assert (container);
9929
9930                 container->type_argc = count;
9931                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
9932                 container->owner.method = m;
9933
9934                 m->is_generic = TRUE;
9935                 mono_method_set_generic_container (m, container);
9936
9937                 for (i = 0; i < count; i++) {
9938                         MonoReflectionGenericParam *gp =
9939                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9940                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
9941                         container->type_params [i] = *param;
9942                 }
9943
9944                 if (klass->generic_container) {
9945                         container->parent = klass->generic_container;
9946                         container->context.class_inst = klass->generic_container->context.class_inst;
9947                 }
9948                 container->context.method_inst = mono_get_shared_generic_inst (container);
9949         }
9950
9951         if (rmb->refs) {
9952                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9953                 int i;
9954                 void **data;
9955
9956                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9957
9958                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9959                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9960                 for (i = 0; i < rmb->nrefs; ++i)
9961                         data [i + 1] = rmb->refs [i];
9962         }
9963
9964         method_aux = NULL;
9965
9966         /* Parameter info */
9967         if (rmb->pinfo) {
9968                 if (!method_aux)
9969                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9970                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9971                 for (i = 0; i <= m->signature->param_count; ++i) {
9972                         MonoReflectionParamBuilder *pb;
9973                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9974                                 if ((i > 0) && (pb->attrs)) {
9975                                         /* Make a copy since it might point to a shared type structure */
9976                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9977                                         m->signature->params [i - 1]->attrs = pb->attrs;
9978                                 }
9979
9980                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9981                                         MonoDynamicImage *assembly;
9982                                         guint32 idx, def_type, len;
9983                                         char *p;
9984                                         const char *p2;
9985
9986                                         if (!method_aux->param_defaults) {
9987                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9988                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9989                                         }
9990                                         assembly = (MonoDynamicImage*)klass->image;
9991                                         idx = encode_constant (assembly, pb->def_value, &def_type);
9992                                         /* Copy the data from the blob since it might get realloc-ed */
9993                                         p = assembly->blob.data + idx;
9994                                         len = mono_metadata_decode_blob_size (p, &p2);
9995                                         len += p2 - p;
9996                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
9997                                         method_aux->param_default_types [i] = def_type;
9998                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9999                                 }
10000
10001                                 if (pb->name) {
10002                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10003                                         g_assert (mono_error_ok (&error));
10004                                 }
10005                                 if (pb->cattrs) {
10006                                         if (!method_aux->param_cattr)
10007                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10008                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10009                                 }
10010                         }
10011                 }
10012         }
10013
10014         /* Parameter marshalling */
10015         specs = NULL;
10016         if (rmb->pinfo)         
10017                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10018                         MonoReflectionParamBuilder *pb;
10019                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10020                                 if (pb->marshal_info) {
10021                                         if (specs == NULL)
10022                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10023                                         specs [pb->position] = 
10024                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10025                                 }
10026                         }
10027                 }
10028         if (specs != NULL) {
10029                 if (!method_aux)
10030                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10031                 method_aux->param_marshall = specs;
10032         }
10033
10034         if (klass->image->dynamic && method_aux)
10035                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10036
10037         mono_loader_unlock ();
10038
10039         return m;
10040 }       
10041
10042 static MonoMethod*
10043 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10044 {
10045         ReflectionMethodBuilder rmb;
10046         MonoMethodSignature *sig;
10047
10048         mono_loader_lock ();
10049         sig = ctor_builder_to_signature (klass->image, mb);
10050         mono_loader_unlock ();
10051
10052         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10053
10054         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10055         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10056
10057         /* If we are in a generic class, we might be called multiple times from inflate_method */
10058         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10059                 /* ilgen is no longer needed */
10060                 mb->ilgen = NULL;
10061         }
10062
10063         return mb->mhandle;
10064 }
10065
10066 static MonoMethod*
10067 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10068 {
10069         ReflectionMethodBuilder rmb;
10070         MonoMethodSignature *sig;
10071
10072         mono_loader_lock ();
10073         sig = method_builder_to_signature (klass->image, mb);
10074         mono_loader_unlock ();
10075
10076         reflection_methodbuilder_from_method_builder (&rmb, mb);
10077
10078         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10079         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10080
10081         /* If we are in a generic class, we might be called multiple times from inflate_method */
10082         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10083                 /* ilgen is no longer needed */
10084                 mb->ilgen = NULL;
10085         }
10086         return mb->mhandle;
10087 }
10088
10089 static MonoClassField*
10090 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10091 {
10092         MonoClassField *field;
10093         MonoType *custom;
10094
10095         field = g_new0 (MonoClassField, 1);
10096
10097         field->name = mono_string_to_utf8 (fb->name);
10098         if (fb->attrs || fb->modreq || fb->modopt) {
10099                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10100                 field->type->attrs = fb->attrs;
10101
10102                 g_assert (klass->image->dynamic);
10103                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10104                 g_free (field->type);
10105                 field->type = custom;
10106         } else {
10107                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10108         }
10109         if (fb->offset != -1)
10110                 field->offset = fb->offset;
10111         field->parent = klass;
10112         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10113
10114         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10115
10116         return field;
10117 }
10118 #endif
10119
10120 MonoType*
10121 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10122 {
10123         MonoClass *klass;
10124         MonoReflectionTypeBuilder *tb = NULL;
10125         gboolean is_dynamic = FALSE;
10126         MonoDomain *domain;
10127         MonoClass *geninst;
10128
10129         mono_loader_lock ();
10130
10131         domain = mono_object_domain (type);
10132
10133         if (is_sre_type_builder (mono_object_class (type))) {
10134                 tb = (MonoReflectionTypeBuilder *) type;
10135
10136                 is_dynamic = TRUE;
10137         } else if (is_sre_generic_instance (mono_object_class (type))) {
10138                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10139                 MonoReflectionType *gtd = rgi->generic_type;
10140
10141                 if (is_sre_type_builder (mono_object_class (gtd))) {
10142                         tb = (MonoReflectionTypeBuilder *)gtd;
10143                         is_dynamic = TRUE;
10144                 }
10145         }
10146
10147         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10148         if (tb && tb->generic_container)
10149                 mono_reflection_create_generic_class (tb);
10150
10151         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10152         if (!klass->generic_container) {
10153                 mono_loader_unlock ();
10154                 return NULL;
10155         }
10156
10157         if (klass->wastypebuilder) {
10158                 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
10159
10160                 is_dynamic = TRUE;
10161         }
10162
10163         mono_loader_unlock ();
10164
10165         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10166
10167         return &geninst->byval_arg;
10168 }
10169
10170 MonoClass*
10171 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10172 {
10173         MonoGenericClass *gclass;
10174         MonoGenericInst *inst;
10175
10176         g_assert (klass->generic_container);
10177
10178         inst = mono_metadata_get_generic_inst (type_argc, types);
10179         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10180
10181         return mono_generic_class_get_class (gclass);
10182 }
10183
10184 MonoReflectionMethod*
10185 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10186 {
10187         MonoClass *klass;
10188         MonoMethod *method, *inflated;
10189         MonoMethodInflated *imethod;
10190         MonoGenericContext tmp_context;
10191         MonoGenericInst *ginst;
10192         MonoType **type_argv;
10193         int count, i;
10194
10195         MONO_ARCH_SAVE_REGS;
10196
10197         /*FIXME but this no longer should happen*/
10198         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10199 #ifndef DISABLE_REFLECTION_EMIT
10200                 MonoReflectionMethodBuilder *mb = NULL;
10201                 MonoReflectionTypeBuilder *tb;
10202                 MonoClass *klass;
10203
10204                 mb = (MonoReflectionMethodBuilder *) rmethod;
10205                 tb = (MonoReflectionTypeBuilder *) mb->type;
10206                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10207
10208                 method = methodbuilder_to_mono_method (klass, mb);
10209 #else
10210                 g_assert_not_reached ();
10211                 method = NULL;
10212 #endif
10213         } else {
10214                 method = rmethod->method;
10215         }
10216
10217         klass = method->klass;
10218
10219         if (method->is_inflated)
10220                 method = ((MonoMethodInflated *) method)->declaring;
10221
10222         count = mono_method_signature (method)->generic_param_count;
10223         if (count != mono_array_length (types))
10224                 return NULL;
10225
10226         type_argv = g_new0 (MonoType *, count);
10227         for (i = 0; i < count; i++) {
10228                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10229                 type_argv [i] = mono_reflection_type_get_handle (garg);
10230         }
10231         ginst = mono_metadata_get_generic_inst (count, type_argv);
10232         g_free (type_argv);
10233
10234         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10235         tmp_context.method_inst = ginst;
10236
10237         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10238         imethod = (MonoMethodInflated *) inflated;
10239
10240         /*FIXME but I think this is no longer necessary*/
10241         if (method->klass->image->dynamic) {
10242                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10243                 /*
10244                  * This table maps metadata structures representing inflated methods/fields
10245                  * to the reflection objects representing their generic definitions.
10246                  */
10247                 mono_loader_lock ();
10248                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10249                 mono_loader_unlock ();
10250         }
10251         
10252         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10253 }
10254
10255 #ifndef DISABLE_REFLECTION_EMIT
10256
10257 static MonoMethod *
10258 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10259 {
10260         MonoMethodInflated *imethod;
10261         MonoGenericContext *context;
10262         int i;
10263
10264         /*
10265          * With generic code sharing the klass might not be inflated.
10266          * This can happen because classes inflated with their own
10267          * type arguments are "normalized" to the uninflated class.
10268          */
10269         if (!klass->generic_class)
10270                 return method;
10271
10272         context = mono_class_get_context (klass);
10273
10274         if (klass->method.count) {
10275                 /* Find the already created inflated method */
10276                 for (i = 0; i < klass->method.count; ++i) {
10277                         g_assert (klass->methods [i]->is_inflated);
10278                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10279                                 break;
10280                 }
10281                 g_assert (i < klass->method.count);
10282                 imethod = (MonoMethodInflated*)klass->methods [i];
10283         } else {
10284                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10285         }
10286
10287         if (method->is_generic && method->klass->image->dynamic) {
10288                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10289
10290                 mono_loader_lock ();
10291                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10292                 mono_loader_unlock ();
10293         }
10294         return (MonoMethod *) imethod;
10295 }
10296
10297 static MonoMethod *
10298 inflate_method (MonoReflectionType *type, MonoObject *obj)
10299 {
10300         MonoMethod *method;
10301         MonoClass *gklass;
10302
10303         MonoClass *type_class = mono_object_class (type);
10304
10305         if (is_sre_generic_instance (type_class)) {
10306                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10307                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10308         } else if (is_sre_type_builder (type_class)) {
10309                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10310         } else if (type->type) {
10311                 gklass = mono_class_from_mono_type (type->type);
10312                 gklass = mono_class_get_generic_type_definition (gklass);
10313         } else {
10314                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10315         }
10316
10317         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10318                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10319                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10320                 else
10321                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10322         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10323                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10324         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10325                 method = ((MonoReflectionMethod *) obj)->method;
10326         else {
10327                 method = NULL; /* prevent compiler warning */
10328                 g_error ("can't handle type %s", obj->vtable->klass->name);
10329         }
10330
10331         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10332 }
10333
10334 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10335 void
10336 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10337                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10338                                           MonoArray *events)
10339 {
10340         MonoGenericClass *gclass;
10341         MonoDynamicGenericClass *dgclass;
10342         MonoClass *klass, *gklass;
10343         MonoType *gtype;
10344         int i;
10345
10346         MONO_ARCH_SAVE_REGS;
10347
10348         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10349         klass = mono_class_from_mono_type (gtype);
10350         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10351         gclass = gtype->data.generic_class;
10352
10353         if (!gclass->is_dynamic)
10354                 return;
10355
10356         dgclass = (MonoDynamicGenericClass *) gclass;
10357
10358         if (dgclass->initialized)
10359                 return;
10360
10361         gklass = gclass->container_class;
10362         mono_class_init (gklass);
10363
10364         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10365         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10366         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10367
10368         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10369         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10370         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10371         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10372         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10373
10374         for (i = 0; i < dgclass->count_methods; i++) {
10375                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10376
10377                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10378         }
10379
10380         for (i = 0; i < dgclass->count_ctors; i++) {
10381                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10382
10383                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10384         }
10385
10386         for (i = 0; i < dgclass->count_fields; i++) {
10387                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10388                 MonoClassField *field, *inflated_field = NULL;
10389
10390                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10391                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10392                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10393                         field = ((MonoReflectionField *) obj)->field;
10394                 else {
10395                         field = NULL; /* prevent compiler warning */
10396                         g_assert_not_reached ();
10397                 }
10398
10399                 dgclass->fields [i] = *field;
10400                 dgclass->fields [i].parent = klass;
10401                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10402                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10403                 dgclass->field_generic_types [i] = field->type;
10404                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10405                 dgclass->field_objects [i] = obj;
10406
10407                 if (inflated_field) {
10408                         g_free (inflated_field);
10409                 } else {
10410                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10411                 }
10412         }
10413
10414         dgclass->initialized = TRUE;
10415 }
10416
10417 static void
10418 fix_partial_generic_class (MonoClass *klass)
10419 {
10420         MonoClass *gklass = klass->generic_class->container_class;
10421         MonoDynamicGenericClass *dgclass;
10422         int i;
10423
10424         if (klass->wastypebuilder)
10425                 return;
10426
10427         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10428
10429         if (!dgclass->initialized)
10430                 return;
10431
10432         if (klass->method.count != gklass->method.count) {
10433                 klass->method.count = gklass->method.count;
10434                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10435
10436                 for (i = 0; i < klass->method.count; i++) {
10437                         klass->methods [i] = mono_class_inflate_generic_method_full (
10438                                 gklass->methods [i], klass, mono_class_get_context (klass));
10439                 }
10440         }
10441
10442         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10443                 klass->interface_count = gklass->interface_count;
10444                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10445                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10446
10447                 for (i = 0; i < gklass->interface_count; ++i) {
10448                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10449                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10450                         mono_metadata_free_type (iface_type);
10451
10452                         ensure_runtime_vtable (klass->interfaces [i]);
10453                 }
10454                 klass->interfaces_inited = 1;
10455         }
10456
10457         if (klass->field.count != gklass->field.count) {
10458                 klass->field.count = gklass->field.count;
10459                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10460
10461                 for (i = 0; i < klass->field.count; i++) {
10462                         klass->fields [i] = gklass->fields [i];
10463                         klass->fields [i].parent = klass;
10464                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10465                 }
10466         }
10467
10468         /*We can only finish with this klass once it's parent has as well*/
10469         if (gklass->wastypebuilder)
10470                 klass->wastypebuilder = TRUE;
10471         return;
10472 }
10473
10474 static void
10475 ensure_generic_class_runtime_vtable (MonoClass *klass)
10476 {
10477         MonoClass *gklass = klass->generic_class->container_class;
10478
10479         ensure_runtime_vtable (gklass); 
10480
10481         fix_partial_generic_class (klass);
10482 }
10483
10484 static void
10485 ensure_runtime_vtable (MonoClass *klass)
10486 {
10487         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10488         int i, num, j;
10489
10490         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10491                 return;
10492         if (klass->parent)
10493                 ensure_runtime_vtable (klass->parent);
10494
10495         if (tb) {
10496                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10497                 num += tb->num_methods;
10498                 klass->method.count = num;
10499                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10500                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10501                 for (i = 0; i < num; ++i)
10502                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10503                 num = tb->num_methods;
10504                 j = i;
10505                 for (i = 0; i < num; ++i)
10506                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10507         
10508                 if (tb->interfaces) {
10509                         klass->interface_count = mono_array_length (tb->interfaces);
10510                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10511                         for (i = 0; i < klass->interface_count; ++i) {
10512                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10513                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10514                                 ensure_runtime_vtable (klass->interfaces [i]);
10515                         }
10516                         klass->interfaces_inited = 1;
10517                 }
10518         } else if (klass->generic_class){
10519                 ensure_generic_class_runtime_vtable (klass);
10520         }
10521
10522         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10523                 for (i = 0; i < klass->method.count; ++i)
10524                         klass->methods [i]->slot = i;
10525                 
10526                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10527                 mono_class_setup_interface_offsets (klass);
10528                 mono_class_setup_interface_id (klass);
10529         }
10530
10531         /*
10532          * The generic vtable is needed even if image->run is not set since some
10533          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10534          * method->slot being defined.
10535          */
10536
10537         /* 
10538          * tb->methods could not be freed since it is used for determining 
10539          * overrides during dynamic vtable construction.
10540          */
10541 }
10542
10543 void
10544 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10545 {
10546         MonoReflectionTypeBuilder *tb;
10547         int i, onum;
10548
10549         *overrides = NULL;
10550         *num_overrides = 0;
10551
10552         g_assert (klass->image->dynamic);
10553
10554         if (!klass->reflection_info)
10555                 return;
10556
10557         g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
10558
10559         tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
10560
10561         onum = 0;
10562         if (tb->methods) {
10563                 for (i = 0; i < tb->num_methods; ++i) {
10564                         MonoReflectionMethodBuilder *mb = 
10565                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10566                         if (mb->override_method)
10567                                 onum ++;
10568                 }
10569         }
10570
10571         if (onum) {
10572                 *overrides = g_new0 (MonoMethod*, onum * 2);
10573
10574                 onum = 0;
10575                 for (i = 0; i < tb->num_methods; ++i) {
10576                         MonoReflectionMethodBuilder *mb = 
10577                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10578                         if (mb->override_method) {
10579                                 (*overrides) [onum * 2] = 
10580                                         mb->override_method->method;
10581                                 (*overrides) [onum * 2 + 1] =
10582                                         mb->mhandle;
10583
10584                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10585                                 g_assert (mb->override_method->method);
10586                                 g_assert (mb->mhandle);
10587
10588                                 onum ++;
10589                         }
10590                 }
10591         }
10592
10593         *num_overrides = onum;
10594 }
10595
10596 static void
10597 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10598 {
10599         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10600         MonoReflectionFieldBuilder *fb;
10601         MonoClassField *field;
10602         MonoImage *image = klass->image;
10603         const char *p, *p2;
10604         int i;
10605         guint32 len, idx, real_size = 0;
10606
10607         klass->field.count = tb->num_fields;
10608         klass->field.first = 0;
10609
10610         mono_error_init (error);
10611
10612         if (tb->class_size) {
10613                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10614                 klass->packing_size = tb->packing_size;
10615                 real_size = klass->instance_size + tb->class_size;
10616         }
10617
10618         if (!klass->field.count) {
10619                 klass->instance_size = MAX (klass->instance_size, real_size);
10620                 return;
10621         }
10622         
10623         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10624         mono_class_alloc_ext (klass);
10625         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10626
10627         for (i = 0; i < klass->field.count; ++i) {
10628                 fb = mono_array_get (tb->fields, gpointer, i);
10629                 field = &klass->fields [i];
10630                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10631                 if (!mono_error_ok (error))
10632                         return;
10633                 if (fb->attrs) {
10634                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10635                         field->type->attrs = fb->attrs;
10636                 } else {
10637                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10638                 }
10639                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10640                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10641                 if (fb->offset != -1)
10642                         field->offset = fb->offset;
10643                 field->parent = klass;
10644                 fb->handle = field;
10645                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10646
10647                 if (fb->def_value) {
10648                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10649                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10650                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10651                         /* Copy the data from the blob since it might get realloc-ed */
10652                         p = assembly->blob.data + idx;
10653                         len = mono_metadata_decode_blob_size (p, &p2);
10654                         len += p2 - p;
10655                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10656                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10657                 }
10658         }
10659
10660         klass->instance_size = MAX (klass->instance_size, real_size);
10661         mono_class_layout_fields (klass);
10662 }
10663
10664 static void
10665 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10666 {
10667         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10668         MonoReflectionPropertyBuilder *pb;
10669         MonoImage *image = klass->image;
10670         MonoProperty *properties;
10671         int i;
10672
10673         mono_error_init (error);
10674
10675         if (!klass->ext)
10676                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10677
10678         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10679         klass->ext->property.first = 0;
10680
10681         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10682         klass->ext->properties = properties;
10683         for (i = 0; i < klass->ext->property.count; ++i) {
10684                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10685                 properties [i].parent = klass;
10686                 properties [i].attrs = pb->attrs;
10687                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10688                 if (!mono_error_ok (error))
10689                         return;
10690                 if (pb->get_method)
10691                         properties [i].get = pb->get_method->mhandle;
10692                 if (pb->set_method)
10693                         properties [i].set = pb->set_method->mhandle;
10694
10695                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10696         }
10697 }
10698
10699 MonoReflectionEvent *
10700 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10701 {
10702         MonoEvent *event = g_new0 (MonoEvent, 1);
10703         MonoClass *klass;
10704         int j;
10705
10706         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10707
10708         event->parent = klass;
10709         event->attrs = eb->attrs;
10710         event->name = mono_string_to_utf8 (eb->name);
10711         if (eb->add_method)
10712                 event->add = eb->add_method->mhandle;
10713         if (eb->remove_method)
10714                 event->remove = eb->remove_method->mhandle;
10715         if (eb->raise_method)
10716                 event->raise = eb->raise_method->mhandle;
10717
10718         if (eb->other_methods) {
10719                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10720                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10721                         MonoReflectionMethodBuilder *mb = 
10722                                 mono_array_get (eb->other_methods,
10723                                                 MonoReflectionMethodBuilder*, j);
10724                         event->other [j] = mb->mhandle;
10725                 }
10726         }
10727
10728         return mono_event_get_object (mono_object_domain (tb), klass, event);
10729 }
10730
10731 static void
10732 typebuilder_setup_events (MonoClass *klass, MonoError *error)
10733 {
10734         MonoReflectionTypeBuilder *tb = klass->reflection_info;
10735         MonoReflectionEventBuilder *eb;
10736         MonoImage *image = klass->image;
10737         MonoEvent *events;
10738         int i, j;
10739
10740         mono_error_init (error);
10741
10742         if (!klass->ext)
10743                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10744
10745         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10746         klass->ext->event.first = 0;
10747
10748         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10749         klass->ext->events = events;
10750         for (i = 0; i < klass->ext->event.count; ++i) {
10751                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10752                 events [i].parent = klass;
10753                 events [i].attrs = eb->attrs;
10754                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
10755                 if (!mono_error_ok (error))
10756                         return;
10757                 if (eb->add_method)
10758                         events [i].add = eb->add_method->mhandle;
10759                 if (eb->remove_method)
10760                         events [i].remove = eb->remove_method->mhandle;
10761                 if (eb->raise_method)
10762                         events [i].raise = eb->raise_method->mhandle;
10763
10764                 if (eb->other_methods) {
10765                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10766                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10767                                 MonoReflectionMethodBuilder *mb = 
10768                                         mono_array_get (eb->other_methods,
10769                                                                         MonoReflectionMethodBuilder*, j);
10770                                 events [i].other [j] = mb->mhandle;
10771                         }
10772                 }
10773                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10774         }
10775 }
10776
10777 static gboolean
10778 remove_instantiations_of_and_ensure_contents (gpointer key,
10779                                                   gpointer value,
10780                                                   gpointer user_data)
10781 {
10782         MonoType *type = (MonoType*)key;
10783         MonoClass *klass = (MonoClass*)user_data;
10784
10785         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
10786                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
10787                 return TRUE;
10788         } else
10789                 return FALSE;
10790 }
10791
10792 static void
10793 check_array_for_usertypes (MonoArray *arr)
10794 {
10795         int i;
10796
10797         if (!arr)
10798                 return;
10799
10800         for (i = 0; i < mono_array_length (arr); ++i)
10801                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
10802 }
10803
10804 MonoReflectionType*
10805 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10806 {
10807         MonoError error;
10808         MonoClass *klass;
10809         MonoDomain* domain;
10810         MonoReflectionType* res;
10811         int i, j;
10812
10813         MONO_ARCH_SAVE_REGS;
10814
10815         domain = mono_object_domain (tb);
10816         klass = mono_class_from_mono_type (tb->type.type);
10817
10818         /*
10819          * Check for user defined Type subclasses.
10820          */
10821         RESOLVE_TYPE (tb->parent);
10822         check_array_for_usertypes (tb->interfaces);
10823         if (tb->fields) {
10824                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10825                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10826                         if (fb) {
10827                                 RESOLVE_TYPE (fb->type);
10828                                 check_array_for_usertypes (fb->modreq);
10829                                 check_array_for_usertypes (fb->modopt);
10830                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10831                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
10832                         }
10833                 }
10834         }
10835         if (tb->methods) {
10836                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10837                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10838                         if (mb) {
10839                                 RESOLVE_TYPE (mb->rtype);
10840                                 check_array_for_usertypes (mb->return_modreq);
10841                                 check_array_for_usertypes (mb->return_modopt);
10842                                 check_array_for_usertypes (mb->parameters);
10843                                 if (mb->param_modreq)
10844                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10845                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10846                                 if (mb->param_modopt)
10847                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10848                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10849                         }
10850                 }
10851         }
10852         if (tb->ctors) {
10853                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10854                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10855                         if (mb) {
10856                                 check_array_for_usertypes (mb->parameters);
10857                                 if (mb->param_modreq)
10858                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10859                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10860                                 if (mb->param_modopt)
10861                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10862                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10863                         }
10864                 }
10865         }
10866
10867         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10868
10869         /* 
10870          * we need to lock the domain because the lock will be taken inside
10871          * So, we need to keep the locking order correct.
10872          */
10873         mono_loader_lock ();
10874         mono_domain_lock (domain);
10875         if (klass->wastypebuilder) {
10876                 mono_domain_unlock (domain);
10877                 mono_loader_unlock ();
10878                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10879         }
10880         /*
10881          * Fields to set in klass:
10882          * the various flags: delegate/unicode/contextbound etc.
10883          */
10884         klass->flags = tb->attrs;
10885         klass->has_cctor = 1;
10886         klass->has_finalize = 1;
10887
10888 #if 0
10889         if (!((MonoDynamicImage*)klass->image)->run) {
10890                 if (klass->generic_container) {
10891                         /* FIXME: The code below can't handle generic classes */
10892                         klass->wastypebuilder = TRUE;
10893                         mono_loader_unlock ();
10894                         mono_domain_unlock (domain);
10895                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10896                 }
10897         }
10898 #endif
10899
10900         /* enums are done right away */
10901         if (!klass->enumtype)
10902                 ensure_runtime_vtable (klass);
10903
10904         if (tb->subtypes) {
10905                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10906                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10907                         mono_class_alloc_ext (klass);
10908                         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)));
10909                 }
10910         }
10911
10912         klass->nested_classes_inited = TRUE;
10913
10914         /* fields and object layout */
10915         if (klass->parent) {
10916                 if (!klass->parent->size_inited)
10917                         mono_class_init (klass->parent);
10918                 klass->instance_size = klass->parent->instance_size;
10919                 klass->sizes.class_size = 0;
10920                 klass->min_align = klass->parent->min_align;
10921                 /* if the type has no fields we won't call the field_setup
10922                  * routine which sets up klass->has_references.
10923                  */
10924                 klass->has_references |= klass->parent->has_references;
10925         } else {
10926                 klass->instance_size = sizeof (MonoObject);
10927                 klass->min_align = 1;
10928         }
10929
10930         /* FIXME: handle packing_size and instance_size */
10931         typebuilder_setup_fields (klass, &error);
10932         if (!mono_error_ok (&error))
10933                 goto failure;
10934         typebuilder_setup_properties (klass, &error);
10935         if (!mono_error_ok (&error))
10936                 goto failure;
10937
10938         typebuilder_setup_events (klass, &error);
10939         if (!mono_error_ok (&error))
10940                 goto failure;
10941
10942         klass->wastypebuilder = TRUE;
10943
10944         /* 
10945          * If we are a generic TypeBuilder, there might be instantiations in the type cache
10946          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
10947          * we want to return normal System.MonoType objects, so clear these out from the cache.
10948          *
10949          * Together with this we must ensure the contents of all instances to match the created type.
10950          */
10951         if (domain->type_hash && klass->generic_container)
10952                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
10953
10954         mono_domain_unlock (domain);
10955         mono_loader_unlock ();
10956
10957         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10958                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10959                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10960         }
10961
10962         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10963         g_assert (res != (MonoReflectionType*)tb);
10964
10965         return res;
10966
10967 failure:
10968         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10969         klass->wastypebuilder = TRUE;
10970         mono_domain_unlock (domain);
10971         mono_loader_unlock ();
10972         mono_error_raise_exception (&error);
10973         return NULL;
10974 }
10975
10976 void
10977 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10978 {
10979         MonoGenericParamFull *param;
10980         MonoImage *image;
10981         MonoClass *pklass;
10982
10983         MONO_ARCH_SAVE_REGS;
10984
10985         param = g_new0 (MonoGenericParamFull, 1);
10986
10987         if (gparam->mbuilder) {
10988                 if (!gparam->mbuilder->generic_container) {
10989                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10990                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10991                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10992                         gparam->mbuilder->generic_container->is_method = TRUE;
10993                         /* 
10994                          * Cannot set owner.method, since the MonoMethod is not created yet.
10995                          * Set the image field instead, so type_in_image () works.
10996                          */
10997                         gparam->mbuilder->generic_container->image = klass->image;
10998                 }
10999                 param->param.owner = gparam->mbuilder->generic_container;
11000         } else if (gparam->tbuilder) {
11001                 if (!gparam->tbuilder->generic_container) {
11002                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11003                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11004                         gparam->tbuilder->generic_container->owner.klass = klass;
11005                 }
11006                 param->param.owner = gparam->tbuilder->generic_container;
11007         }
11008
11009         param->info.name = mono_string_to_utf8 (gparam->name);
11010         param->param.num = gparam->index;
11011
11012         image = &gparam->tbuilder->module->dynamic_image->image;
11013         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11014
11015         gparam->type.type = &pklass->byval_arg;
11016
11017         MOVING_GC_REGISTER (&pklass->reflection_info);
11018         pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
11019         mono_image_lock (image);
11020         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11021         mono_image_unlock (image);
11022 }
11023
11024 MonoArray *
11025 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11026 {
11027         MonoReflectionModuleBuilder *module = sig->module;
11028         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11029         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11030         guint32 buflen, i;
11031         MonoArray *result;
11032         SigBuffer buf;
11033
11034         check_array_for_usertypes (sig->arguments);
11035
11036         sigbuffer_init (&buf, 32);
11037
11038         sigbuffer_add_value (&buf, 0x07);
11039         sigbuffer_add_value (&buf, na);
11040         if (assembly != NULL){
11041                 for (i = 0; i < na; ++i) {
11042                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11043                         encode_reflection_type (assembly, type, &buf);
11044                 }
11045         }
11046
11047         buflen = buf.p - buf.buf;
11048         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11049         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11050         sigbuffer_free (&buf);
11051
11052         return result;
11053 }
11054
11055 MonoArray *
11056 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11057 {
11058         MonoDynamicImage *assembly = sig->module->dynamic_image;
11059         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11060         guint32 buflen, i;
11061         MonoArray *result;
11062         SigBuffer buf;
11063
11064         check_array_for_usertypes (sig->arguments);
11065
11066         sigbuffer_init (&buf, 32);
11067
11068         sigbuffer_add_value (&buf, 0x06);
11069         for (i = 0; i < na; ++i) {
11070                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11071                 encode_reflection_type (assembly, type, &buf);
11072         }
11073
11074         buflen = buf.p - buf.buf;
11075         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11076         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11077         sigbuffer_free (&buf);
11078
11079         return result;
11080 }
11081
11082 void 
11083 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11084 {
11085         ReflectionMethodBuilder rmb;
11086         MonoMethodSignature *sig;
11087         MonoClass *klass;
11088         GSList *l;
11089         int i;
11090
11091         sig = dynamic_method_to_signature (mb);
11092
11093         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11094
11095         /*
11096          * Resolve references.
11097          */
11098         /* 
11099          * Every second entry in the refs array is reserved for storing handle_class,
11100          * which is needed by the ldtoken implementation in the JIT.
11101          */
11102         rmb.nrefs = mb->nrefs;
11103         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11104         for (i = 0; i < mb->nrefs; i += 2) {
11105                 MonoClass *handle_class;
11106                 gpointer ref;
11107                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11108
11109                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11110                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11111                         /*
11112                          * The referenced DynamicMethod should already be created by the managed
11113                          * code, except in the case of circular references. In that case, we store
11114                          * method in the refs array, and fix it up later when the referenced 
11115                          * DynamicMethod is created.
11116                          */
11117                         if (method->mhandle) {
11118                                 ref = method->mhandle;
11119                         } else {
11120                                 /* FIXME: GC object stored in unmanaged memory */
11121                                 ref = method;
11122
11123                                 /* FIXME: GC object stored in unmanaged memory */
11124                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11125                         }
11126                         handle_class = mono_defaults.methodhandle_class;
11127                 } else {
11128                         MonoException *ex = NULL;
11129                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11130                         if (!ref)
11131                                 ex = mono_get_exception_type_load (NULL, NULL);
11132                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11133                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11134
11135                         if (ex) {
11136                                 g_free (rmb.refs);
11137                                 mono_raise_exception (ex);
11138                                 return;
11139                         }
11140                 }
11141
11142                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11143                 rmb.refs [i + 1] = handle_class;
11144         }               
11145
11146         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11147
11148         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11149
11150         /* Fix up refs entries pointing at us */
11151         for (l = mb->referenced_by; l; l = l->next) {
11152                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11153                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11154                 gpointer *data;
11155                 
11156                 g_assert (method->mhandle);
11157
11158                 data = (gpointer*)wrapper->method_data;
11159                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11160                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11161                                 data [i + 1] = mb->mhandle;
11162                 }
11163         }
11164         g_slist_free (mb->referenced_by);
11165
11166         g_free (rmb.refs);
11167
11168         /* ilgen is no longer needed */
11169         mb->ilgen = NULL;
11170 }
11171
11172 #endif /* DISABLE_REFLECTION_EMIT */
11173
11174 void
11175 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11176 {
11177         g_assert (mb);
11178
11179         if (mb->mhandle)
11180                 mono_runtime_free_method (
11181                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11182 }
11183
11184 /**
11185  * 
11186  * mono_reflection_is_valid_dynamic_token:
11187  * 
11188  * Returns TRUE if token is valid.
11189  * 
11190  */
11191 gboolean
11192 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11193 {
11194         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11195 }
11196
11197 #ifndef DISABLE_REFLECTION_EMIT
11198
11199 /**
11200  * mono_reflection_lookup_dynamic_token:
11201  *
11202  * Finish the Builder object pointed to by TOKEN and return the corresponding
11203  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11204  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11205  * mapping table.
11206  *
11207  * LOCKING: Take the loader lock
11208  */
11209 gpointer
11210 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11211 {
11212         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11213         MonoObject *obj;
11214         MonoClass *klass;
11215
11216         mono_loader_lock ();
11217         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11218         mono_loader_unlock ();
11219         if (!obj) {
11220                 if (valid_token)
11221                         g_error ("Could not find required dynamic token 0x%08x", token);
11222                 else
11223                         return NULL;
11224         }
11225
11226         if (!handle_class)
11227                 handle_class = &klass;
11228         return resolve_object (image, obj, handle_class, context);
11229 }
11230
11231 /*
11232  * ensure_complete_type:
11233  *
11234  *   Ensure that KLASS is completed if it is a dynamic type, or references
11235  * dynamic types.
11236  */
11237 static void
11238 ensure_complete_type (MonoClass *klass)
11239 {
11240         if (klass->image->dynamic && !klass->wastypebuilder) {
11241                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
11242
11243                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11244
11245                 // Asserting here could break a lot of code
11246                 //g_assert (klass->wastypebuilder);
11247         }
11248
11249         if (klass->generic_class) {
11250                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11251                 int i;
11252
11253                 for (i = 0; i < inst->type_argc; ++i) {
11254                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11255                 }
11256         }
11257 }
11258
11259 static gpointer
11260 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11261 {
11262         gpointer result = NULL;
11263
11264         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11265                 result = mono_string_intern ((MonoString*)obj);
11266                 *handle_class = mono_defaults.string_class;
11267                 g_assert (result);
11268         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11269                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11270                 if (context) {
11271                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11272                         result = mono_class_from_mono_type (inflated);
11273                         mono_metadata_free_type (inflated);
11274                 } else {
11275                         result = mono_class_from_mono_type (type);
11276                 }
11277                 *handle_class = mono_defaults.typehandle_class;
11278                 g_assert (result);
11279         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11280                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11281                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11282                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11283                 result = ((MonoReflectionMethod*)obj)->method;
11284                 if (context)
11285                         result = mono_class_inflate_generic_method (result, context);
11286                 *handle_class = mono_defaults.methodhandle_class;
11287                 g_assert (result);
11288         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11289                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11290                 result = mb->mhandle;
11291                 if (!result) {
11292                         /* Type is not yet created */
11293                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11294
11295                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11296
11297                         /*
11298                          * Hopefully this has been filled in by calling CreateType() on the
11299                          * TypeBuilder.
11300                          */
11301                         /*
11302                          * TODO: This won't work if the application finishes another 
11303                          * TypeBuilder instance instead of this one.
11304                          */
11305                         result = mb->mhandle;
11306                 }
11307                 if (context)
11308                         result = mono_class_inflate_generic_method (result, context);
11309                 *handle_class = mono_defaults.methodhandle_class;
11310         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11311                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11312
11313                 result = cb->mhandle;
11314                 if (!result) {
11315                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11316
11317                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11318                         result = cb->mhandle;
11319                 }
11320                 if (context)
11321                         result = mono_class_inflate_generic_method (result, context);
11322                 *handle_class = mono_defaults.methodhandle_class;
11323         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11324                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11325
11326                 ensure_complete_type (field->parent);
11327                 if (context) {
11328                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11329                         MonoClass *class = mono_class_from_mono_type (inflated);
11330                         MonoClassField *inflated_field;
11331                         gpointer iter = NULL;
11332                         mono_metadata_free_type (inflated);
11333                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11334                                 if (!strcmp (field->name, inflated_field->name))
11335                                         break;
11336                         }
11337                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11338                         result = inflated_field;
11339                 } else {
11340                         result = field;
11341                 }
11342                 *handle_class = mono_defaults.fieldhandle_class;
11343                 g_assert (result);
11344         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11345                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11346                 result = fb->handle;
11347
11348                 if (!result) {
11349                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11350
11351                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11352                         result = fb->handle;
11353                 }
11354
11355                 if (fb->handle && fb->handle->parent->generic_container) {
11356                         MonoClass *klass = fb->handle->parent;
11357                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11358                         MonoClass *inflated = mono_class_from_mono_type (type);
11359
11360                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11361                         g_assert (result);
11362                         mono_metadata_free_type (type);
11363                 }
11364                 *handle_class = mono_defaults.fieldhandle_class;
11365         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11366                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11367                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11368                 MonoClass *klass;
11369
11370                 klass = type->data.klass;
11371                 if (klass->wastypebuilder) {
11372                         /* Already created */
11373                         result = klass;
11374                 }
11375                 else {
11376                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11377                         result = type->data.klass;
11378                         g_assert (result);
11379                 }
11380                 *handle_class = mono_defaults.typehandle_class;
11381         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11382                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11383                 MonoMethodSignature *sig;
11384                 int nargs, i;
11385
11386                 if (helper->arguments)
11387                         nargs = mono_array_length (helper->arguments);
11388                 else
11389                         nargs = 0;
11390
11391                 sig = mono_metadata_signature_alloc (image, nargs);
11392                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11393                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11394
11395                 if (helper->unmanaged_call_conv) { /* unmanaged */
11396                         sig->call_convention = helper->unmanaged_call_conv - 1;
11397                         sig->pinvoke = TRUE;
11398                 } else if (helper->call_conv & 0x02) {
11399                         sig->call_convention = MONO_CALL_VARARG;
11400                 } else {
11401                         sig->call_convention = MONO_CALL_DEFAULT;
11402                 }
11403
11404                 sig->param_count = nargs;
11405                 /* TODO: Copy type ? */
11406                 sig->ret = helper->return_type->type;
11407                 for (i = 0; i < nargs; ++i)
11408                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11409
11410                 result = sig;
11411                 *handle_class = NULL;
11412         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11413                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11414                 /* Already created by the managed code */
11415                 g_assert (method->mhandle);
11416                 result = method->mhandle;
11417                 *handle_class = mono_defaults.methodhandle_class;
11418         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11419                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11420                 type = mono_class_inflate_generic_type (type, context);
11421                 result = mono_class_from_mono_type (type);
11422                 *handle_class = mono_defaults.typehandle_class;
11423                 g_assert (result);
11424                 mono_metadata_free_type (type);
11425         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11426                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11427                 type = mono_class_inflate_generic_type (type, context);
11428                 result = mono_class_from_mono_type (type);
11429                 *handle_class = mono_defaults.typehandle_class;
11430                 g_assert (result);
11431                 mono_metadata_free_type (type);
11432         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11433                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11434                 MonoClass *inflated;
11435                 MonoType *type;
11436                 MonoClassField *field;
11437
11438                 if (is_sre_field_builder (mono_object_class (f->fb)))
11439                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11440                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11441                         field = ((MonoReflectionField*)f->fb)->field;
11442                 else
11443                         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)));
11444
11445                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11446                 inflated = mono_class_from_mono_type (type);
11447
11448                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11449                 ensure_complete_type (field->parent);
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 }