Merged into single file, added assertions
[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  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 void
206 mono_reflection_init (void)
207 {
208 }
209
210 static void
211 sigbuffer_init (SigBuffer *buf, int size)
212 {
213         buf->buf = g_malloc (size);
214         buf->p = buf->buf;
215         buf->end = buf->buf + size;
216 }
217
218 static void
219 sigbuffer_make_room (SigBuffer *buf, int size)
220 {
221         if (buf->end - buf->p < size) {
222                 int new_size = buf->end - buf->buf + size + 32;
223                 char *p = g_realloc (buf->buf, new_size);
224                 size = buf->p - buf->buf;
225                 buf->buf = p;
226                 buf->p = p + size;
227                 buf->end = buf->buf + new_size;
228         }
229 }
230
231 static void
232 sigbuffer_add_value (SigBuffer *buf, guint32 val)
233 {
234         sigbuffer_make_room (buf, 6);
235         mono_metadata_encode_value (val, buf->p, &buf->p);
236 }
237
238 static void
239 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
240 {
241         sigbuffer_make_room (buf, 1);
242         buf->p [0] = val;
243         buf->p++;
244 }
245
246 static void
247 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
248 {
249         sigbuffer_make_room (buf, size);
250         memcpy (buf->p, p, size);
251         buf->p += size;
252 }
253
254 static void
255 sigbuffer_free (SigBuffer *buf)
256 {
257         g_free (buf->buf);
258 }
259
260 #ifndef DISABLE_REFLECTION_EMIT
261 /**
262  * mp_g_alloc:
263  *
264  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
265  * from the C heap.
266  */
267 static gpointer
268 image_g_malloc (MonoImage *image, guint size)
269 {
270         if (image)
271                 return mono_image_alloc (image, size);
272         else
273                 return g_malloc (size);
274 }
275 #endif /* !DISABLE_REFLECTION_EMIT */
276
277 /**
278  * image_g_alloc0:
279  *
280  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281  * from the C heap.
282  */
283 static gpointer
284 image_g_malloc0 (MonoImage *image, guint size)
285 {
286         if (image)
287                 return mono_image_alloc0 (image, size);
288         else
289                 return g_malloc0 (size);
290 }
291
292 #ifndef DISABLE_REFLECTION_EMIT
293 static char*
294 image_strdup (MonoImage *image, const char *s)
295 {
296         if (image)
297                 return mono_image_strdup (image, s);
298         else
299                 return g_strdup (s);
300 }
301 #endif
302
303 #define image_g_new(image,struct_type, n_structs)               \
304     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
305
306 #define image_g_new0(image,struct_type, n_structs)              \
307     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
308
309
310 static void
311 alloc_table (MonoDynamicTable *table, guint nrows)
312 {
313         table->rows = nrows;
314         g_assert (table->columns);
315         if (nrows + 1 >= table->alloc_rows) {
316                 while (nrows + 1 >= table->alloc_rows) {
317                         if (table->alloc_rows == 0)
318                                 table->alloc_rows = 16;
319                         else
320                                 table->alloc_rows *= 2;
321                 }
322
323                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
324         }
325 }
326
327 static void
328 make_room_in_stream (MonoDynamicStream *stream, int size)
329 {
330         if (size <= stream->alloc_size)
331                 return;
332         
333         while (stream->alloc_size <= size) {
334                 if (stream->alloc_size < 4096)
335                         stream->alloc_size = 4096;
336                 else
337                         stream->alloc_size *= 2;
338         }
339         
340         stream->data = g_realloc (stream->data, stream->alloc_size);
341 }
342
343 static guint32
344 string_heap_insert (MonoDynamicStream *sh, const char *str)
345 {
346         guint32 idx;
347         guint32 len;
348         gpointer oldkey, oldval;
349
350         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
351                 return GPOINTER_TO_UINT (oldval);
352
353         len = strlen (str) + 1;
354         idx = sh->index;
355         
356         make_room_in_stream (sh, idx + len);
357
358         /*
359          * We strdup the string even if we already copy them in sh->data
360          * so that the string pointers in the hash remain valid even if
361          * we need to realloc sh->data. We may want to avoid that later.
362          */
363         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
364         memcpy (sh->data + idx, str, len);
365         sh->index += len;
366         return idx;
367 }
368
369 static guint32
370 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
371 {
372         char *name = mono_string_to_utf8 (str);
373         guint32 idx;
374         idx = string_heap_insert (sh, name);
375         g_free (name);
376         return idx;
377 }
378
379 #ifndef DISABLE_REFLECTION_EMIT
380 static void
381 string_heap_init (MonoDynamicStream *sh)
382 {
383         sh->index = 0;
384         sh->alloc_size = 4096;
385         sh->data = g_malloc (4096);
386         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
387         string_heap_insert (sh, "");
388 }
389 #endif
390
391 static guint32
392 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
393 {
394         guint32 idx;
395         
396         make_room_in_stream (stream, stream->index + len);
397         memcpy (stream->data + stream->index, data, len);
398         idx = stream->index;
399         stream->index += len;
400         /* 
401          * align index? Not without adding an additional param that controls it since
402          * we may store a blob value in pieces.
403          */
404         return idx;
405 }
406
407 static guint32
408 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
409 {
410         guint32 idx;
411         
412         make_room_in_stream (stream, stream->index + len);
413         memset (stream->data + stream->index, 0, len);
414         idx = stream->index;
415         stream->index += len;
416         return idx;
417 }
418
419 static void
420 stream_data_align (MonoDynamicStream *stream)
421 {
422         char buf [4] = {0};
423         guint32 count = stream->index % 4;
424
425         /* we assume the stream data will be aligned */
426         if (count)
427                 mono_image_add_stream_data (stream, buf, 4 - count);
428 }
429
430 #ifndef DISABLE_REFLECTION_EMIT
431 static int
432 mono_blob_entry_hash (const char* str)
433 {
434         guint len, h;
435         const char *end;
436         len = mono_metadata_decode_blob_size (str, &str);
437         if (len > 0) {
438                 end = str + len;
439                 h = *str;
440                 for (str += 1; str < end; str++)
441                         h = (h << 5) - h + *str;
442                 return h;
443         } else {
444                 return 0;
445         }
446 }
447
448 static gboolean
449 mono_blob_entry_equal (const char *str1, const char *str2) {
450         int len, len2;
451         const char *end1;
452         const char *end2;
453         len = mono_metadata_decode_blob_size (str1, &end1);
454         len2 = mono_metadata_decode_blob_size (str2, &end2);
455         if (len != len2)
456                 return 0;
457         return memcmp (end1, end2, len) == 0;
458 }
459 #endif
460 static guint32
461 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
462 {
463         guint32 idx;
464         char *copy;
465         gpointer oldkey, oldval;
466
467         copy = g_malloc (s1+s2);
468         memcpy (copy, b1, s1);
469         memcpy (copy + s1, b2, s2);
470         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
471                 g_free (copy);
472                 idx = GPOINTER_TO_UINT (oldval);
473         } else {
474                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
475                 mono_image_add_stream_data (&assembly->blob, b2, s2);
476                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
477         }
478         return idx;
479 }
480
481 static guint32
482 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
483 {
484         char blob_size [8];
485         char *b = blob_size;
486         guint32 size = buf->p - buf->buf;
487         /* store length */
488         g_assert (size <= (buf->end - buf->buf));
489         mono_metadata_encode_value (size, b, &b);
490         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
491 }
492
493 /*
494  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
495  * dest may be misaligned.
496  */
497 static void
498 swap_with_size (char *dest, const char* val, int len, int nelem) {
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
500         int elem;
501
502         for (elem = 0; elem < nelem; ++elem) {
503                 switch (len) {
504                 case 1:
505                         *dest = *val;
506                         break;
507                 case 2:
508                         dest [0] = val [1];
509                         dest [1] = val [0];
510                         break;
511                 case 4:
512                         dest [0] = val [3];
513                         dest [1] = val [2];
514                         dest [2] = val [1];
515                         dest [3] = val [0];
516                         break;
517                 case 8:
518                         dest [0] = val [7];
519                         dest [1] = val [6];
520                         dest [2] = val [5];
521                         dest [3] = val [4];
522                         dest [4] = val [3];
523                         dest [5] = val [2];
524                         dest [6] = val [1];
525                         dest [7] = val [0];
526                         break;
527                 default:
528                         g_assert_not_reached ();
529                 }
530                 dest += len;
531                 val += len;
532         }
533 #else
534         memcpy (dest, val, len * nelem);
535 #endif
536 }
537
538 static guint32
539 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
540 {
541         char blob_size [64];
542         char *b = blob_size;
543         guint32 idx = 0, len;
544
545         len = str->length * 2;
546         mono_metadata_encode_value (len, b, &b);
547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
548         {
549                 char *swapped = g_malloc (2 * mono_string_length (str));
550                 const char *p = (const char*)mono_string_chars (str);
551
552                 swap_with_size (swapped, p, 2, mono_string_length (str));
553                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
554                 g_free (swapped);
555         }
556 #else
557         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
558 #endif
559         return idx;
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static MonoClass *
564 default_class_from_mono_type (MonoType *type)
565 {
566         switch (type->type) {
567         case MONO_TYPE_OBJECT:
568                 return mono_defaults.object_class;
569         case MONO_TYPE_VOID:
570                 return mono_defaults.void_class;
571         case MONO_TYPE_BOOLEAN:
572                 return mono_defaults.boolean_class;
573         case MONO_TYPE_CHAR:
574                 return mono_defaults.char_class;
575         case MONO_TYPE_I1:
576                 return mono_defaults.sbyte_class;
577         case MONO_TYPE_U1:
578                 return mono_defaults.byte_class;
579         case MONO_TYPE_I2:
580                 return mono_defaults.int16_class;
581         case MONO_TYPE_U2:
582                 return mono_defaults.uint16_class;
583         case MONO_TYPE_I4:
584                 return mono_defaults.int32_class;
585         case MONO_TYPE_U4:
586                 return mono_defaults.uint32_class;
587         case MONO_TYPE_I:
588                 return mono_defaults.int_class;
589         case MONO_TYPE_U:
590                 return mono_defaults.uint_class;
591         case MONO_TYPE_I8:
592                 return mono_defaults.int64_class;
593         case MONO_TYPE_U8:
594                 return mono_defaults.uint64_class;
595         case MONO_TYPE_R4:
596                 return mono_defaults.single_class;
597         case MONO_TYPE_R8:
598                 return mono_defaults.double_class;
599         case MONO_TYPE_STRING:
600                 return mono_defaults.string_class;
601         default:
602                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
603                 g_assert_not_reached ();
604         }
605         
606         return NULL;
607 }
608 #endif
609
610 /*
611  * mono_class_get_ref_info:
612  *
613  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
614  */
615 gpointer
616 mono_class_get_ref_info (MonoClass *klass)
617 {
618         if (klass->ref_info_handle == 0)
619                 return NULL;
620         else
621                 return mono_gchandle_get_target (klass->ref_info_handle);
622 }
623
624 void
625 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
626 {
627         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
628         g_assert (klass->ref_info_handle != 0);
629 }
630
631 void
632 mono_class_free_ref_info (MonoClass *klass)
633 {
634         if (klass->ref_info_handle) {
635                 mono_gchandle_free (klass->ref_info_handle);
636                 klass->ref_info_handle = 0;
637         }
638 }
639
640 static void
641 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
642 {
643         int i;
644         MonoGenericInst *class_inst;
645         MonoClass *klass;
646
647         g_assert (gclass);
648
649         class_inst = gclass->context.class_inst;
650
651         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
652         klass = gclass->container_class;
653         sigbuffer_add_value (buf, klass->byval_arg.type);
654         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
655
656         sigbuffer_add_value (buf, class_inst->type_argc);
657         for (i = 0; i < class_inst->type_argc; ++i)
658                 encode_type (assembly, class_inst->type_argv [i], buf);
659
660 }
661
662 static void
663 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
664 {
665         if (!type) {
666                 g_assert_not_reached ();
667                 return;
668         }
669                 
670         if (type->byref)
671                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
672
673         switch (type->type){
674         case MONO_TYPE_VOID:
675         case MONO_TYPE_BOOLEAN:
676         case MONO_TYPE_CHAR:
677         case MONO_TYPE_I1:
678         case MONO_TYPE_U1:
679         case MONO_TYPE_I2:
680         case MONO_TYPE_U2:
681         case MONO_TYPE_I4:
682         case MONO_TYPE_U4:
683         case MONO_TYPE_I8:
684         case MONO_TYPE_U8:
685         case MONO_TYPE_R4:
686         case MONO_TYPE_R8:
687         case MONO_TYPE_I:
688         case MONO_TYPE_U:
689         case MONO_TYPE_STRING:
690         case MONO_TYPE_OBJECT:
691         case MONO_TYPE_TYPEDBYREF:
692                 sigbuffer_add_value (buf, type->type);
693                 break;
694         case MONO_TYPE_PTR:
695                 sigbuffer_add_value (buf, type->type);
696                 encode_type (assembly, type->data.type, buf);
697                 break;
698         case MONO_TYPE_SZARRAY:
699                 sigbuffer_add_value (buf, type->type);
700                 encode_type (assembly, &type->data.klass->byval_arg, buf);
701                 break;
702         case MONO_TYPE_VALUETYPE:
703         case MONO_TYPE_CLASS: {
704                 MonoClass *k = mono_class_from_mono_type (type);
705
706                 if (k->generic_container) {
707                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
708                         encode_generic_class (assembly, gclass, buf);
709                 } else {
710                         /*
711                          * Make sure we use the correct type.
712                          */
713                         sigbuffer_add_value (buf, k->byval_arg.type);
714                         /*
715                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
716                          * otherwise two typerefs could point to the same type, leading to
717                          * verification errors.
718                          */
719                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
720                 }
721                 break;
722         }
723         case MONO_TYPE_ARRAY:
724                 sigbuffer_add_value (buf, type->type);
725                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
726                 sigbuffer_add_value (buf, type->data.array->rank);
727                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
728                 sigbuffer_add_value (buf, 0);
729                 break;
730         case MONO_TYPE_GENERICINST:
731                 encode_generic_class (assembly, type->data.generic_class, buf);
732                 break;
733         case MONO_TYPE_VAR:
734         case MONO_TYPE_MVAR:
735                 sigbuffer_add_value (buf, type->type);
736                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
737                 break;
738         default:
739                 g_error ("need to encode type %x", type->type);
740         }
741 }
742
743 static void
744 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
745 {
746         if (!type) {
747                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
748                 return;
749         }
750
751         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
752 }
753
754 static void
755 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
756 {
757         int i;
758
759         if (modreq) {
760                 for (i = 0; i < mono_array_length (modreq); ++i) {
761                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
762                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
763                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
764                 }
765         }
766         if (modopt) {
767                 for (i = 0; i < mono_array_length (modopt); ++i) {
768                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
769                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
770                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
771                 }
772         }
773 }
774
775 #ifndef DISABLE_REFLECTION_EMIT
776 static guint32
777 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
778 {
779         SigBuffer buf;
780         int i;
781         guint32 nparams =  sig->param_count;
782         guint32 idx;
783
784         if (!assembly->save)
785                 return 0;
786
787         sigbuffer_init (&buf, 32);
788         /*
789          * FIXME: vararg, explicit_this, differenc call_conv values...
790          */
791         idx = sig->call_convention;
792         if (sig->hasthis)
793                 idx |= 0x20; /* hasthis */
794         if (sig->generic_param_count)
795                 idx |= 0x10; /* generic */
796         sigbuffer_add_byte (&buf, idx);
797         if (sig->generic_param_count)
798                 sigbuffer_add_value (&buf, sig->generic_param_count);
799         sigbuffer_add_value (&buf, nparams);
800         encode_type (assembly, sig->ret, &buf);
801         for (i = 0; i < nparams; ++i) {
802                 if (i == sig->sentinelpos)
803                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804                 encode_type (assembly, sig->params [i], &buf);
805         }
806         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807         sigbuffer_free (&buf);
808         return idx;
809 }
810 #endif
811
812 static guint32
813 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
814 {
815         /*
816          * FIXME: reuse code from method_encode_signature().
817          */
818         SigBuffer buf;
819         int i;
820         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
821         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
822         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
823         guint32 idx;
824
825         sigbuffer_init (&buf, 32);
826         /* LAMESPEC: all the call conv spec is foobared */
827         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
828         if (mb->call_conv & 2)
829                 idx |= 0x5; /* vararg */
830         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
831                 idx |= 0x20; /* hasthis */
832         if (ngparams)
833                 idx |= 0x10; /* generic */
834         sigbuffer_add_byte (&buf, idx);
835         if (ngparams)
836                 sigbuffer_add_value (&buf, ngparams);
837         sigbuffer_add_value (&buf, nparams + notypes);
838         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
839         encode_reflection_type (assembly, mb->rtype, &buf);
840         for (i = 0; i < nparams; ++i) {
841                 MonoArray *modreq = NULL;
842                 MonoArray *modopt = NULL;
843                 MonoReflectionType *pt;
844
845                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
846                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
847                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
848                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
849                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
850                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
851                 encode_reflection_type (assembly, pt, &buf);
852         }
853         if (notypes)
854                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
855         for (i = 0; i < notypes; ++i) {
856                 MonoReflectionType *pt;
857
858                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
859                 encode_reflection_type (assembly, pt, &buf);
860         }
861
862         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
863         sigbuffer_free (&buf);
864         return idx;
865 }
866
867 static guint32
868 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
869 {
870         MonoDynamicTable *table;
871         guint32 *values;
872         guint32 idx, sig_idx;
873         guint nl = mono_array_length (ilgen->locals);
874         SigBuffer buf;
875         int i;
876
877         sigbuffer_init (&buf, 32);
878         sigbuffer_add_value (&buf, 0x07);
879         sigbuffer_add_value (&buf, nl);
880         for (i = 0; i < nl; ++i) {
881                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
882                 
883                 if (lb->is_pinned)
884                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
885                 
886                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
887         }
888         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
889         sigbuffer_free (&buf);
890
891         if (assembly->standalonesig_cache == NULL)
892                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
893         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
894         if (idx)
895                 return idx;
896
897         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
898         idx = table->next_idx ++;
899         table->rows ++;
900         alloc_table (table, table->rows);
901         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
902
903         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
904
905         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
906
907         return idx;
908 }
909
910 static guint32
911 method_count_clauses (MonoReflectionILGen *ilgen)
912 {
913         guint32 num_clauses = 0;
914         int i;
915
916         MonoILExceptionInfo *ex_info;
917         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
918                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
919                 if (ex_info->handlers)
920                         num_clauses += mono_array_length (ex_info->handlers);
921                 else
922                         num_clauses++;
923         }
924
925         return num_clauses;
926 }
927
928 #ifndef DISABLE_REFLECTION_EMIT
929 static MonoExceptionClause*
930 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
931 {
932         MonoExceptionClause *clauses;
933         MonoExceptionClause *clause;
934         MonoILExceptionInfo *ex_info;
935         MonoILExceptionBlock *ex_block;
936         guint32 finally_start;
937         int i, j, clause_index;;
938
939         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
940
941         clause_index = 0;
942         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
943                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
944                 finally_start = ex_info->start + ex_info->len;
945                 if (!ex_info->handlers)
946                         continue;
947                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
948                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
949                         clause = &(clauses [clause_index]);
950
951                         clause->flags = ex_block->type;
952                         clause->try_offset = ex_info->start;
953
954                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
955                                 clause->try_len = finally_start - ex_info->start;
956                         else
957                                 clause->try_len = ex_info->len;
958                         clause->handler_offset = ex_block->start;
959                         clause->handler_len = ex_block->len;
960                         if (ex_block->extype) {
961                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
962                         } else {
963                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
964                                         clause->data.filter_offset = ex_block->filter_offset;
965                                 else
966                                         clause->data.filter_offset = 0;
967                         }
968                         finally_start = ex_block->start + ex_block->len;
969
970                         clause_index ++;
971                 }
972         }
973
974         return clauses;
975 }
976 #endif /* !DISABLE_REFLECTION_EMIT */
977
978 static guint32
979 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
980 {
981         char flags = 0;
982         guint32 idx;
983         guint32 code_size;
984         gint32 max_stack, i;
985         gint32 num_locals = 0;
986         gint32 num_exception = 0;
987         gint maybe_small;
988         guint32 fat_flags;
989         char fat_header [12];
990         guint32 int_value;
991         guint16 short_value;
992         guint32 local_sig = 0;
993         guint32 header_size = 12;
994         MonoArray *code;
995
996         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
997                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
998                 return 0;
999
1000         /*if (mb->name)
1001                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1002         if (mb->ilgen) {
1003                 code = mb->ilgen->code;
1004                 code_size = mb->ilgen->code_len;
1005                 max_stack = mb->ilgen->max_stack;
1006                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1007                 if (mb->ilgen->ex_handlers)
1008                         num_exception = method_count_clauses (mb->ilgen);
1009         } else {
1010                 code = mb->code;
1011                 if (code == NULL){
1012                         char *name = mono_string_to_utf8 (mb->name);
1013                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1014                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1015                         g_free (str);
1016                         g_free (name);
1017                         mono_raise_exception (exception);
1018                 }
1019
1020                 code_size = mono_array_length (code);
1021                 max_stack = 8; /* we probably need to run a verifier on the code... */
1022         }
1023
1024         stream_data_align (&assembly->code);
1025
1026         /* check for exceptions, maxstack, locals */
1027         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1028         if (maybe_small) {
1029                 if (code_size < 64 && !(code_size & 1)) {
1030                         flags = (code_size << 2) | 0x2;
1031                 } else if (code_size < 32 && (code_size & 1)) {
1032                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1033                 } else {
1034                         goto fat_header;
1035                 }
1036                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
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 + 1));
1040                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1041                 return assembly->text_rva + idx;
1042         } 
1043 fat_header:
1044         if (num_locals)
1045                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1046         /* 
1047          * FIXME: need to set also the header size in fat_flags.
1048          * (and more sects and init locals flags)
1049          */
1050         fat_flags =  0x03;
1051         if (num_exception)
1052                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1053         if (mb->init_locals)
1054                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1055         fat_header [0] = fat_flags;
1056         fat_header [1] = (header_size / 4 ) << 4;
1057         short_value = GUINT16_TO_LE (max_stack);
1058         memcpy (fat_header + 2, &short_value, 2);
1059         int_value = GUINT32_TO_LE (code_size);
1060         memcpy (fat_header + 4, &int_value, 4);
1061         int_value = GUINT32_TO_LE (local_sig);
1062         memcpy (fat_header + 8, &int_value, 4);
1063         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1064         /* add to the fixup todo list */
1065         if (mb->ilgen && mb->ilgen->num_token_fixups)
1066                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1067         
1068         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1069         if (num_exception) {
1070                 unsigned char sheader [4];
1071                 MonoILExceptionInfo * ex_info;
1072                 MonoILExceptionBlock * ex_block;
1073                 int j;
1074
1075                 stream_data_align (&assembly->code);
1076                 /* always use fat format for now */
1077                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1078                 num_exception *= 6 * sizeof (guint32);
1079                 num_exception += 4; /* include the size of the header */
1080                 sheader [1] = num_exception & 0xff;
1081                 sheader [2] = (num_exception >> 8) & 0xff;
1082                 sheader [3] = (num_exception >> 16) & 0xff;
1083                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1084                 /* fat header, so we are already aligned */
1085                 /* reverse order */
1086                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1087                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1088                         if (ex_info->handlers) {
1089                                 int finally_start = ex_info->start + ex_info->len;
1090                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1091                                         guint32 val;
1092                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1093                                         /* the flags */
1094                                         val = GUINT32_TO_LE (ex_block->type);
1095                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1096                                         /* try offset */
1097                                         val = GUINT32_TO_LE (ex_info->start);
1098                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1099                                         /* need fault, too, probably */
1100                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1101                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1102                                         else
1103                                                 val = GUINT32_TO_LE (ex_info->len);
1104                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105                                         /* handler offset */
1106                                         val = GUINT32_TO_LE (ex_block->start);
1107                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108                                         /* handler len */
1109                                         val = GUINT32_TO_LE (ex_block->len);
1110                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1111                                         finally_start = ex_block->start + ex_block->len;
1112                                         if (ex_block->extype) {
1113                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1114                                         } else {
1115                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1116                                                         val = ex_block->filter_offset;
1117                                                 else
1118                                                         val = 0;
1119                                         }
1120                                         val = GUINT32_TO_LE (val);
1121                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122                                         /*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", 
1123                                                         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);*/
1124                                 }
1125                         } else {
1126                                 g_error ("No clauses for ex info block %d", i);
1127                         }
1128                 }
1129         }
1130         return assembly->text_rva + idx;
1131 }
1132
1133 static guint32
1134 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1135 {
1136         int i;
1137         MonoDynamicTable *table;
1138         guint32 *values;
1139         
1140         table = &assembly->tables [table_idx];
1141
1142         g_assert (col < table->columns);
1143
1144         values = table->values + table->columns;
1145         for (i = 1; i <= table->rows; ++i) {
1146                 if (values [col] == token)
1147                         return i;
1148                 values += table->columns;
1149         }
1150         return 0;
1151 }
1152
1153 /*
1154  * LOCKING: Acquires the loader lock. 
1155  */
1156 static MonoCustomAttrInfo*
1157 lookup_custom_attr (MonoImage *image, gpointer member)
1158 {
1159         MonoCustomAttrInfo* res;
1160
1161         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1162
1163         if (!res)
1164                 return NULL;
1165
1166         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1167         res->cached = 0;
1168         return res;
1169 }
1170
1171 static gboolean
1172 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1173 {
1174         /* FIXME: Need to do more checks */
1175         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1176                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1177
1178                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1179                         return FALSE;
1180         }
1181
1182         return TRUE;
1183 }
1184
1185 static MonoCustomAttrInfo*
1186 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1187 {
1188         int i, index, count, not_visible;
1189         MonoCustomAttrInfo *ainfo;
1190         MonoReflectionCustomAttr *cattr;
1191
1192         if (!cattrs)
1193                 return NULL;
1194         /* FIXME: check in assembly the Run flag is set */
1195
1196         count = mono_array_length (cattrs);
1197
1198         /* Skip nonpublic attributes since MS.NET seems to do the same */
1199         /* FIXME: This needs to be done more globally */
1200         not_visible = 0;
1201         for (i = 0; i < count; ++i) {
1202                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1203                 if (!custom_attr_visible (image, cattr))
1204                         not_visible ++;
1205         }
1206         count -= not_visible;
1207
1208         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1209
1210         ainfo->image = image;
1211         ainfo->num_attrs = count;
1212         ainfo->cached = alloc_img != NULL;
1213         index = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (custom_attr_visible (image, cattr)) {
1217                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1218                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1219                         ainfo->attrs [index].ctor = cattr->ctor->method;
1220                         ainfo->attrs [index].data = saved;
1221                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1222                         index ++;
1223                 }
1224         }
1225
1226         return ainfo;
1227 }
1228
1229 #ifndef DISABLE_REFLECTION_EMIT
1230 /*
1231  * LOCKING: Acquires the loader lock. 
1232  */
1233 static void
1234 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1235 {
1236         MonoCustomAttrInfo *ainfo, *tmp;
1237
1238         if (!cattrs || !mono_array_length (cattrs))
1239                 return;
1240
1241         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1242
1243         mono_loader_lock ();
1244         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1245         if (tmp)
1246                 mono_custom_attrs_free (tmp);
1247         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1248         mono_loader_unlock ();
1249
1250 }
1251 #endif
1252
1253 void
1254 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1255 {
1256         if (!ainfo->cached)
1257                 g_free (ainfo);
1258 }
1259
1260 /*
1261  * idx is the table index of the object
1262  * type is one of MONO_CUSTOM_ATTR_*
1263  */
1264 static void
1265 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1266 {
1267         MonoDynamicTable *table;
1268         MonoReflectionCustomAttr *cattr;
1269         guint32 *values;
1270         guint32 count, i, token;
1271         char blob_size [6];
1272         char *p = blob_size;
1273         
1274         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1275         if (!cattrs)
1276                 return;
1277         count = mono_array_length (cattrs);
1278         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1279         table->rows += count;
1280         alloc_table (table, table->rows);
1281         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1282         idx <<= MONO_CUSTOM_ATTR_BITS;
1283         idx |= type;
1284         for (i = 0; i < count; ++i) {
1285                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1286                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1287                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1288                 type = mono_metadata_token_index (token);
1289                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1290                 switch (mono_metadata_token_table (token)) {
1291                 case MONO_TABLE_METHOD:
1292                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1293                         /*
1294                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1295                          * method, not the one returned by mono_image_create_token ().
1296                          */
1297                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1298                         break;
1299                 case MONO_TABLE_MEMBERREF:
1300                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1301                         break;
1302                 default:
1303                         g_warning ("got wrong token in custom attr");
1304                         continue;
1305                 }
1306                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1307                 p = blob_size;
1308                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1309                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1310                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1311                 values += MONO_CUSTOM_ATTR_SIZE;
1312                 ++table->next_idx;
1313         }
1314 }
1315
1316 static void
1317 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1318 {
1319         MonoDynamicTable *table;
1320         guint32 *values;
1321         guint32 count, i, idx;
1322         MonoReflectionPermissionSet *perm;
1323
1324         if (!permissions)
1325                 return;
1326
1327         count = mono_array_length (permissions);
1328         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1329         table->rows += count;
1330         alloc_table (table, table->rows);
1331
1332         for (i = 0; i < mono_array_length (permissions); ++i) {
1333                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1334
1335                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1336
1337                 idx = mono_metadata_token_index (parent_token);
1338                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1339                 switch (mono_metadata_token_table (parent_token)) {
1340                 case MONO_TABLE_TYPEDEF:
1341                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1342                         break;
1343                 case MONO_TABLE_METHOD:
1344                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1345                         break;
1346                 case MONO_TABLE_ASSEMBLY:
1347                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1348                         break;
1349                 default:
1350                         g_assert_not_reached ();
1351                 }
1352
1353                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1354                 values [MONO_DECL_SECURITY_PARENT] = idx;
1355                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1356
1357                 ++table->next_idx;
1358         }
1359 }
1360
1361 /*
1362  * Fill in the MethodDef and ParamDef tables for a method.
1363  * This is used for both normal methods and constructors.
1364  */
1365 static void
1366 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1367 {
1368         MonoDynamicTable *table;
1369         guint32 *values;
1370         guint i, count;
1371
1372         /* room in this table is already allocated */
1373         table = &assembly->tables [MONO_TABLE_METHOD];
1374         *mb->table_idx = table->next_idx ++;
1375         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1376         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1377         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1378         values [MONO_METHOD_FLAGS] = mb->attrs;
1379         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1380         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1381         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1382         
1383         table = &assembly->tables [MONO_TABLE_PARAM];
1384         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1385
1386         mono_image_add_decl_security (assembly, 
1387                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1388
1389         if (mb->pinfo) {
1390                 MonoDynamicTable *mtable;
1391                 guint32 *mvalues;
1392                 
1393                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1394                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1395                 
1396                 count = 0;
1397                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1398                         if (mono_array_get (mb->pinfo, gpointer, i))
1399                                 count++;
1400                 }
1401                 table->rows += count;
1402                 alloc_table (table, table->rows);
1403                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1404                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1405                         MonoReflectionParamBuilder *pb;
1406                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1407                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1408                                 values [MONO_PARAM_SEQUENCE] = i;
1409                                 if (pb->name != NULL) {
1410                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1411                                 } else {
1412                                         values [MONO_PARAM_NAME] = 0;
1413                                 }
1414                                 values += MONO_PARAM_SIZE;
1415                                 if (pb->marshal_info) {
1416                                         mtable->rows++;
1417                                         alloc_table (mtable, mtable->rows);
1418                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1419                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1420                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1421                                 }
1422                                 pb->table_idx = table->next_idx++;
1423                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1424                                         guint32 field_type = 0;
1425                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1426                                         mtable->rows ++;
1427                                         alloc_table (mtable, mtable->rows);
1428                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1429                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1430                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1431                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1432                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1433                                 }
1434                         }
1435                 }
1436         }
1437 }
1438
1439 #ifndef DISABLE_REFLECTION_EMIT
1440 static void
1441 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1442 {
1443         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1444
1445         rmb->ilgen = mb->ilgen;
1446         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1447         rmb->parameters = mb->parameters;
1448         rmb->generic_params = mb->generic_params;
1449         rmb->generic_container = mb->generic_container;
1450         rmb->opt_types = NULL;
1451         rmb->pinfo = mb->pinfo;
1452         rmb->attrs = mb->attrs;
1453         rmb->iattrs = mb->iattrs;
1454         rmb->call_conv = mb->call_conv;
1455         rmb->code = mb->code;
1456         rmb->type = mb->type;
1457         rmb->name = mb->name;
1458         rmb->table_idx = &mb->table_idx;
1459         rmb->init_locals = mb->init_locals;
1460         rmb->skip_visibility = FALSE;
1461         rmb->return_modreq = mb->return_modreq;
1462         rmb->return_modopt = mb->return_modopt;
1463         rmb->param_modreq = mb->param_modreq;
1464         rmb->param_modopt = mb->param_modopt;
1465         rmb->permissions = mb->permissions;
1466         rmb->mhandle = mb->mhandle;
1467         rmb->nrefs = 0;
1468         rmb->refs = NULL;
1469
1470         if (mb->dll) {
1471                 rmb->charset = mb->charset;
1472                 rmb->extra_flags = mb->extra_flags;
1473                 rmb->native_cc = mb->native_cc;
1474                 rmb->dllentry = mb->dllentry;
1475                 rmb->dll = mb->dll;
1476         }
1477 }
1478
1479 static void
1480 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1481 {
1482         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1483
1484         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1485
1486         rmb->ilgen = mb->ilgen;
1487         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1488         rmb->parameters = mb->parameters;
1489         rmb->generic_params = NULL;
1490         rmb->generic_container = NULL;
1491         rmb->opt_types = NULL;
1492         rmb->pinfo = mb->pinfo;
1493         rmb->attrs = mb->attrs;
1494         rmb->iattrs = mb->iattrs;
1495         rmb->call_conv = mb->call_conv;
1496         rmb->code = NULL;
1497         rmb->type = mb->type;
1498         rmb->name = mono_string_new (mono_domain_get (), name);
1499         rmb->table_idx = &mb->table_idx;
1500         rmb->init_locals = mb->init_locals;
1501         rmb->skip_visibility = FALSE;
1502         rmb->return_modreq = NULL;
1503         rmb->return_modopt = NULL;
1504         rmb->param_modreq = mb->param_modreq;
1505         rmb->param_modopt = mb->param_modopt;
1506         rmb->permissions = mb->permissions;
1507         rmb->mhandle = mb->mhandle;
1508         rmb->nrefs = 0;
1509         rmb->refs = NULL;
1510 }
1511
1512 static void
1513 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1514 {
1515         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1516
1517         rmb->ilgen = mb->ilgen;
1518         rmb->rtype = mb->rtype;
1519         rmb->parameters = mb->parameters;
1520         rmb->generic_params = NULL;
1521         rmb->generic_container = NULL;
1522         rmb->opt_types = NULL;
1523         rmb->pinfo = NULL;
1524         rmb->attrs = mb->attrs;
1525         rmb->iattrs = 0;
1526         rmb->call_conv = mb->call_conv;
1527         rmb->code = NULL;
1528         rmb->type = (MonoObject *) mb->owner;
1529         rmb->name = mb->name;
1530         rmb->table_idx = NULL;
1531         rmb->init_locals = mb->init_locals;
1532         rmb->skip_visibility = mb->skip_visibility;
1533         rmb->return_modreq = NULL;
1534         rmb->return_modopt = NULL;
1535         rmb->param_modreq = NULL;
1536         rmb->param_modopt = NULL;
1537         rmb->permissions = NULL;
1538         rmb->mhandle = mb->mhandle;
1539         rmb->nrefs = 0;
1540         rmb->refs = NULL;
1541 }       
1542 #endif
1543
1544 static void
1545 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1546 {
1547         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1548         MonoDynamicTable *table;
1549         guint32 *values;
1550         guint32 tok;
1551         MonoReflectionMethod *m;
1552         int i;
1553
1554         if (!mb->override_methods)
1555                 return;
1556
1557         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1558                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1559
1560                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1561                 table->rows ++;
1562                 alloc_table (table, table->rows);
1563                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1564                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1565                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1566
1567                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1568                 switch (mono_metadata_token_table (tok)) {
1569                 case MONO_TABLE_MEMBERREF:
1570                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1571                         break;
1572                 case MONO_TABLE_METHOD:
1573                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1574                         break;
1575                 default:
1576                         g_assert_not_reached ();
1577                 }
1578                 values [MONO_METHODIMPL_DECLARATION] = tok;
1579         }
1580 }
1581
1582 #ifndef DISABLE_REFLECTION_EMIT
1583 static void
1584 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1585 {
1586         MonoDynamicTable *table;
1587         guint32 *values;
1588         ReflectionMethodBuilder rmb;
1589         int i;
1590
1591         reflection_methodbuilder_from_method_builder (&rmb, mb);
1592
1593         mono_image_basic_method (&rmb, assembly);
1594         mb->table_idx = *rmb.table_idx;
1595
1596         if (mb->dll) { /* It's a P/Invoke method */
1597                 guint32 moduleref;
1598                 /* map CharSet values to on-disk values */
1599                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1600                 int extra_flags = mb->extra_flags;
1601                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1602                 table->rows ++;
1603                 alloc_table (table, table->rows);
1604                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1605                 
1606                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1607                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1608                 if (mb->dllentry)
1609                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1610                 else
1611                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1612                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1613                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1614                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1615                         table->rows ++;
1616                         alloc_table (table, table->rows);
1617                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1618                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1619                 }
1620         }
1621
1622         if (mb->generic_params) {
1623                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1624                 table->rows += mono_array_length (mb->generic_params);
1625                 alloc_table (table, table->rows);
1626                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1627                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1628
1629                         mono_image_get_generic_param_info (
1630                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1631                 }
1632         }
1633
1634 }
1635
1636 static void
1637 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1638 {
1639         ReflectionMethodBuilder rmb;
1640
1641         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1642
1643         mono_image_basic_method (&rmb, assembly);
1644         mb->table_idx = *rmb.table_idx;
1645 }
1646 #endif
1647
1648 static char*
1649 type_get_fully_qualified_name (MonoType *type)
1650 {
1651         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1652 }
1653
1654 static char*
1655 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1656         MonoClass *klass;
1657         MonoAssembly *ta;
1658
1659         klass = mono_class_from_mono_type (type);
1660         if (!klass) 
1661                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1662         ta = klass->image->assembly;
1663         if (ta->dynamic || (ta == ass)) {
1664                 if (klass->generic_class || klass->generic_container)
1665                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1666                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1667                 else
1668                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1669         }
1670
1671         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1672 }
1673
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 /*field_image is the image to which the eventual custom mods have been encoded against*/
1676 static guint32
1677 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1678 {
1679         SigBuffer buf;
1680         guint32 idx, i, token;
1681
1682         if (!assembly->save)
1683                 return 0;
1684
1685         sigbuffer_init (&buf, 32);
1686         
1687         sigbuffer_add_value (&buf, 0x06);
1688         /* encode custom attributes before the type */
1689         if (type->num_mods) {
1690                 for (i = 0; i < type->num_mods; ++i) {
1691                         if (field_image) {
1692                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1693                                 g_assert (class);
1694                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1695                         } else {
1696                                 token = type->modifiers [i].token;
1697                         }
1698
1699                         if (type->modifiers [i].required)
1700                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1701                         else
1702                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1703
1704                         sigbuffer_add_value (&buf, token);
1705                 }
1706         }
1707         encode_type (assembly, type, &buf);
1708         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1709         sigbuffer_free (&buf);
1710         return idx;
1711 }
1712 #endif
1713
1714 static guint32
1715 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1716 {
1717         SigBuffer buf;
1718         guint32 idx;
1719         guint32 typespec = 0;
1720         MonoType *type;
1721         MonoClass *class;
1722
1723         init_type_builder_generics (fb->type);
1724
1725         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1726         class = mono_class_from_mono_type (type);
1727
1728         sigbuffer_init (&buf, 32);
1729         
1730         sigbuffer_add_value (&buf, 0x06);
1731         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1732         /* encode custom attributes before the type */
1733
1734         if (class->generic_container)
1735                 typespec = create_typespec (assembly, type);
1736
1737         if (typespec) {
1738                 MonoGenericClass *gclass;
1739                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1740                 encode_generic_class (assembly, gclass, &buf);
1741         } else {
1742                 encode_type (assembly, type, &buf);
1743         }
1744         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1745         sigbuffer_free (&buf);
1746         return idx;
1747 }
1748
1749 static guint32
1750 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1751         char blob_size [64];
1752         char *b = blob_size;
1753         char *p, *box_val;
1754         char* buf;
1755         guint32 idx = 0, len = 0, dummy = 0;
1756 #ifdef ARM_FPU_FPA
1757 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1758         guint32 fpa_double [2];
1759         guint32 *fpa_p;
1760 #endif
1761 #endif
1762         
1763         p = buf = g_malloc (64);
1764         if (!val) {
1765                 *ret_type = MONO_TYPE_CLASS;
1766                 len = 4;
1767                 box_val = (char*)&dummy;
1768         } else {
1769                 box_val = ((char*)val) + sizeof (MonoObject);
1770                 *ret_type = val->vtable->klass->byval_arg.type;
1771         }
1772 handle_enum:
1773         switch (*ret_type) {
1774         case MONO_TYPE_BOOLEAN:
1775         case MONO_TYPE_U1:
1776         case MONO_TYPE_I1:
1777                 len = 1;
1778                 break;
1779         case MONO_TYPE_CHAR:
1780         case MONO_TYPE_U2:
1781         case MONO_TYPE_I2:
1782                 len = 2;
1783                 break;
1784         case MONO_TYPE_U4:
1785         case MONO_TYPE_I4:
1786         case MONO_TYPE_R4:
1787                 len = 4;
1788                 break;
1789         case MONO_TYPE_U8:
1790         case MONO_TYPE_I8:
1791                 len = 8;
1792                 break;
1793         case MONO_TYPE_R8:
1794                 len = 8;
1795 #ifdef ARM_FPU_FPA
1796 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1797                 fpa_p = (guint32*)box_val;
1798                 fpa_double [0] = fpa_p [1];
1799                 fpa_double [1] = fpa_p [0];
1800                 box_val = (char*)fpa_double;
1801 #endif
1802 #endif
1803                 break;
1804         case MONO_TYPE_VALUETYPE: {
1805                 MonoClass *klass = val->vtable->klass;
1806                 
1807                 if (klass->enumtype) {
1808                         *ret_type = mono_class_enum_basetype (klass)->type;
1809                         goto handle_enum;
1810                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1811                         len = 8;
1812                 } else 
1813                         g_error ("we can't encode valuetypes, we should have never reached this line");
1814                 break;
1815         }
1816         case MONO_TYPE_CLASS:
1817                 break;
1818         case MONO_TYPE_STRING: {
1819                 MonoString *str = (MonoString*)val;
1820                 /* there is no signature */
1821                 len = str->length * 2;
1822                 mono_metadata_encode_value (len, b, &b);
1823 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1824                 {
1825                         char *swapped = g_malloc (2 * mono_string_length (str));
1826                         const char *p = (const char*)mono_string_chars (str);
1827
1828                         swap_with_size (swapped, p, 2, mono_string_length (str));
1829                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1830                         g_free (swapped);
1831                 }
1832 #else
1833                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1834 #endif
1835
1836                 g_free (buf);
1837                 return idx;
1838         }
1839         case MONO_TYPE_GENERICINST:
1840                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1841                 goto handle_enum;
1842         default:
1843                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1844         }
1845
1846         /* there is no signature */
1847         mono_metadata_encode_value (len, b, &b);
1848 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1849         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1850         swap_with_size (blob_size, box_val, len, 1);
1851         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1852 #else
1853         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1854 #endif
1855
1856         g_free (buf);
1857         return idx;
1858 }
1859
1860 static guint32
1861 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1862         char *str;
1863         SigBuffer buf;
1864         guint32 idx, len;
1865
1866         sigbuffer_init (&buf, 32);
1867
1868         sigbuffer_add_value (&buf, minfo->type);
1869
1870         switch (minfo->type) {
1871         case MONO_NATIVE_BYVALTSTR:
1872         case MONO_NATIVE_BYVALARRAY:
1873                 sigbuffer_add_value (&buf, minfo->count);
1874                 break;
1875         case MONO_NATIVE_LPARRAY:
1876                 if (minfo->eltype || minfo->has_size) {
1877                         sigbuffer_add_value (&buf, minfo->eltype);
1878                         if (minfo->has_size) {
1879                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1880                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1881
1882                                 /* LAMESPEC: ElemMult is undocumented */
1883                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1884                         }
1885                 }
1886                 break;
1887         case MONO_NATIVE_SAFEARRAY:
1888                 if (minfo->eltype)
1889                         sigbuffer_add_value (&buf, minfo->eltype);
1890                 break;
1891         case MONO_NATIVE_CUSTOM:
1892                 if (minfo->guid) {
1893                         str = mono_string_to_utf8 (minfo->guid);
1894                         len = strlen (str);
1895                         sigbuffer_add_value (&buf, len);
1896                         sigbuffer_add_mem (&buf, str, len);
1897                         g_free (str);
1898                 } else {
1899                         sigbuffer_add_value (&buf, 0);
1900                 }
1901                 /* native type name */
1902                 sigbuffer_add_value (&buf, 0);
1903                 /* custom marshaler type name */
1904                 if (minfo->marshaltype || minfo->marshaltyperef) {
1905                         if (minfo->marshaltyperef)
1906                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1907                         else
1908                                 str = mono_string_to_utf8 (minfo->marshaltype);
1909                         len = strlen (str);
1910                         sigbuffer_add_value (&buf, len);
1911                         sigbuffer_add_mem (&buf, str, len);
1912                         g_free (str);
1913                 } else {
1914                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1915                         sigbuffer_add_value (&buf, 0);
1916                 }
1917                 if (minfo->mcookie) {
1918                         str = mono_string_to_utf8 (minfo->mcookie);
1919                         len = strlen (str);
1920                         sigbuffer_add_value (&buf, len);
1921                         sigbuffer_add_mem (&buf, str, len);
1922                         g_free (str);
1923                 } else {
1924                         sigbuffer_add_value (&buf, 0);
1925                 }
1926                 break;
1927         default:
1928                 break;
1929         }
1930         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1931         sigbuffer_free (&buf);
1932         return idx;
1933 }
1934
1935 static void
1936 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1937 {
1938         MonoDynamicTable *table;
1939         guint32 *values;
1940
1941         /* maybe this fixup should be done in the C# code */
1942         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1943                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1944         table = &assembly->tables [MONO_TABLE_FIELD];
1945         fb->table_idx = table->next_idx ++;
1946         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1947         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1948         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1949         values [MONO_FIELD_FLAGS] = fb->attrs;
1950         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1951
1952         if (fb->offset != -1) {
1953                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1954                 table->rows ++;
1955                 alloc_table (table, table->rows);
1956                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1957                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1958                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1959         }
1960         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1961                 guint32 field_type = 0;
1962                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1963                 table->rows ++;
1964                 alloc_table (table, table->rows);
1965                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1966                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1967                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1968                 values [MONO_CONSTANT_TYPE] = field_type;
1969                 values [MONO_CONSTANT_PADDING] = 0;
1970         }
1971         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1972                 guint32 rva_idx;
1973                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1974                 table->rows ++;
1975                 alloc_table (table, table->rows);
1976                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1977                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1978                 /*
1979                  * We store it in the code section because it's simpler for now.
1980                  */
1981                 if (fb->rva_data) {
1982                         if (mono_array_length (fb->rva_data) >= 10)
1983                                 stream_data_align (&assembly->code);
1984                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1985                 } else
1986                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1987                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1988         }
1989         if (fb->marshal_info) {
1990                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1991                 table->rows ++;
1992                 alloc_table (table, table->rows);
1993                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1994                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1995                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1996         }
1997 }
1998
1999 static guint32
2000 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2001 {
2002         SigBuffer buf;
2003         guint32 nparams = 0;
2004         MonoReflectionMethodBuilder *mb = fb->get_method;
2005         MonoReflectionMethodBuilder *smb = fb->set_method;
2006         guint32 idx, i;
2007
2008         if (mb && mb->parameters)
2009                 nparams = mono_array_length (mb->parameters);
2010         if (!mb && smb && smb->parameters)
2011                 nparams = mono_array_length (smb->parameters) - 1;
2012         sigbuffer_init (&buf, 32);
2013         if (fb->call_conv & 0x20)
2014                 sigbuffer_add_byte (&buf, 0x28);
2015         else
2016                 sigbuffer_add_byte (&buf, 0x08);
2017         sigbuffer_add_value (&buf, nparams);
2018         if (mb) {
2019                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2020                 for (i = 0; i < nparams; ++i) {
2021                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2022                         encode_reflection_type (assembly, pt, &buf);
2023                 }
2024         } else if (smb && smb->parameters) {
2025                 /* the property type is the last param */
2026                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2027                 for (i = 0; i < nparams; ++i) {
2028                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2029                         encode_reflection_type (assembly, pt, &buf);
2030                 }
2031         } else {
2032                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2033         }
2034
2035         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2036         sigbuffer_free (&buf);
2037         return idx;
2038 }
2039
2040 static void
2041 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2042 {
2043         MonoDynamicTable *table;
2044         guint32 *values;
2045         guint num_methods = 0;
2046         guint32 semaidx;
2047
2048         /* 
2049          * we need to set things in the following tables:
2050          * PROPERTYMAP (info already filled in _get_type_info ())
2051          * PROPERTY    (rows already preallocated in _get_type_info ())
2052          * METHOD      (method info already done with the generic method code)
2053          * METHODSEMANTICS
2054          * CONSTANT
2055          */
2056         table = &assembly->tables [MONO_TABLE_PROPERTY];
2057         pb->table_idx = table->next_idx ++;
2058         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2059         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2060         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2061         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2062
2063         /* FIXME: we still don't handle 'other' methods */
2064         if (pb->get_method) num_methods ++;
2065         if (pb->set_method) num_methods ++;
2066
2067         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2068         table->rows += num_methods;
2069         alloc_table (table, table->rows);
2070
2071         if (pb->get_method) {
2072                 semaidx = table->next_idx ++;
2073                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2074                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2075                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2076                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2077         }
2078         if (pb->set_method) {
2079                 semaidx = table->next_idx ++;
2080                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2081                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2082                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2083                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2084         }
2085         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2086                 guint32 field_type = 0;
2087                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2088                 table->rows ++;
2089                 alloc_table (table, table->rows);
2090                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2091                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2092                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2093                 values [MONO_CONSTANT_TYPE] = field_type;
2094                 values [MONO_CONSTANT_PADDING] = 0;
2095         }
2096 }
2097
2098 static void
2099 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2100 {
2101         MonoDynamicTable *table;
2102         guint32 *values;
2103         guint num_methods = 0;
2104         guint32 semaidx;
2105
2106         /* 
2107          * we need to set things in the following tables:
2108          * EVENTMAP (info already filled in _get_type_info ())
2109          * EVENT    (rows already preallocated in _get_type_info ())
2110          * METHOD      (method info already done with the generic method code)
2111          * METHODSEMANTICS
2112          */
2113         table = &assembly->tables [MONO_TABLE_EVENT];
2114         eb->table_idx = table->next_idx ++;
2115         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2116         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2117         values [MONO_EVENT_FLAGS] = eb->attrs;
2118         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2119
2120         /*
2121          * FIXME: we still don't handle 'other' methods 
2122          */
2123         if (eb->add_method) num_methods ++;
2124         if (eb->remove_method) num_methods ++;
2125         if (eb->raise_method) num_methods ++;
2126
2127         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2128         table->rows += num_methods;
2129         alloc_table (table, table->rows);
2130
2131         if (eb->add_method) {
2132                 semaidx = table->next_idx ++;
2133                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2134                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2135                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2136                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2137         }
2138         if (eb->remove_method) {
2139                 semaidx = table->next_idx ++;
2140                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2141                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2142                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2143                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2144         }
2145         if (eb->raise_method) {
2146                 semaidx = table->next_idx ++;
2147                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2148                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2149                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2150                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2151         }
2152 }
2153
2154 static void
2155 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2156 {
2157         MonoDynamicTable *table;
2158         guint32 num_constraints, i;
2159         guint32 *values;
2160         guint32 table_idx;
2161
2162         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2163         num_constraints = gparam->iface_constraints ?
2164                 mono_array_length (gparam->iface_constraints) : 0;
2165         table->rows += num_constraints;
2166         if (gparam->base_type)
2167                 table->rows++;
2168         alloc_table (table, table->rows);
2169
2170         if (gparam->base_type) {
2171                 table_idx = table->next_idx ++;
2172                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2173
2174                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2177         }
2178
2179         for (i = 0; i < num_constraints; i++) {
2180                 MonoReflectionType *constraint = mono_array_get (
2181                         gparam->iface_constraints, gpointer, i);
2182
2183                 table_idx = table->next_idx ++;
2184                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2185
2186                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2187                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2188                         assembly, mono_reflection_type_get_handle (constraint));
2189         }
2190 }
2191
2192 static void
2193 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2194 {
2195         GenericParamTableEntry *entry;
2196
2197         /*
2198          * The GenericParam table must be sorted according to the `owner' field.
2199          * We need to do this sorting prior to writing the GenericParamConstraint
2200          * table, since we have to use the final GenericParam table indices there
2201          * and they must also be sorted.
2202          */
2203
2204         entry = g_new0 (GenericParamTableEntry, 1);
2205         entry->owner = owner;
2206         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2207         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2208         entry->gparam = gparam;
2209         
2210         g_ptr_array_add (assembly->gen_params, entry);
2211 }
2212
2213 static void
2214 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2215 {
2216         MonoDynamicTable *table;
2217         MonoGenericParam *param;
2218         guint32 *values;
2219         guint32 table_idx;
2220
2221         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2222         table_idx = table->next_idx ++;
2223         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2224
2225         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2226
2227         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2228         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2229         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2230         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2231
2232         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2233
2234         encode_constraints (entry->gparam, table_idx, assembly);
2235 }
2236
2237 static guint32
2238 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2239 {
2240         MonoDynamicTable *table;
2241         guint32 token;
2242         guint32 *values;
2243         guint32 cols [MONO_ASSEMBLY_SIZE];
2244         const char *pubkey;
2245         guint32 publen;
2246
2247         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2248                 return token;
2249
2250         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2251                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2252                 token = table->next_idx ++;
2253                 table->rows ++;
2254                 alloc_table (table, table->rows);
2255                 values = table->values + token * MONO_MODULEREF_SIZE;
2256                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2257
2258                 token <<= MONO_RESOLTION_SCOPE_BITS;
2259                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2260                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2261
2262                 return token;
2263         }
2264         
2265         if (image->assembly->dynamic)
2266                 /* FIXME: */
2267                 memset (cols, 0, sizeof (cols));
2268         else {
2269                 /* image->assembly->image is the manifest module */
2270                 image = image->assembly->image;
2271                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2272         }
2273
2274         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2275         token = table->next_idx ++;
2276         table->rows ++;
2277         alloc_table (table, table->rows);
2278         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2279         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2280         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2281         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2282         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2283         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2284         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2285         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2286         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2287
2288         if (strcmp ("", image->assembly->aname.culture)) {
2289                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2290                                 image->assembly->aname.culture);
2291         }
2292
2293         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2294                 guchar pubtoken [9];
2295                 pubtoken [0] = 8;
2296                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2297                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2298         } else {
2299                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2300         }
2301         token <<= MONO_RESOLTION_SCOPE_BITS;
2302         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2303         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2304         return token;
2305 }
2306
2307 static guint32
2308 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2309 {
2310         MonoDynamicTable *table;
2311         guint32 *values;
2312         guint32 token;
2313         SigBuffer buf;
2314
2315         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2316                 return token;
2317
2318         sigbuffer_init (&buf, 32);
2319         switch (type->type) {
2320         case MONO_TYPE_FNPTR:
2321         case MONO_TYPE_PTR:
2322         case MONO_TYPE_SZARRAY:
2323         case MONO_TYPE_ARRAY:
2324         case MONO_TYPE_VAR:
2325         case MONO_TYPE_MVAR:
2326         case MONO_TYPE_GENERICINST:
2327                 encode_type (assembly, type, &buf);
2328                 break;
2329         case MONO_TYPE_CLASS:
2330         case MONO_TYPE_VALUETYPE: {
2331                 MonoClass *k = mono_class_from_mono_type (type);
2332                 if (!k || !k->generic_container) {
2333                         sigbuffer_free (&buf);
2334                         return 0;
2335                 }
2336                 encode_type (assembly, type, &buf);
2337                 break;
2338         }
2339         default:
2340                 sigbuffer_free (&buf);
2341                 return 0;
2342         }
2343
2344         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2345         if (assembly->save) {
2346                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2347                 alloc_table (table, table->rows + 1);
2348                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2349                 values [MONO_TYPESPEC_SIGNATURE] = token;
2350         }
2351         sigbuffer_free (&buf);
2352
2353         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2354         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2355         table->next_idx ++;
2356         return token;
2357 }
2358
2359 static guint32
2360 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2361 {
2362         MonoDynamicTable *table;
2363         guint32 *values;
2364         guint32 token, scope, enclosing;
2365         MonoClass *klass;
2366
2367         /* if the type requires a typespec, we must try that first*/
2368         if (try_typespec && (token = create_typespec (assembly, type)))
2369                 return token;
2370         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2371         if (token)
2372                 return token;
2373         klass = mono_class_from_mono_type (type);
2374         if (!klass)
2375                 klass = mono_class_from_mono_type (type);
2376
2377         /*
2378          * If it's in the same module and not a generic type parameter:
2379          */
2380         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2381                         (type->type != MONO_TYPE_MVAR)) {
2382                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2383                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2384                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2385                 return token;
2386         }
2387
2388         if (klass->nested_in) {
2389                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2390                 /* get the typeref idx of the enclosing type */
2391                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2392                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2393         } else {
2394                 scope = resolution_scope_from_image (assembly, klass->image);
2395         }
2396         table = &assembly->tables [MONO_TABLE_TYPEREF];
2397         if (assembly->save) {
2398                 alloc_table (table, table->rows + 1);
2399                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2400                 values [MONO_TYPEREF_SCOPE] = scope;
2401                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2402                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2403         }
2404         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2405         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2406         table->next_idx ++;
2407         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2408         return token;
2409 }
2410
2411 /*
2412  * Despite the name, we handle also TypeSpec (with the above helper).
2413  */
2414 static guint32
2415 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2416 {
2417         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2418 }
2419
2420 #ifndef DISABLE_REFLECTION_EMIT
2421 static guint32
2422 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2423 {
2424         MonoDynamicTable *table;
2425         guint32 *values;
2426         guint32 token, pclass;
2427
2428         switch (parent & MONO_TYPEDEFORREF_MASK) {
2429         case MONO_TYPEDEFORREF_TYPEREF:
2430                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2431                 break;
2432         case MONO_TYPEDEFORREF_TYPESPEC:
2433                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2434                 break;
2435         case MONO_TYPEDEFORREF_TYPEDEF:
2436                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2437                 break;
2438         default:
2439                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2440                 return 0;
2441         }
2442         /* extract the index */
2443         parent >>= MONO_TYPEDEFORREF_BITS;
2444
2445         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2446
2447         if (assembly->save) {
2448                 alloc_table (table, table->rows + 1);
2449                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2450                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2451                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2452                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2453         }
2454
2455         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2456         table->next_idx ++;
2457
2458         return token;
2459 }
2460
2461 /*
2462  * Insert a memberef row into the metadata: the token that point to the memberref
2463  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2464  * mono_image_get_fieldref_token()).
2465  * The sig param is an index to an already built signature.
2466  */
2467 static guint32
2468 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2469 {
2470         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2471         return mono_image_add_memberef_row (assembly, parent, name, sig);
2472 }
2473
2474
2475 static guint32
2476 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2477 {
2478         guint32 token;
2479         MonoMethodSignature *sig;
2480         
2481         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2482
2483         if (create_typespec) {
2484                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2485                 if (token)
2486                         return token;
2487         } 
2488
2489         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2490         if (token && !create_typespec)
2491                 return token;
2492
2493         g_assert (!method->is_inflated);
2494         if (!token) {
2495                 /*
2496                  * A methodref signature can't contain an unmanaged calling convention.
2497                  */
2498                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2499                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2500                         sig->call_convention = MONO_CALL_DEFAULT;
2501                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2502                         method->name,  method_encode_signature (assembly, sig));
2503                 g_free (sig);
2504                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2505         }
2506
2507         if (create_typespec) {
2508                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2509                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2510                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2511
2512                 if (assembly->save) {
2513                         guint32 *values;
2514
2515                         alloc_table (table, table->rows + 1);
2516                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2517                         values [MONO_METHODSPEC_METHOD] = token;
2518                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2519                 }
2520
2521                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2522                 table->next_idx ++;
2523                 /*methodspec and memberef tokens are diferent, */
2524                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2525                 return token;
2526         }
2527         return token;
2528 }
2529
2530 static guint32
2531 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2532 {
2533         guint32 token, parent, sig;
2534         ReflectionMethodBuilder rmb;
2535         char *name;
2536         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2537         
2538         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2539         if (token)
2540                 return token;
2541
2542         name = mono_string_to_utf8 (method->name);
2543         reflection_methodbuilder_from_method_builder (&rmb, method);
2544
2545         /*
2546          * A methodref signature can't contain an unmanaged calling convention.
2547          * Since some flags are encoded as part of call_conv, we need to check against it.
2548         */
2549         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2550                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2551
2552         sig = method_builder_encode_signature (assembly, &rmb);
2553
2554         if (tb->generic_params)
2555                 parent = create_generic_typespec (assembly, tb);
2556         else
2557                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2558
2559         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2560
2561         g_free (name);
2562         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2563         return token;
2564 }
2565
2566 static guint32
2567 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2568                                      const gchar *name, guint32 sig)
2569 {
2570         MonoDynamicTable *table;
2571         guint32 token;
2572         guint32 *values;
2573         
2574         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2575
2576         if (assembly->save) {
2577                 alloc_table (table, table->rows + 1);
2578                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2579                 values [MONO_MEMBERREF_CLASS] = original;
2580                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2581                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2582         }
2583
2584         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2585         table->next_idx ++;
2586
2587         return token;
2588 }
2589
2590 static guint32
2591 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2592 {
2593         SigBuffer buf;
2594         int i;
2595         guint32 nparams = mono_array_length (mb->generic_params);
2596         guint32 idx;
2597
2598         if (!assembly->save)
2599                 return 0;
2600
2601         sigbuffer_init (&buf, 32);
2602
2603         sigbuffer_add_value (&buf, 0xa);
2604         sigbuffer_add_value (&buf, nparams);
2605
2606         for (i = 0; i < nparams; i++) {
2607                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2608                 sigbuffer_add_value (&buf, i);
2609         }
2610
2611         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2612         sigbuffer_free (&buf);
2613         return idx;
2614 }
2615
2616 static guint32
2617 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2618 {
2619         MonoDynamicTable *table;
2620         guint32 *values;
2621         guint32 token, mtoken = 0;
2622
2623         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2624         if (token)
2625                 return token;
2626
2627         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2628
2629         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2630         switch (mono_metadata_token_table (mtoken)) {
2631         case MONO_TABLE_MEMBERREF:
2632                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2633                 break;
2634         case MONO_TABLE_METHOD:
2635                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2636                 break;
2637         default:
2638                 g_assert_not_reached ();
2639         }
2640
2641         if (assembly->save) {
2642                 alloc_table (table, table->rows + 1);
2643                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2644                 values [MONO_METHODSPEC_METHOD] = mtoken;
2645                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2646         }
2647
2648         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2649         table->next_idx ++;
2650
2651         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2652         return token;
2653 }
2654
2655 static guint32
2656 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2657 {
2658         guint32 token;
2659
2660         if (mb->generic_params && create_methodspec) 
2661                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2662
2663         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2664         if (token)
2665                 return token;
2666
2667         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2668         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2669         return token;
2670 }
2671
2672 static guint32
2673 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2674 {
2675         guint32 token, parent, sig;
2676         ReflectionMethodBuilder rmb;
2677         char *name;
2678         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2679         
2680         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2681         if (token)
2682                 return token;
2683
2684         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2685
2686         if (tb->generic_params)
2687                 parent = create_generic_typespec (assembly, tb);
2688         else
2689                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2690         
2691         name = mono_string_to_utf8 (rmb.name);
2692         sig = method_builder_encode_signature (assembly, &rmb);
2693
2694         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2695
2696         g_free (name);
2697         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2698         return token;
2699 }
2700 #endif
2701
2702 static gboolean
2703 is_field_on_inst (MonoClassField *field)
2704 {
2705         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2706 }
2707
2708 /*
2709  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2710  */
2711 static MonoType*
2712 get_field_on_inst_generic_type (MonoClassField *field)
2713 {
2714         MonoClass *class, *gtd;
2715         MonoDynamicGenericClass *dgclass;
2716         int field_index;
2717
2718         g_assert (is_field_on_inst (field));
2719
2720         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2721
2722         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2723                 field_index = field - dgclass->fields;
2724                 return dgclass->field_generic_types [field_index];              
2725         }
2726
2727         class = field->parent;
2728         gtd = class->generic_class->container_class;
2729
2730         if (field >= class->fields && field - class->fields < class->field.count) {
2731                 field_index = field - class->fields;
2732                 return gtd->fields [field_index].type;
2733         }
2734
2735         g_assert_not_reached ();
2736         return 0;
2737 }
2738
2739 #ifndef DISABLE_REFLECTION_EMIT
2740 static guint32
2741 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2742 {
2743         MonoType *type;
2744         guint32 token;
2745
2746         g_assert (field);
2747         g_assert (field->parent);
2748
2749         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2750         if (token)
2751                 return token;
2752
2753         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2754                 int index = field - field->parent->fields;
2755                 type = field->parent->generic_class->container_class->fields [index].type;
2756         } else {
2757                 if (is_field_on_inst (field))
2758                         type = get_field_on_inst_generic_type (field);
2759                 else
2760                         type = mono_field_get_type (field);
2761         }
2762         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2763                                                                                         mono_field_get_name (field),
2764                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2765         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2766         return token;
2767 }
2768
2769 static guint32
2770 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2771 {
2772         guint32 token;
2773         MonoClass *klass;
2774         MonoGenericClass *gclass;
2775         MonoDynamicGenericClass *dgclass;
2776         MonoType *type;
2777         char *name;
2778
2779         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2780         if (token)
2781                 return token;
2782         if (is_sre_field_builder (mono_object_class (f->fb))) {
2783                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2784                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785                 klass = mono_class_from_mono_type (type);
2786                 gclass = type->data.generic_class;
2787                 g_assert (gclass->is_dynamic);
2788                 dgclass = (MonoDynamicGenericClass *) gclass;
2789
2790                 name = mono_string_to_utf8 (fb->name);
2791                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2792                                                                                                 field_encode_signature (assembly, fb));
2793                 g_free (name);          
2794         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2795                 guint32 sig;
2796                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2797
2798                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2799                 klass = mono_class_from_mono_type (type);
2800
2801                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2802                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2803         } else {
2804                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2805                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2806         }
2807
2808         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2809         return token;
2810 }
2811
2812 static guint32
2813 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2814 {
2815         guint32 sig, token;
2816         MonoClass *klass;
2817         MonoGenericClass *gclass;
2818         MonoType *type;
2819
2820         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2821
2822         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2823         if (token)
2824                 return token;
2825
2826         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2827                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2828                 MonoDynamicGenericClass *dgclass;
2829                 ReflectionMethodBuilder rmb;
2830                 char *name;
2831
2832                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2833                 klass = mono_class_from_mono_type (type);
2834
2835                 gclass = type->data.generic_class;
2836                 g_assert (gclass->is_dynamic);
2837                 dgclass = (MonoDynamicGenericClass *) gclass;
2838
2839                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2840
2841                 name = mono_string_to_utf8 (rmb.name);
2842
2843                 sig = method_builder_encode_signature (assembly, &rmb);
2844
2845                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2846                 g_free (name);
2847         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2848                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2849
2850                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2851                 klass = mono_class_from_mono_type (type);
2852
2853                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2854                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2855         } else {
2856                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2857                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2858         }
2859
2860
2861         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2862         return token;
2863 }
2864
2865 static MonoMethod*
2866 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2867 {
2868         MonoClass *klass;
2869         MonoGenericContext tmp_context;
2870         MonoType **type_argv;
2871         MonoGenericInst *ginst;
2872         MonoMethod *method, *inflated;
2873         int count, i;
2874
2875         init_type_builder_generics ((MonoObject*)m->inst);
2876
2877         method = inflate_method (m->inst, (MonoObject*)m->mb);
2878
2879         klass = method->klass;
2880
2881         if (m->method_args == NULL)
2882                 return method;
2883
2884         if (method->is_inflated)
2885                 method = ((MonoMethodInflated *) method)->declaring;
2886
2887         count = mono_array_length (m->method_args);
2888
2889         type_argv = g_new0 (MonoType *, count);
2890         for (i = 0; i < count; i++) {
2891                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2892                 type_argv [i] = mono_reflection_type_get_handle (garg);
2893         }
2894         ginst = mono_metadata_get_generic_inst (count, type_argv);
2895         g_free (type_argv);
2896
2897         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2898         tmp_context.method_inst = ginst;
2899
2900         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2901         return inflated;
2902 }
2903
2904 static guint32
2905 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2906 {
2907         guint32 sig, token = 0;
2908         MonoType *type;
2909         MonoClass *klass;
2910
2911         if (m->method_args) {
2912                 MonoMethod *inflated;
2913
2914                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2915                 if (create_methodspec)
2916                         token = mono_image_get_methodspec_token (assembly, inflated);
2917                 else
2918                         token = mono_image_get_inflated_method_token (assembly, inflated);
2919                 return token;
2920         }
2921
2922         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2923         if (token)
2924                 return token;
2925
2926         if (is_sre_method_builder (mono_object_class (m->mb))) {
2927                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2928                 MonoGenericClass *gclass;
2929                 ReflectionMethodBuilder rmb;
2930                 char *name;
2931
2932                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2933                 klass = mono_class_from_mono_type (type);
2934                 gclass = type->data.generic_class;
2935                 g_assert (gclass->is_dynamic);
2936
2937                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2938
2939                 name = mono_string_to_utf8 (rmb.name);
2940
2941                 sig = method_builder_encode_signature (assembly, &rmb);
2942
2943                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2944                 g_free (name);          
2945         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2946                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2947
2948                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2949                 klass = mono_class_from_mono_type (type);
2950
2951                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2952                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2953         } else {
2954                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2955                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2956         }
2957
2958         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2959         return token;
2960 }
2961
2962 static guint32
2963 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2964 {
2965         SigBuffer buf;
2966         int i;
2967         guint32 nparams = context->method_inst->type_argc;
2968         guint32 idx;
2969
2970         if (!assembly->save)
2971                 return 0;
2972
2973         sigbuffer_init (&buf, 32);
2974         /*
2975          * FIXME: vararg, explicit_this, differenc call_conv values...
2976          */
2977         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2978         sigbuffer_add_value (&buf, nparams);
2979
2980         for (i = 0; i < nparams; i++)
2981                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2982
2983         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2984         sigbuffer_free (&buf);
2985         return idx;
2986 }
2987
2988 static guint32
2989 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2990 {
2991         MonoDynamicTable *table;
2992         guint32 *values;
2993         guint32 token, mtoken = 0, sig;
2994         MonoMethodInflated *imethod;
2995         MonoMethod *declaring;
2996
2997         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2998
2999         g_assert (method->is_inflated);
3000         imethod = (MonoMethodInflated *) method;
3001         declaring = imethod->declaring;
3002
3003         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3004         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3005
3006         if (!mono_method_signature (declaring)->generic_param_count)
3007                 return mtoken;
3008
3009         switch (mono_metadata_token_table (mtoken)) {
3010         case MONO_TABLE_MEMBERREF:
3011                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3012                 break;
3013         case MONO_TABLE_METHOD:
3014                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3015                 break;
3016         default:
3017                 g_assert_not_reached ();
3018         }
3019
3020         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3021
3022         if (assembly->save) {
3023                 alloc_table (table, table->rows + 1);
3024                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3025                 values [MONO_METHODSPEC_METHOD] = mtoken;
3026                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3027         }
3028
3029         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3030         table->next_idx ++;
3031
3032         return token;
3033 }
3034
3035 static guint32
3036 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3037 {
3038         MonoMethodInflated *imethod;
3039         guint32 token;
3040         
3041         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3042         if (token)
3043                 return token;
3044
3045         g_assert (method->is_inflated);
3046         imethod = (MonoMethodInflated *) method;
3047
3048         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3049                 token = method_encode_methodspec (assembly, method);
3050         } else {
3051                 guint32 sig = method_encode_signature (
3052                         assembly, mono_method_signature (imethod->declaring));
3053                 token = mono_image_get_memberref_token (
3054                         assembly, &method->klass->byval_arg, method->name, sig);
3055         }
3056
3057         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3058         return token;
3059 }
3060
3061 static guint32
3062 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3063 {
3064         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3065         guint32 sig, token;
3066
3067         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3068         token = mono_image_get_memberref_token (
3069                 assembly, &m->klass->byval_arg, m->name, sig);
3070
3071         return token;
3072 }
3073
3074 static guint32
3075 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3076 {
3077         MonoDynamicTable *table;
3078         MonoClass *klass;
3079         MonoType *type;
3080         guint32 *values;
3081         guint32 token;
3082         SigBuffer buf;
3083         int count, i;
3084
3085         /*
3086          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3087          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3088          * Because of this, we must not insert it into the `typeref' hash table.
3089          */
3090         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3091         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3092         if (token)
3093                 return token;
3094
3095         sigbuffer_init (&buf, 32);
3096
3097         g_assert (tb->generic_params);
3098         klass = mono_class_from_mono_type (type);
3099
3100         if (tb->generic_container)
3101                 mono_reflection_create_generic_class (tb);
3102
3103         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3104         g_assert (klass->generic_container);
3105         sigbuffer_add_value (&buf, klass->byval_arg.type);
3106         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3107
3108         count = mono_array_length (tb->generic_params);
3109         sigbuffer_add_value (&buf, count);
3110         for (i = 0; i < count; i++) {
3111                 MonoReflectionGenericParam *gparam;
3112
3113                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3114
3115                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3116         }
3117
3118         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3119
3120         if (assembly->save) {
3121                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3122                 alloc_table (table, table->rows + 1);
3123                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3124                 values [MONO_TYPESPEC_SIGNATURE] = token;
3125         }
3126         sigbuffer_free (&buf);
3127
3128         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3129         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3130         table->next_idx ++;
3131         return token;
3132 }
3133
3134 /*
3135  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3136  */
3137 static MonoType*
3138 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3139 {
3140         int i, count, len, pos;
3141         MonoType *t;
3142
3143         count = 0;
3144         if (modreq)
3145                 count += mono_array_length (modreq);
3146         if (modopt)
3147                 count += mono_array_length (modopt);
3148
3149         if (count == 0)
3150                 return mono_metadata_type_dup (NULL, type);
3151
3152         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3153         t = g_malloc (len);
3154         memcpy (t, type, MONO_SIZEOF_TYPE);
3155
3156         t->num_mods = count;
3157         pos = 0;
3158         if (modreq) {
3159                 for (i = 0; i < mono_array_length (modreq); ++i) {
3160                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3161                         t->modifiers [pos].required = 1;
3162                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3163                         pos ++;
3164                 }
3165         }
3166         if (modopt) {
3167                 for (i = 0; i < mono_array_length (modopt); ++i) {
3168                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3169                         t->modifiers [pos].required = 0;
3170                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3171                         pos ++;
3172                 }
3173         }
3174
3175         return t;
3176 }
3177
3178 static void
3179 init_type_builder_generics (MonoObject *type)
3180 {
3181         MonoReflectionTypeBuilder *tb;
3182
3183         if (!is_sre_type_builder(mono_object_class (type)))
3184                 return;
3185         tb = (MonoReflectionTypeBuilder *)type;
3186
3187         if (tb && tb->generic_container)
3188                 mono_reflection_create_generic_class (tb);
3189 }
3190
3191 static guint32
3192 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3193 {
3194         MonoDynamicTable *table;
3195         MonoClass *klass;
3196         MonoType *custom = NULL, *type;
3197         guint32 *values;
3198         guint32 token, pclass, parent, sig;
3199         gchar *name;
3200
3201         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3202         if (token)
3203                 return token;
3204
3205         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3206         name = mono_string_to_utf8 (fb->name);
3207
3208         /*FIXME this is one more layer of ugliness due how types are created.*/
3209         init_type_builder_generics (fb->type);
3210
3211         /* fb->type does not include the custom modifiers */
3212         /* FIXME: We should do this in one place when a fieldbuilder is created */
3213         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3214         if (fb->modreq || fb->modopt)
3215                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3216
3217         sig = fieldref_encode_signature (assembly, NULL, type);
3218         g_free (custom);
3219
3220         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3221         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3222         
3223         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3224         parent >>= MONO_TYPEDEFORREF_BITS;
3225
3226         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3227
3228         if (assembly->save) {
3229                 alloc_table (table, table->rows + 1);
3230                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3231                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3232                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3233                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3234         }
3235
3236         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3237         table->next_idx ++;
3238         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3239         g_free (name);
3240         return token;
3241 }
3242
3243 static guint32
3244 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3245 {
3246         SigBuffer buf;
3247         guint32 nargs;
3248         guint32 size;
3249         guint32 i, idx;
3250
3251         if (!assembly->save)
3252                 return 0;
3253
3254         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3255         g_assert (helper->type == 2);
3256
3257         if (helper->arguments)
3258                 nargs = mono_array_length (helper->arguments);
3259         else
3260                 nargs = 0;
3261
3262         size = 10 + (nargs * 10);
3263         
3264         sigbuffer_init (&buf, 32);
3265
3266         /* Encode calling convention */
3267         /* Change Any to Standard */
3268         if ((helper->call_conv & 0x03) == 0x03)
3269                 helper->call_conv = 0x01;
3270         /* explicit_this implies has_this */
3271         if (helper->call_conv & 0x40)
3272                 helper->call_conv &= 0x20;
3273
3274         if (helper->call_conv == 0) { /* Unmanaged */
3275                 idx = helper->unmanaged_call_conv - 1;
3276         } else {
3277                 /* Managed */
3278                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3279                 if (helper->call_conv & 0x02) /* varargs */
3280                         idx += 0x05;
3281         }
3282
3283         sigbuffer_add_byte (&buf, idx);
3284         sigbuffer_add_value (&buf, nargs);
3285         encode_reflection_type (assembly, helper->return_type, &buf);
3286         for (i = 0; i < nargs; ++i) {
3287                 MonoArray *modreqs = NULL;
3288                 MonoArray *modopts = NULL;
3289                 MonoReflectionType *pt;
3290
3291                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3292                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3293                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3294                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3295
3296                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3297                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3298                 encode_reflection_type (assembly, pt, &buf);
3299         }
3300         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3301         sigbuffer_free (&buf);
3302
3303         return idx;
3304 }
3305
3306 static guint32 
3307 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3308 {
3309         guint32 idx;
3310         MonoDynamicTable *table;
3311         guint32 *values;
3312
3313         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3314         idx = table->next_idx ++;
3315         table->rows ++;
3316         alloc_table (table, table->rows);
3317         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3318
3319         values [MONO_STAND_ALONE_SIGNATURE] =
3320                 mono_reflection_encode_sighelper (assembly, helper);
3321
3322         return idx;
3323 }
3324
3325 static int
3326 reflection_cc_to_file (int call_conv) {
3327         switch (call_conv & 0x3) {
3328         case 0:
3329         case 1: return MONO_CALL_DEFAULT;
3330         case 2: return MONO_CALL_VARARG;
3331         default:
3332                 g_assert_not_reached ();
3333         }
3334         return 0;
3335 }
3336 #endif /* !DISABLE_REFLECTION_EMIT */
3337
3338 typedef struct {
3339         MonoType *parent;
3340         MonoMethodSignature *sig;
3341         char *name;
3342         guint32 token;
3343 } ArrayMethod;
3344
3345 #ifndef DISABLE_REFLECTION_EMIT
3346 static guint32
3347 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3348 {
3349         guint32 nparams, i;
3350         GList *tmp;
3351         char *name;
3352         MonoMethodSignature *sig;
3353         ArrayMethod *am;
3354         MonoType *mtype;
3355
3356         name = mono_string_to_utf8 (m->name);
3357         nparams = mono_array_length (m->parameters);
3358         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3359         sig->hasthis = 1;
3360         sig->sentinelpos = -1;
3361         sig->call_convention = reflection_cc_to_file (m->call_conv);
3362         sig->param_count = nparams;
3363         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3364         mtype = mono_reflection_type_get_handle (m->parent);
3365         for (i = 0; i < nparams; ++i)
3366                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3367
3368         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3369                 am = tmp->data;
3370                 if (strcmp (name, am->name) == 0 && 
3371                                 mono_metadata_type_equal (am->parent, mtype) &&
3372                                 mono_metadata_signature_equal (am->sig, sig)) {
3373                         g_free (name);
3374                         g_free (sig);
3375                         m->table_idx = am->token & 0xffffff;
3376                         return am->token;
3377                 }
3378         }
3379         am = g_new0 (ArrayMethod, 1);
3380         am->name = name;
3381         am->sig = sig;
3382         am->parent = mtype;
3383         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3384                 method_encode_signature (assembly, sig));
3385         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3386         m->table_idx = am->token & 0xffffff;
3387         return am->token;
3388 }
3389
3390 /*
3391  * Insert into the metadata tables all the info about the TypeBuilder tb.
3392  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3393  */
3394 static void
3395 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3396 {
3397         MonoDynamicTable *table;
3398         guint *values;
3399         int i, is_object = 0, is_system = 0;
3400         char *n;
3401
3402         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3403         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3404         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3405         n = mono_string_to_utf8 (tb->name);
3406         if (strcmp (n, "Object") == 0)
3407                 is_object++;
3408         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3409         g_free (n);
3410         n = mono_string_to_utf8 (tb->nspace);
3411         if (strcmp (n, "System") == 0)
3412                 is_system++;
3413         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3414         g_free (n);
3415         if (tb->parent && !(is_system && is_object) && 
3416                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3417                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3418         } else {
3419                 values [MONO_TYPEDEF_EXTENDS] = 0;
3420         }
3421         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3422         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3423
3424         /*
3425          * if we have explicitlayout or sequentiallayouts, output data in the
3426          * ClassLayout table.
3427          */
3428         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3429                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3430                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3431                 table->rows++;
3432                 alloc_table (table, table->rows);
3433                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3434                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3435                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3436                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3437         }
3438
3439         /* handle interfaces */
3440         if (tb->interfaces) {
3441                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3442                 i = table->rows;
3443                 table->rows += mono_array_length (tb->interfaces);
3444                 alloc_table (table, table->rows);
3445                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3446                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3447                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3448                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3449                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3450                         values += MONO_INTERFACEIMPL_SIZE;
3451                 }
3452         }
3453
3454         /* handle fields */
3455         if (tb->fields) {
3456                 table = &assembly->tables [MONO_TABLE_FIELD];
3457                 table->rows += tb->num_fields;
3458                 alloc_table (table, table->rows);
3459                 for (i = 0; i < tb->num_fields; ++i)
3460                         mono_image_get_field_info (
3461                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3462         }
3463
3464         /* handle constructors */
3465         if (tb->ctors) {
3466                 table = &assembly->tables [MONO_TABLE_METHOD];
3467                 table->rows += mono_array_length (tb->ctors);
3468                 alloc_table (table, table->rows);
3469                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3470                         mono_image_get_ctor_info (domain,
3471                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3472         }
3473
3474         /* handle methods */
3475         if (tb->methods) {
3476                 table = &assembly->tables [MONO_TABLE_METHOD];
3477                 table->rows += tb->num_methods;
3478                 alloc_table (table, table->rows);
3479                 for (i = 0; i < tb->num_methods; ++i)
3480                         mono_image_get_method_info (
3481                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3482         }
3483
3484         /* Do the same with properties etc.. */
3485         if (tb->events && mono_array_length (tb->events)) {
3486                 table = &assembly->tables [MONO_TABLE_EVENT];
3487                 table->rows += mono_array_length (tb->events);
3488                 alloc_table (table, table->rows);
3489                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3490                 table->rows ++;
3491                 alloc_table (table, table->rows);
3492                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3493                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3494                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3495                 for (i = 0; i < mono_array_length (tb->events); ++i)
3496                         mono_image_get_event_info (
3497                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3498         }
3499         if (tb->properties && mono_array_length (tb->properties)) {
3500                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3501                 table->rows += mono_array_length (tb->properties);
3502                 alloc_table (table, table->rows);
3503                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3504                 table->rows ++;
3505                 alloc_table (table, table->rows);
3506                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3507                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3508                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3509                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3510                         mono_image_get_property_info (
3511                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3512         }
3513
3514         /* handle generic parameters */
3515         if (tb->generic_params) {
3516                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3517                 table->rows += mono_array_length (tb->generic_params);
3518                 alloc_table (table, table->rows);
3519                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3520                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3521
3522                         mono_image_get_generic_param_info (
3523                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3524                 }
3525         }
3526
3527         mono_image_add_decl_security (assembly, 
3528                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3529
3530         if (tb->subtypes) {
3531                 MonoDynamicTable *ntable;
3532                 
3533                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3534                 ntable->rows += mono_array_length (tb->subtypes);
3535                 alloc_table (ntable, ntable->rows);
3536                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3537
3538                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3539                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3540
3541                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3542                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3543                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3544                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3545                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3546                                 ntable->next_idx, ntable->rows);*/
3547                         values += MONO_NESTED_CLASS_SIZE;
3548                         ntable->next_idx++;
3549                 }
3550         }
3551 }
3552 #endif
3553
3554 static void
3555 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3556 {
3557         int i;
3558
3559         mono_ptr_array_append (*types, type);
3560
3561         if (!type->subtypes)
3562                 return;
3563
3564         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3565                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3566                 collect_types (types, subtype);
3567         }
3568 }
3569
3570 static gint
3571 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3572 {
3573         if ((*type1)->table_idx < (*type2)->table_idx)
3574                 return -1;
3575         else
3576                 if ((*type1)->table_idx > (*type2)->table_idx)
3577                         return 1;
3578         else
3579                 return 0;
3580 }
3581
3582 static void
3583 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3584         int i;
3585
3586         if (!pinfo)
3587                 return;
3588         for (i = 0; i < mono_array_length (pinfo); ++i) {
3589                 MonoReflectionParamBuilder *pb;
3590                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3591                 if (!pb)
3592                         continue;
3593                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3594         }
3595 }
3596
3597 static void
3598 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3599         int i;
3600         
3601         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3602         if (tb->fields) {
3603                 for (i = 0; i < tb->num_fields; ++i) {
3604                         MonoReflectionFieldBuilder* fb;
3605                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3606                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3607                 }
3608         }
3609         if (tb->events) {
3610                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3611                         MonoReflectionEventBuilder* eb;
3612                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3613                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3614                 }
3615         }
3616         if (tb->properties) {
3617                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3618                         MonoReflectionPropertyBuilder* pb;
3619                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3620                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3621                 }
3622         }
3623         if (tb->ctors) {
3624                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3625                         MonoReflectionCtorBuilder* cb;
3626                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3627                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3628                         params_add_cattrs (assembly, cb->pinfo);
3629                 }
3630         }
3631
3632         if (tb->methods) {
3633                 for (i = 0; i < tb->num_methods; ++i) {
3634                         MonoReflectionMethodBuilder* mb;
3635                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3636                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3637                         params_add_cattrs (assembly, mb->pinfo);
3638                 }
3639         }
3640
3641         if (tb->subtypes) {
3642                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3643                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3644         }
3645 }
3646
3647 static void
3648 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3649 {
3650         int i;
3651         
3652         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3653
3654         if (moduleb->global_methods) {
3655                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3656                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3657                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3658                         params_add_cattrs (assembly, mb->pinfo);
3659                 }
3660         }
3661
3662         if (moduleb->global_fields) {
3663                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3664                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3665                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3666                 }
3667         }
3668         
3669         if (moduleb->types) {
3670                 for (i = 0; i < moduleb->num_types; ++i)
3671                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3672         }
3673 }
3674
3675 static void
3676 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3677 {
3678         MonoDynamicTable *table;
3679         guint32 *values;
3680         char blob_size [6];
3681         guchar hash [20];
3682         char *b = blob_size;
3683         char *dir, *path;
3684
3685         table = &assembly->tables [MONO_TABLE_FILE];
3686         table->rows++;
3687         alloc_table (table, table->rows);
3688         values = table->values + table->next_idx * MONO_FILE_SIZE;
3689         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3690         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3691         if (module->image->dynamic) {
3692                 /* This depends on the fact that the main module is emitted last */
3693                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3694                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3695         } else {
3696                 dir = NULL;
3697                 path = g_strdup (module->image->name);
3698         }
3699         mono_sha1_get_digest_from_file (path, hash);
3700         g_free (dir);
3701         g_free (path);
3702         mono_metadata_encode_value (20, b, &b);
3703         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3704         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3705         table->next_idx ++;
3706 }
3707
3708 static void
3709 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3710 {
3711         MonoDynamicTable *table;
3712         int i;
3713
3714         table = &assembly->tables [MONO_TABLE_MODULE];
3715         mb->table_idx = table->next_idx ++;
3716         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3717         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3718         i /= 16;
3719         ++i;
3720         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3721         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3722         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3723         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3724 }
3725
3726 static guint32
3727 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3728         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3729 {
3730         MonoDynamicTable *table;
3731         guint32 *values;
3732         guint32 visib, res;
3733
3734         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3735         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3736                 return 0;
3737
3738         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3739         table->rows++;
3740         alloc_table (table, table->rows);
3741         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3742
3743         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3744         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3745         if (klass->nested_in)
3746                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3747         else
3748                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3749         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3750         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3751
3752         res = table->next_idx;
3753
3754         table->next_idx ++;
3755
3756         /* Emit nested types */
3757         if (klass->ext && klass->ext->nested_classes) {
3758                 GList *tmp;
3759
3760                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3761                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3762         }
3763
3764         return res;
3765 }
3766
3767 static void
3768 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3769         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3770 {
3771         MonoClass *klass;
3772         guint32 idx, i;
3773
3774         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3775
3776         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3777
3778         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3779                                                                                                    parent_index, assembly);
3780
3781         /* 
3782          * Emit nested types
3783          * We need to do this ourselves since klass->nested_classes is not set up.
3784          */
3785         if (tb->subtypes) {
3786                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3787                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3788         }
3789 }
3790
3791 static void
3792 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3793         guint32 module_index, MonoDynamicImage *assembly)
3794 {
3795         MonoImage *image = module->image;
3796         MonoTableInfo  *t;
3797         guint32 i;
3798
3799         t = &image->tables [MONO_TABLE_TYPEDEF];
3800
3801         for (i = 0; i < t->rows; ++i) {
3802                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3803
3804                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3805                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3806         }
3807 }
3808
3809 static void
3810 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3811 {
3812         MonoDynamicTable *table;
3813         guint32 *values;
3814         guint32 scope, scope_idx, impl, current_idx;
3815         gboolean forwarder = TRUE;
3816         gpointer iter = NULL;
3817         MonoClass *nested;
3818
3819         if (klass->nested_in) {
3820                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3821                 forwarder = FALSE;
3822         } else {
3823                 scope = resolution_scope_from_image (assembly, klass->image);
3824                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3825                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3826                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3827         }
3828
3829         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3830
3831         table->rows++;
3832         alloc_table (table, table->rows);
3833         current_idx = table->next_idx;
3834         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3835
3836         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3837         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3838         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3839         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3840         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3841
3842         table->next_idx++;
3843
3844         while ((nested = mono_class_get_nested_types (klass, &iter)))
3845                 add_exported_type (assemblyb, assembly, nested, current_idx);
3846 }
3847
3848 static void
3849 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3850 {
3851         MonoClass *klass;
3852         int i;
3853
3854         if (!assemblyb->type_forwarders)
3855                 return;
3856
3857         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3858                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3859                 MonoType *type;
3860                 if (!t)
3861                         continue;
3862
3863                 type = mono_reflection_type_get_handle (t);
3864                 g_assert (type);
3865
3866                 klass = mono_class_from_mono_type (type);
3867
3868                 add_exported_type (assemblyb, assembly, klass, 0);
3869         }
3870 }
3871
3872 #define align_pointer(base,p)\
3873         do {\
3874                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3875                 if (__diff & 3)\
3876                         (p) += 4 - (__diff & 3);\
3877         } while (0)
3878
3879 static int
3880 compare_constants (const void *a, const void *b)
3881 {
3882         const guint32 *a_values = a;
3883         const guint32 *b_values = b;
3884         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3885 }
3886
3887 static int
3888 compare_semantics (const void *a, const void *b)
3889 {
3890         const guint32 *a_values = a;
3891         const guint32 *b_values = b;
3892         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3893         if (assoc)
3894                 return assoc;
3895         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3896 }
3897
3898 static int
3899 compare_custom_attrs (const void *a, const void *b)
3900 {
3901         const guint32 *a_values = a;
3902         const guint32 *b_values = b;
3903
3904         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3905 }
3906
3907 static int
3908 compare_field_marshal (const void *a, const void *b)
3909 {
3910         const guint32 *a_values = a;
3911         const guint32 *b_values = b;
3912
3913         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3914 }
3915
3916 static int
3917 compare_nested (const void *a, const void *b)
3918 {
3919         const guint32 *a_values = a;
3920         const guint32 *b_values = b;
3921
3922         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3923 }
3924
3925 static int
3926 compare_genericparam (const void *a, const void *b)
3927 {
3928         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3929         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3930
3931         if ((*b_entry)->owner == (*a_entry)->owner)
3932                 return 
3933                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3934                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3935         else
3936                 return (*a_entry)->owner - (*b_entry)->owner;
3937 }
3938
3939 static int
3940 compare_declsecurity_attrs (const void *a, const void *b)
3941 {
3942         const guint32 *a_values = a;
3943         const guint32 *b_values = b;
3944
3945         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3946 }
3947
3948 static int
3949 compare_interface_impl (const void *a, const void *b)
3950 {
3951         const guint32 *a_values = a;
3952         const guint32 *b_values = b;
3953
3954         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3955         if (klass)
3956                 return klass;
3957
3958         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3959 }
3960
3961 static void
3962 pad_heap (MonoDynamicStream *sh)
3963 {
3964         if (sh->index & 3) {
3965                 int sz = 4 - (sh->index & 3);
3966                 memset (sh->data + sh->index, 0, sz);
3967                 sh->index += sz;
3968         }
3969 }
3970
3971 struct StreamDesc {
3972         const char *name;
3973         MonoDynamicStream *stream;
3974 };
3975
3976 /*
3977  * build_compressed_metadata() fills in the blob of data that represents the 
3978  * raw metadata as it will be saved in the PE file. The five streams are output 
3979  * and the metadata tables are comnpressed from the guint32 array representation, 
3980  * to the compressed on-disk format.
3981  */
3982 static void
3983 build_compressed_metadata (MonoDynamicImage *assembly)
3984 {
3985         MonoDynamicTable *table;
3986         int i;
3987         guint64 valid_mask = 0;
3988         guint64 sorted_mask;
3989         guint32 heapt_size = 0;
3990         guint32 meta_size = 256; /* allow for header and other stuff */
3991         guint32 table_offset;
3992         guint32 ntables = 0;
3993         guint64 *int64val;
3994         guint32 *int32val;
3995         guint16 *int16val;
3996         MonoImage *meta;
3997         unsigned char *p;
3998         struct StreamDesc stream_desc [5];
3999
4000         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4001         for (i = 0; i < assembly->gen_params->len; i++){
4002                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4003                 write_generic_param_entry (assembly, entry);
4004         }
4005
4006         stream_desc [0].name  = "#~";
4007         stream_desc [0].stream = &assembly->tstream;
4008         stream_desc [1].name  = "#Strings";
4009         stream_desc [1].stream = &assembly->sheap;
4010         stream_desc [2].name  = "#US";
4011         stream_desc [2].stream = &assembly->us;
4012         stream_desc [3].name  = "#Blob";
4013         stream_desc [3].stream = &assembly->blob;
4014         stream_desc [4].name  = "#GUID";
4015         stream_desc [4].stream = &assembly->guid;
4016         
4017         /* tables that are sorted */
4018         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4019                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4020                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4021                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4022                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4023                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4024                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4025         
4026         /* Compute table sizes */
4027         /* the MonoImage has already been created in mono_image_basic_init() */
4028         meta = &assembly->image;
4029
4030         /* sizes should be multiple of 4 */
4031         pad_heap (&assembly->blob);
4032         pad_heap (&assembly->guid);
4033         pad_heap (&assembly->sheap);
4034         pad_heap (&assembly->us);
4035
4036         /* Setup the info used by compute_sizes () */
4037         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4038         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4039         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4040
4041         meta_size += assembly->blob.index;
4042         meta_size += assembly->guid.index;
4043         meta_size += assembly->sheap.index;
4044         meta_size += assembly->us.index;
4045
4046         for (i=0; i < MONO_TABLE_NUM; ++i)
4047                 meta->tables [i].rows = assembly->tables [i].rows;
4048         
4049         for (i = 0; i < MONO_TABLE_NUM; i++){
4050                 if (meta->tables [i].rows == 0)
4051                         continue;
4052                 valid_mask |= (guint64)1 << i;
4053                 ntables ++;
4054                 meta->tables [i].row_size = mono_metadata_compute_size (
4055                         meta, i, &meta->tables [i].size_bitfield);
4056                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4057         }
4058         heapt_size += 24; /* #~ header size */
4059         heapt_size += ntables * 4;
4060         /* make multiple of 4 */
4061         heapt_size += 3;
4062         heapt_size &= ~3;
4063         meta_size += heapt_size;
4064         meta->raw_metadata = g_malloc0 (meta_size);
4065         p = (unsigned char*)meta->raw_metadata;
4066         /* the metadata signature */
4067         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4068         /* version numbers and 4 bytes reserved */
4069         int16val = (guint16*)p;
4070         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4071         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4072         p += 8;
4073         /* version string */
4074         int32val = (guint32*)p;
4075         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4076         p += 4;
4077         memcpy (p, meta->version, strlen (meta->version));
4078         p += GUINT32_FROM_LE (*int32val);
4079         align_pointer (meta->raw_metadata, p);
4080         int16val = (guint16*)p;
4081         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4082         *int16val = GUINT16_TO_LE (5); /* number of streams */
4083         p += 4;
4084
4085         /*
4086          * write the stream info.
4087          */
4088         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4089         table_offset += 3; table_offset &= ~3;
4090
4091         assembly->tstream.index = heapt_size;
4092         for (i = 0; i < 5; ++i) {
4093                 int32val = (guint32*)p;
4094                 stream_desc [i].stream->offset = table_offset;
4095                 *int32val++ = GUINT32_TO_LE (table_offset);
4096                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4097                 table_offset += GUINT32_FROM_LE (*int32val);
4098                 table_offset += 3; table_offset &= ~3;
4099                 p += 8;
4100                 strcpy ((char*)p, stream_desc [i].name);
4101                 p += strlen (stream_desc [i].name) + 1;
4102                 align_pointer (meta->raw_metadata, p);
4103         }
4104         /* 
4105          * now copy the data, the table stream header and contents goes first.
4106          */
4107         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4108         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4109         int32val = (guint32*)p;
4110         *int32val = GUINT32_TO_LE (0); /* reserved */
4111         p += 4;
4112
4113         *p++ = 2; /* version */
4114         *p++ = 0;
4115
4116         if (meta->idx_string_wide)
4117                 *p |= 0x01;
4118         if (meta->idx_guid_wide)
4119                 *p |= 0x02;
4120         if (meta->idx_blob_wide)
4121                 *p |= 0x04;
4122         ++p;
4123         *p++ = 1; /* reserved */
4124         int64val = (guint64*)p;
4125         *int64val++ = GUINT64_TO_LE (valid_mask);
4126         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4127         p += 16;
4128         int32val = (guint32*)p;
4129         for (i = 0; i < MONO_TABLE_NUM; i++){
4130                 if (meta->tables [i].rows == 0)
4131                         continue;
4132                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4133         }
4134         p = (unsigned char*)int32val;
4135
4136         /* sort the tables that still need sorting */
4137         table = &assembly->tables [MONO_TABLE_CONSTANT];
4138         if (table->rows)
4139                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4140         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4141         if (table->rows)
4142                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4143         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4144         if (table->rows)
4145                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4146         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4147         if (table->rows)
4148                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4149         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4150         if (table->rows)
4151                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4152         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4153         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4154         if (table->rows)
4155                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4156         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4157         if (table->rows)
4158                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4159
4160         /* compress the tables */
4161         for (i = 0; i < MONO_TABLE_NUM; i++){
4162                 int row, col;
4163                 guint32 *values;
4164                 guint32 bitfield = meta->tables [i].size_bitfield;
4165                 if (!meta->tables [i].rows)
4166                         continue;
4167                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4168                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4169                 meta->tables [i].base = (char*)p;
4170                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4171                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4172                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4173                                 switch (mono_metadata_table_size (bitfield, col)) {
4174                                 case 1:
4175                                         *p++ = values [col];
4176                                         break;
4177                                 case 2:
4178                                         *p++ = values [col] & 0xff;
4179                                         *p++ = (values [col] >> 8) & 0xff;
4180                                         break;
4181                                 case 4:
4182                                         *p++ = values [col] & 0xff;
4183                                         *p++ = (values [col] >> 8) & 0xff;
4184                                         *p++ = (values [col] >> 16) & 0xff;
4185                                         *p++ = (values [col] >> 24) & 0xff;
4186                                         break;
4187                                 default:
4188                                         g_assert_not_reached ();
4189                                 }
4190                         }
4191                 }
4192                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4193         }
4194         
4195         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4196         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4197         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4198         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4199         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4200
4201         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4202 }
4203
4204 /*
4205  * Some tables in metadata need to be sorted according to some criteria, but
4206  * when methods and fields are first created with reflection, they may be assigned a token
4207  * that doesn't correspond to the final token they will get assigned after the sorting.
4208  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4209  * with the reflection objects that represent them. Once all the tables are set up, the 
4210  * reflection objects will contains the correct table index. fixup_method() will fixup the
4211  * tokens for the method with ILGenerator @ilgen.
4212  */
4213 static void
4214 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4215 {
4216         guint32 code_idx = GPOINTER_TO_UINT (value);
4217         MonoReflectionILTokenInfo *iltoken;
4218         MonoReflectionFieldBuilder *field;
4219         MonoReflectionCtorBuilder *ctor;
4220         MonoReflectionMethodBuilder *method;
4221         MonoReflectionTypeBuilder *tb;
4222         MonoReflectionArrayMethod *am;
4223         guint32 i, idx = 0;
4224         unsigned char *target;
4225
4226         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4227                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4228                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4229                 switch (target [3]) {
4230                 case MONO_TABLE_FIELD:
4231                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4232                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4233                                 idx = field->table_idx;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4235                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4236                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4237                         } else {
4238                                 g_assert_not_reached ();
4239                         }
4240                         break;
4241                 case MONO_TABLE_METHOD:
4242                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4243                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4244                                 idx = method->table_idx;
4245                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4246                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4247                                 idx = ctor->table_idx;
4248                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4249                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4250                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4251                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4252                         } else {
4253                                 g_assert_not_reached ();
4254                         }
4255                         break;
4256                 case MONO_TABLE_TYPEDEF:
4257                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4258                                 g_assert_not_reached ();
4259                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4260                         idx = tb->table_idx;
4261                         break;
4262                 case MONO_TABLE_MEMBERREF:
4263                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4264                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4265                                 idx = am->table_idx;
4266                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4267                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4268                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4269                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4270                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4271                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4272                                 continue;
4273                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4274                                 continue;
4275                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4276                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4277                                 g_assert (is_field_on_inst (f));
4278                                 continue;
4279                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4280                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4281                                 continue;
4282                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4283                                 continue;
4284                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4285                                 continue;
4286                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4287                                 continue;
4288                         } else {
4289                                 g_assert_not_reached ();
4290                         }
4291                         break;
4292                 case MONO_TABLE_METHODSPEC:
4293                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4294                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4295                                 g_assert (mono_method_signature (m)->generic_param_count);
4296                                 continue;
4297                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4298                                 continue;
4299                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4300                                 continue;
4301                         } else {
4302                                 g_assert_not_reached ();
4303                         }
4304                         break;
4305                 default:
4306                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4307                 }
4308                 target [0] = idx & 0xff;
4309                 target [1] = (idx >> 8) & 0xff;
4310                 target [2] = (idx >> 16) & 0xff;
4311         }
4312 }
4313
4314 /*
4315  * fixup_cattrs:
4316  *
4317  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4318  * value is not known when the table is emitted.
4319  */
4320 static void
4321 fixup_cattrs (MonoDynamicImage *assembly)
4322 {
4323         MonoDynamicTable *table;
4324         guint32 *values;
4325         guint32 type, i, idx, token;
4326         MonoObject *ctor;
4327
4328         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4329
4330         for (i = 0; i < table->rows; ++i) {
4331                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4332
4333                 type = values [MONO_CUSTOM_ATTR_TYPE];
4334                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4335                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4336                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4337                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4338                         g_assert (ctor);
4339
4340                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4341                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4342                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4343                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4344                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4345                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4346                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4347                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4348                         }
4349                 }
4350         }
4351 }
4352
4353 static void
4354 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4355 {
4356         MonoDynamicTable *table;
4357         guint32 *values;
4358
4359         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4360         table->rows++;
4361         alloc_table (table, table->rows);
4362         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4363         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4364         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4365         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4366         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4367         table->next_idx++;
4368 }
4369
4370 static void
4371 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4372 {
4373         MonoDynamicTable *table;
4374         guint32 *values;
4375         char blob_size [6];
4376         guchar hash [20];
4377         char *b = blob_size;
4378         char *name, *sname;
4379         guint32 idx, offset;
4380
4381         if (rsrc->filename) {
4382                 name = mono_string_to_utf8 (rsrc->filename);
4383                 sname = g_path_get_basename (name);
4384         
4385                 table = &assembly->tables [MONO_TABLE_FILE];
4386                 table->rows++;
4387                 alloc_table (table, table->rows);
4388                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4389                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4390                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4391                 g_free (sname);
4392
4393                 mono_sha1_get_digest_from_file (name, hash);
4394                 mono_metadata_encode_value (20, b, &b);
4395                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4396                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4397                 g_free (name);
4398                 idx = table->next_idx++;
4399                 rsrc->offset = 0;
4400                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4401         } else {
4402                 char sizebuf [4];
4403                 char *data;
4404                 guint len;
4405                 if (rsrc->data) {
4406                         data = mono_array_addr (rsrc->data, char, 0);
4407                         len = mono_array_length (rsrc->data);
4408                 } else {
4409                         data = NULL;
4410                         len = 0;
4411                 }
4412                 offset = len;
4413                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4414                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4415                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4416                 mono_image_add_stream_data (&assembly->resources, data, len);
4417
4418                 if (!mb->is_main)
4419                         /* 
4420                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4421                          * the main module, but that needs to reference the FILE table
4422                          * which isn't emitted yet.
4423                          */
4424                         return;
4425                 else
4426                         idx = 0;
4427         }
4428
4429         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4430 }
4431
4432 static void
4433 set_version_from_string (MonoString *version, guint32 *values)
4434 {
4435         gchar *ver, *p, *str;
4436         guint32 i;
4437         
4438         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4439         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4440         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4441         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4442         if (!version)
4443                 return;
4444         ver = str = mono_string_to_utf8 (version);
4445         for (i = 0; i < 4; ++i) {
4446                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4447                 switch (*p) {
4448                 case '.':
4449                         p++;
4450                         break;
4451                 case '*':
4452                         /* handle Revision and Build */
4453                         p++;
4454                         break;
4455                 }
4456                 ver = p;
4457         }
4458         g_free (str);
4459 }
4460
4461 static guint32
4462 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4463         gsize len;
4464         guint32 token = 0;
4465         char blob_size [6];
4466         char *b = blob_size;
4467
4468         if (!pkey)
4469                 return token;
4470
4471         len = mono_array_length (pkey);
4472         mono_metadata_encode_value (len, b, &b);
4473         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4474         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4475
4476         assembly->public_key = g_malloc (len);
4477         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4478         assembly->public_key_len = len;
4479
4480         /* Special case: check for ECMA key (16 bytes) */
4481         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4482                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4483                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4484         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4485                 /* minimum key size (in 2.0) is 384 bits */
4486                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4487         } else {
4488                 /* FIXME - verifier */
4489                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4490                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4491         }
4492         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4493
4494         return token;
4495 }
4496
4497 static void
4498 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4499 {
4500         MonoDynamicTable *table;
4501         MonoDynamicImage *assembly;
4502         MonoReflectionAssemblyBuilder *assemblyb;
4503         MonoDomain *domain;
4504         guint32 *values;
4505         int i;
4506         guint32 module_index;
4507
4508         assemblyb = moduleb->assemblyb;
4509         assembly = moduleb->dynamic_image;
4510         domain = mono_object_domain (assemblyb);
4511
4512         /* Emit ASSEMBLY table */
4513         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4514         alloc_table (table, 1);
4515         values = table->values + MONO_ASSEMBLY_SIZE;
4516         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4517         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4518         if (assemblyb->culture) {
4519                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4520         } else {
4521                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4522         }
4523         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4524         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4525         set_version_from_string (assemblyb->version, values);
4526
4527         /* Emit FILE + EXPORTED_TYPE table */
4528         module_index = 0;
4529         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4530                 int j;
4531                 MonoReflectionModuleBuilder *file_module = 
4532                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4533                 if (file_module != moduleb) {
4534                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4535                         module_index ++;
4536                         if (file_module->types) {
4537                                 for (j = 0; j < file_module->num_types; ++j) {
4538                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4539                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4540                                 }
4541                         }
4542                 }
4543         }
4544         if (assemblyb->loaded_modules) {
4545                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4546                         MonoReflectionModule *file_module = 
4547                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4548                         mono_image_fill_file_table (domain, file_module, assembly);
4549                         module_index ++;
4550                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4551                 }
4552         }
4553         if (assemblyb->type_forwarders)
4554                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4555
4556         /* Emit MANIFESTRESOURCE table */
4557         module_index = 0;
4558         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4559                 int j;
4560                 MonoReflectionModuleBuilder *file_module = 
4561                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4562                 /* The table for the main module is emitted later */
4563                 if (file_module != moduleb) {
4564                         module_index ++;
4565                         if (file_module->resources) {
4566                                 int len = mono_array_length (file_module->resources);
4567                                 for (j = 0; j < len; ++j) {
4568                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4569                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4570                                 }
4571                         }
4572                 }
4573         }               
4574 }
4575
4576 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4577
4578 /*
4579  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4580  * for the modulebuilder @moduleb.
4581  * At the end of the process, method and field tokens are fixed up and the 
4582  * on-disk compressed metadata representation is created.
4583  */
4584 void
4585 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4586 {
4587         MonoDynamicTable *table;
4588         MonoDynamicImage *assembly;
4589         MonoReflectionAssemblyBuilder *assemblyb;
4590         MonoDomain *domain;
4591         MonoPtrArray types;
4592         guint32 *values;
4593         int i, j;
4594
4595         assemblyb = moduleb->assemblyb;
4596         assembly = moduleb->dynamic_image;
4597         domain = mono_object_domain (assemblyb);
4598
4599         if (assembly->text_rva)
4600                 return;
4601
4602         assembly->text_rva = START_TEXT_RVA;
4603
4604         if (moduleb->is_main) {
4605                 mono_image_emit_manifest (moduleb);
4606         }
4607
4608         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4609         table->rows = 1; /* .<Module> */
4610         table->next_idx++;
4611         alloc_table (table, table->rows);
4612         /*
4613          * Set the first entry.
4614          */
4615         values = table->values + table->columns;
4616         values [MONO_TYPEDEF_FLAGS] = 0;
4617         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4618         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4619         values [MONO_TYPEDEF_EXTENDS] = 0;
4620         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4621         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4622
4623         /* 
4624          * handle global methods 
4625          * FIXME: test what to do when global methods are defined in multiple modules.
4626          */
4627         if (moduleb->global_methods) {
4628                 table = &assembly->tables [MONO_TABLE_METHOD];
4629                 table->rows += mono_array_length (moduleb->global_methods);
4630                 alloc_table (table, table->rows);
4631                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4632                         mono_image_get_method_info (
4633                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4634         }
4635         if (moduleb->global_fields) {
4636                 table = &assembly->tables [MONO_TABLE_FIELD];
4637                 table->rows += mono_array_length (moduleb->global_fields);
4638                 alloc_table (table, table->rows);
4639                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4640                         mono_image_get_field_info (
4641                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4642         }
4643
4644         table = &assembly->tables [MONO_TABLE_MODULE];
4645         alloc_table (table, 1);
4646         mono_image_fill_module_table (domain, moduleb, assembly);
4647
4648         /* Collect all types into a list sorted by their table_idx */
4649         mono_ptr_array_init (types, moduleb->num_types);
4650
4651         if (moduleb->types)
4652                 for (i = 0; i < moduleb->num_types; ++i) {
4653                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4654                         collect_types (&types, type);
4655                 }
4656
4657         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4658         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4659         table->rows += mono_ptr_array_size (types);
4660         alloc_table (table, table->rows);
4661
4662         /*
4663          * Emit type names + namespaces at one place inside the string heap,
4664          * so load_class_names () needs to touch fewer pages.
4665          */
4666         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4668                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4669         }
4670         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4671                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4672                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4673         }
4674
4675         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4676                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4677                 mono_image_get_type_info (domain, type, assembly);
4678         }
4679
4680         /* 
4681          * table->rows is already set above and in mono_image_fill_module_table.
4682          */
4683         /* add all the custom attributes at the end, once all the indexes are stable */
4684         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4685
4686         /* CAS assembly permissions */
4687         if (assemblyb->permissions_minimum)
4688                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4689         if (assemblyb->permissions_optional)
4690                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4691         if (assemblyb->permissions_refused)
4692                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4693
4694         module_add_cattrs (assembly, moduleb);
4695
4696         /* fixup tokens */
4697         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4698
4699         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4700          * the final tokens and don't need another fixup pass. */
4701
4702         if (moduleb->global_methods) {
4703                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4704                         MonoReflectionMethodBuilder *mb = mono_array_get (
4705                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4706                         mono_image_add_methodimpl (assembly, mb);
4707                 }
4708         }
4709
4710         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4711                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4712                 if (type->methods) {
4713                         for (j = 0; j < type->num_methods; ++j) {
4714                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4715                                         type->methods, MonoReflectionMethodBuilder*, j);
4716
4717                                 mono_image_add_methodimpl (assembly, mb);
4718                         }
4719                 }
4720         }
4721
4722         mono_ptr_array_destroy (types);
4723
4724         fixup_cattrs (assembly);
4725 }
4726
4727 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4728
4729 void
4730 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4731 {
4732         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4733 }
4734
4735 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4736
4737
4738 typedef struct {
4739         guint32 import_lookup_table;
4740         guint32 timestamp;
4741         guint32 forwarder;
4742         guint32 name_rva;
4743         guint32 import_address_table_rva;
4744 } MonoIDT;
4745
4746 typedef struct {
4747         guint32 name_rva;
4748         guint32 flags;
4749 } MonoILT;
4750
4751 #ifndef DISABLE_REFLECTION_EMIT
4752
4753 /*
4754  * mono_image_insert_string:
4755  * @module: module builder object
4756  * @str: a string
4757  *
4758  * Insert @str into the user string stream of @module.
4759  */
4760 guint32
4761 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4762 {
4763         MonoDynamicImage *assembly;
4764         guint32 idx;
4765         char buf [16];
4766         char *b = buf;
4767         
4768         MONO_ARCH_SAVE_REGS;
4769
4770         if (!module->dynamic_image)
4771                 mono_image_module_basic_init (module);
4772
4773         assembly = module->dynamic_image;
4774         
4775         if (assembly->save) {
4776                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4777                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4778 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4779         {
4780                 char *swapped = g_malloc (2 * mono_string_length (str));
4781                 const char *p = (const char*)mono_string_chars (str);
4782
4783                 swap_with_size (swapped, p, 2, mono_string_length (str));
4784                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4785                 g_free (swapped);
4786         }
4787 #else
4788                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4789 #endif
4790                 mono_image_add_stream_data (&assembly->us, "", 1);
4791         } else {
4792                 idx = assembly->us.index ++;
4793         }
4794
4795         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4796
4797         return MONO_TOKEN_STRING | idx;
4798 }
4799
4800 guint32
4801 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4802 {
4803         MonoClass *klass;
4804         guint32 token = 0;
4805         MonoMethodSignature *sig;
4806
4807         klass = obj->vtable->klass;
4808         if (strcmp (klass->name, "MonoMethod") == 0) {
4809                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4810                 MonoMethodSignature *old;
4811                 guint32 sig_token, parent;
4812                 int nargs, i;
4813
4814                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4815
4816                 nargs = mono_array_length (opt_param_types);
4817                 old = mono_method_signature (method);
4818                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4819
4820                 sig->hasthis = old->hasthis;
4821                 sig->explicit_this = old->explicit_this;
4822                 sig->call_convention = old->call_convention;
4823                 sig->generic_param_count = old->generic_param_count;
4824                 sig->param_count = old->param_count + nargs;
4825                 sig->sentinelpos = old->param_count;
4826                 sig->ret = old->ret;
4827
4828                 for (i = 0; i < old->param_count; i++)
4829                         sig->params [i] = old->params [i];
4830
4831                 for (i = 0; i < nargs; i++) {
4832                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4833                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4834                 }
4835
4836                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4837                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4838                 parent >>= MONO_TYPEDEFORREF_BITS;
4839
4840                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4841                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4842
4843                 sig_token = method_encode_signature (assembly, sig);
4844                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4845         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4846                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4847                 ReflectionMethodBuilder rmb;
4848                 guint32 parent, sig_token;
4849                 int nopt_args, nparams, ngparams, i;
4850                 char *name;
4851
4852                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4853                 rmb.opt_types = opt_param_types;
4854                 nopt_args = mono_array_length (opt_param_types);
4855
4856                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4857                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4858                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4859
4860                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4861                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4862                 sig->call_convention = rmb.call_conv;
4863                 sig->generic_param_count = ngparams;
4864                 sig->param_count = nparams + nopt_args;
4865                 sig->sentinelpos = nparams;
4866                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4867
4868                 for (i = 0; i < nparams; i++) {
4869                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4870                         sig->params [i] = mono_reflection_type_get_handle (rt);
4871                 }
4872
4873                 for (i = 0; i < nopt_args; i++) {
4874                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4875                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4876                 }
4877
4878                 sig_token = method_builder_encode_signature (assembly, &rmb);
4879
4880                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4881                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4882
4883                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4884                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4885
4886                 name = mono_string_to_utf8 (rmb.name);
4887                 token = mono_image_get_varargs_method_token (
4888                         assembly, parent, name, sig_token);
4889                 g_free (name);
4890         } else {
4891                 g_error ("requested method token for %s\n", klass->name);
4892         }
4893
4894         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4895         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4896         return token;
4897 }
4898
4899 /*
4900  * mono_image_create_token:
4901  * @assembly: a dynamic assembly
4902  * @obj:
4903  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4904  *
4905  * Get a token to insert in the IL code stream for the given MemberInfo.
4906  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4907  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4908  * entry.
4909  */
4910 guint32
4911 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4912                                                  gboolean create_open_instance, gboolean register_token)
4913 {
4914         MonoClass *klass;
4915         guint32 token = 0;
4916
4917         klass = obj->vtable->klass;
4918
4919         /* Check for user defined reflection objects */
4920         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4921         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4922                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4923
4924         if (strcmp (klass->name, "MethodBuilder") == 0) {
4925                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4926                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4927
4928                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4929                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4930                 else
4931                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4932                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4933         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4934                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4935                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4936
4937                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4938                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4939                 else
4940                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4941                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4942         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4943                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4944                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4945                 if (tb->generic_params) {
4946                         token = mono_image_get_generic_field_token (assembly, fb);
4947                 } else {
4948                         if (tb->module->dynamic_image == assembly) {
4949                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4950                         } else {
4951                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4952                         }
4953                 }
4954         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4955                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4956                 if (create_open_instance && tb->generic_params) {
4957                         MonoType *type;
4958                         init_type_builder_generics (obj);
4959                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4960                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4961                         token = mono_metadata_token_from_dor (token);
4962                 } else if (tb->module->dynamic_image == assembly) {
4963                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4964                 } else {
4965                         MonoType *type;
4966                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4967                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4968                 }
4969         } else if (strcmp (klass->name, "MonoType") == 0) {
4970                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4971                 MonoClass *mc = mono_class_from_mono_type (type);
4972                 token = mono_metadata_token_from_dor (
4973                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4974         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4975                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4976                 token = mono_metadata_token_from_dor (
4977                         mono_image_typedef_or_ref (assembly, type));
4978         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4979                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4980                 token = mono_metadata_token_from_dor (
4981                         mono_image_typedef_or_ref (assembly, type));
4982         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4983                    strcmp (klass->name, "MonoMethod") == 0 ||
4984                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4985                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4986                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4987                 if (m->method->is_inflated) {
4988                         if (create_open_instance)
4989                                 token = mono_image_get_methodspec_token (assembly, m->method);
4990                         else
4991                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4992                 } else if ((m->method->klass->image == &assembly->image) &&
4993                          !m->method->klass->generic_class) {
4994                         static guint32 method_table_idx = 0xffffff;
4995                         if (m->method->klass->wastypebuilder) {
4996                                 /* we use the same token as the one that was assigned
4997                                  * to the Methodbuilder.
4998                                  * FIXME: do the equivalent for Fields.
4999                                  */
5000                                 token = m->method->token;
5001                         } else {
5002                                 /*
5003                                  * Each token should have a unique index, but the indexes are
5004                                  * assigned by managed code, so we don't know about them. An
5005                                  * easy solution is to count backwards...
5006                                  */
5007                                 method_table_idx --;
5008                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5009                         }
5010                 } else {
5011                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5012                 }
5013                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5014         } else if (strcmp (klass->name, "MonoField") == 0) {
5015                 MonoReflectionField *f = (MonoReflectionField *)obj;
5016                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5017                         static guint32 field_table_idx = 0xffffff;
5018                         field_table_idx --;
5019                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5020                 } else {
5021                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5022                 }
5023                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5024         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5025                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5026                 token = mono_image_get_array_token (assembly, m);
5027         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5028                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5029                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5030         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5031                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5032                 token = mono_metadata_token_from_dor (
5033                         mono_image_typedef_or_ref (assembly, type));
5034         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5035                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5036                 token = mono_image_get_field_on_inst_token (assembly, f);
5037         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5038                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5039                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5040         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5041                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5042                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5043         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5044                 MonoReflectionType *type = (MonoReflectionType *)obj;
5045                 token = mono_metadata_token_from_dor (
5046                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5047         } else {
5048                 g_error ("requested token for %s\n", klass->name);
5049         }
5050
5051         if (register_token)
5052                 mono_image_register_token (assembly, token, obj);
5053
5054         return token;
5055 }
5056
5057 /*
5058  * mono_image_register_token:
5059  *
5060  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5061  * the Module.ResolveXXXToken () methods to work.
5062  */
5063 void
5064 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5065 {
5066         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5067         if (prev) {
5068                 /* There could be multiple MethodInfo objects with the same token */
5069                 //g_assert (prev == obj);
5070         } else {
5071                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5072         }
5073 }
5074
5075 static MonoDynamicImage*
5076 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5077 {
5078         static const guchar entrycode [16] = {0xff, 0x25, 0};
5079         MonoDynamicImage *image;
5080         int i;
5081
5082         const char *version;
5083
5084         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5085                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5086         else
5087                 version = mono_get_runtime_info ()->runtime_version;
5088
5089 #if HAVE_BOEHM_GC
5090         /* The MonoGHashTable's need GC tracking */
5091         image = GC_MALLOC (sizeof (MonoDynamicImage));
5092 #else
5093         image = g_new0 (MonoDynamicImage, 1);
5094 #endif
5095         
5096         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5097         
5098         /*g_print ("created image %p\n", image);*/
5099         /* keep in sync with image.c */
5100         image->image.name = assembly_name;
5101         image->image.assembly_name = image->image.name; /* they may be different */
5102         image->image.module_name = module_name;
5103         image->image.version = g_strdup (version);
5104         image->image.md_version_major = 1;
5105         image->image.md_version_minor = 1;
5106         image->image.dynamic = TRUE;
5107
5108         image->image.references = g_new0 (MonoAssembly*, 1);
5109         image->image.references [0] = NULL;
5110
5111         mono_image_init (&image->image);
5112
5113         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5114         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5115         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5116         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5117         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5118         image->handleref = g_hash_table_new (NULL, NULL);
5119         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5120         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5122         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5123         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5125         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5126         image->gen_params = g_ptr_array_new ();
5127         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5128
5129         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5130         string_heap_init (&image->sheap);
5131         mono_image_add_stream_data (&image->us, "", 1);
5132         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5133         /* import tables... */
5134         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5135         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5136         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5137         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5138         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5139         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5140         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5141         stream_data_align (&image->code);
5142
5143         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5144
5145         for (i=0; i < MONO_TABLE_NUM; ++i) {
5146                 image->tables [i].next_idx = 1;
5147                 image->tables [i].columns = table_sizes [i];
5148         }
5149
5150         image->image.assembly = (MonoAssembly*)assembly;
5151         image->run = assembly->run;
5152         image->save = assembly->save;
5153         image->pe_kind = 0x1; /* ILOnly */
5154         image->machine = 0x14c; /* I386 */
5155         
5156         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5157
5158         return image;
5159 }
5160 #endif
5161
5162 static void
5163 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5164 {
5165         g_free (key);
5166 }
5167
5168 static void
5169 release_hashtable (MonoGHashTable **hash)
5170 {
5171         if (*hash) {
5172                 mono_g_hash_table_destroy (*hash);
5173                 *hash = NULL;
5174         }
5175 }
5176
5177 void
5178 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5179 {
5180         release_hashtable (&image->token_fixups);
5181         release_hashtable (&image->handleref_managed);
5182         release_hashtable (&image->tokens);
5183         release_hashtable (&image->remapped_tokens);
5184         release_hashtable (&image->generic_def_objects);
5185         release_hashtable (&image->methodspec);
5186 }
5187
5188 void
5189 mono_dynamic_image_free (MonoDynamicImage *image)
5190 {
5191         MonoDynamicImage *di = image;
5192         GList *list;
5193         int i;
5194
5195         if (di->methodspec)
5196                 mono_g_hash_table_destroy (di->methodspec);
5197         if (di->typespec)
5198                 g_hash_table_destroy (di->typespec);
5199         if (di->typeref)
5200                 g_hash_table_destroy (di->typeref);
5201         if (di->handleref)
5202                 g_hash_table_destroy (di->handleref);
5203         if (di->handleref_managed)
5204                 mono_g_hash_table_destroy (di->handleref_managed);
5205         if (di->tokens)
5206                 mono_g_hash_table_destroy (di->tokens);
5207         if (di->remapped_tokens)
5208                 mono_g_hash_table_destroy (di->remapped_tokens);
5209         if (di->generic_def_objects)
5210                 mono_g_hash_table_destroy (di->generic_def_objects);
5211         if (di->blob_cache) {
5212                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5213                 g_hash_table_destroy (di->blob_cache);
5214         }
5215         if (di->standalonesig_cache)
5216                 g_hash_table_destroy (di->standalonesig_cache);
5217         for (list = di->array_methods; list; list = list->next) {
5218                 ArrayMethod *am = (ArrayMethod *)list->data;
5219                 g_free (am->sig);
5220                 g_free (am->name);
5221                 g_free (am);
5222         }
5223         g_list_free (di->array_methods);
5224         if (di->gen_params) {
5225                 for (i = 0; i < di->gen_params->len; i++) {
5226                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5227                         mono_gc_deregister_root ((char*) &entry->gparam);
5228                         g_free (entry);
5229                 }
5230                 g_ptr_array_free (di->gen_params, TRUE);
5231         }
5232         if (di->token_fixups)
5233                 mono_g_hash_table_destroy (di->token_fixups);
5234         if (di->method_to_table_idx)
5235                 g_hash_table_destroy (di->method_to_table_idx);
5236         if (di->field_to_table_idx)
5237                 g_hash_table_destroy (di->field_to_table_idx);
5238         if (di->method_aux_hash)
5239                 g_hash_table_destroy (di->method_aux_hash);
5240         if (di->vararg_aux_hash)
5241                 g_hash_table_destroy (di->vararg_aux_hash);
5242         g_free (di->strong_name);
5243         g_free (di->win32_res);
5244         if (di->public_key)
5245                 g_free (di->public_key);
5246
5247         /*g_print ("string heap destroy for image %p\n", di);*/
5248         mono_dynamic_stream_reset (&di->sheap);
5249         mono_dynamic_stream_reset (&di->code);
5250         mono_dynamic_stream_reset (&di->resources);
5251         mono_dynamic_stream_reset (&di->us);
5252         mono_dynamic_stream_reset (&di->blob);
5253         mono_dynamic_stream_reset (&di->tstream);
5254         mono_dynamic_stream_reset (&di->guid);
5255         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5256                 g_free (di->tables [i].values);
5257         }
5258 }       
5259
5260 #ifndef DISABLE_REFLECTION_EMIT
5261
5262 /*
5263  * mono_image_basic_init:
5264  * @assembly: an assembly builder object
5265  *
5266  * Create the MonoImage that represents the assembly builder and setup some
5267  * of the helper hash table and the basic metadata streams.
5268  */
5269 void
5270 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5271 {
5272         MonoDynamicAssembly *assembly;
5273         MonoDynamicImage *image;
5274         MonoDomain *domain = mono_object_domain (assemblyb);
5275         
5276         MONO_ARCH_SAVE_REGS;
5277
5278         if (assemblyb->dynamic_assembly)
5279                 return;
5280
5281 #if HAVE_BOEHM_GC
5282         /* assembly->assembly.image might be GC allocated */
5283         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5284 #else
5285         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5286 #endif
5287
5288         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5289         
5290         assembly->assembly.ref_count = 1;
5291         assembly->assembly.dynamic = TRUE;
5292         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5293         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5294         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5295         if (assemblyb->culture)
5296                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5297         else
5298                 assembly->assembly.aname.culture = g_strdup ("");
5299
5300         if (assemblyb->version) {
5301                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5302                         char **version = g_strsplit (vstr, ".", 4);
5303                         char **parts = version;
5304                         assembly->assembly.aname.major = atoi (*parts++);
5305                         assembly->assembly.aname.minor = atoi (*parts++);
5306                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5307                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5308
5309                         g_strfreev (version);
5310                         g_free (vstr);
5311         } else {
5312                         assembly->assembly.aname.major = 0;
5313                         assembly->assembly.aname.minor = 0;
5314                         assembly->assembly.aname.build = 0;
5315                         assembly->assembly.aname.revision = 0;
5316         }
5317
5318         assembly->run = assemblyb->access != 2;
5319         assembly->save = assemblyb->access != 1;
5320         assembly->domain = domain;
5321
5322         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5323         image->initial_image = TRUE;
5324         assembly->assembly.aname.name = image->image.name;
5325         assembly->assembly.image = &image->image;
5326         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5327                 /* -1 to correct for the trailing NULL byte */
5328                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5329                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5330                 }
5331                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5332         }
5333
5334         mono_domain_assemblies_lock (domain);
5335         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5336         mono_domain_assemblies_unlock (domain);
5337
5338         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5339         
5340         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5341         
5342         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5343 }
5344
5345 #endif /* !DISABLE_REFLECTION_EMIT */
5346
5347 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5348
5349 static int
5350 calc_section_size (MonoDynamicImage *assembly)
5351 {
5352         int nsections = 0;
5353
5354         /* alignment constraints */
5355         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5356         g_assert ((assembly->code.index % 4) == 0);
5357         assembly->meta_size += 3;
5358         assembly->meta_size &= ~3;
5359         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5360         g_assert ((assembly->resources.index % 4) == 0);
5361
5362         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5363         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5364         nsections++;
5365
5366         if (assembly->win32_res) {
5367                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5368
5369                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5370                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5371                 nsections++;
5372         }
5373
5374         assembly->sections [MONO_SECTION_RELOC].size = 12;
5375         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5376         nsections++;
5377
5378         return nsections;
5379 }
5380
5381 typedef struct {
5382         guint32 id;
5383         guint32 offset;
5384         GSList *children;
5385         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5386 } ResTreeNode;
5387
5388 static int
5389 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5390 {
5391         ResTreeNode *t1 = (ResTreeNode*)a;
5392         ResTreeNode *t2 = (ResTreeNode*)b;
5393
5394         return t1->id - t2->id;
5395 }
5396
5397 /*
5398  * resource_tree_create:
5399  *
5400  *  Organize the resources into a resource tree.
5401  */
5402 static ResTreeNode *
5403 resource_tree_create (MonoArray *win32_resources)
5404 {
5405         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5406         GSList *l;
5407         int i;
5408
5409         tree = g_new0 (ResTreeNode, 1);
5410         
5411         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5412                 MonoReflectionWin32Resource *win32_res =
5413                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5414
5415                 /* Create node */
5416
5417                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5418                 lang_node = g_new0 (ResTreeNode, 1);
5419                 lang_node->id = win32_res->lang_id;
5420                 lang_node->win32_res = win32_res;
5421
5422                 /* Create type node if neccesary */
5423                 type_node = NULL;
5424                 for (l = tree->children; l; l = l->next)
5425                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5426                                 type_node = (ResTreeNode*)l->data;
5427                                 break;
5428                         }
5429
5430                 if (!type_node) {
5431                         type_node = g_new0 (ResTreeNode, 1);
5432                         type_node->id = win32_res->res_type;
5433
5434                         /* 
5435                          * The resource types have to be sorted otherwise
5436                          * Windows Explorer can't display the version information.
5437                          */
5438                         tree->children = g_slist_insert_sorted (tree->children, 
5439                                 type_node, resource_tree_compare_by_id);
5440                 }
5441
5442                 /* Create res node if neccesary */
5443                 res_node = NULL;
5444                 for (l = type_node->children; l; l = l->next)
5445                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5446                                 res_node = (ResTreeNode*)l->data;
5447                                 break;
5448                         }
5449
5450                 if (!res_node) {
5451                         res_node = g_new0 (ResTreeNode, 1);
5452                         res_node->id = win32_res->res_id;
5453                         type_node->children = g_slist_append (type_node->children, res_node);
5454                 }
5455
5456                 res_node->children = g_slist_append (res_node->children, lang_node);
5457         }
5458
5459         return tree;
5460 }
5461
5462 /*
5463  * resource_tree_encode:
5464  * 
5465  *   Encode the resource tree into the format used in the PE file.
5466  */
5467 static void
5468 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5469 {
5470         char *entries;
5471         MonoPEResourceDir dir;
5472         MonoPEResourceDirEntry dir_entry;
5473         MonoPEResourceDataEntry data_entry;
5474         GSList *l;
5475         guint32 res_id_entries;
5476
5477         /*
5478          * For the format of the resource directory, see the article
5479          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5480          * Matt Pietrek
5481          */
5482
5483         memset (&dir, 0, sizeof (dir));
5484         memset (&dir_entry, 0, sizeof (dir_entry));
5485         memset (&data_entry, 0, sizeof (data_entry));
5486
5487         g_assert (sizeof (dir) == 16);
5488         g_assert (sizeof (dir_entry) == 8);
5489         g_assert (sizeof (data_entry) == 16);
5490
5491         node->offset = p - begin;
5492
5493         /* IMAGE_RESOURCE_DIRECTORY */
5494         res_id_entries = g_slist_length (node->children);
5495         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5496
5497         memcpy (p, &dir, sizeof (dir));
5498         p += sizeof (dir);
5499
5500         /* Reserve space for entries */
5501         entries = p;
5502         p += sizeof (dir_entry) * res_id_entries;
5503
5504         /* Write children */
5505         for (l = node->children; l; l = l->next) {
5506                 ResTreeNode *child = (ResTreeNode*)l->data;
5507
5508                 if (child->win32_res) {
5509                         guint32 size;
5510
5511                         child->offset = p - begin;
5512
5513                         /* IMAGE_RESOURCE_DATA_ENTRY */
5514                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5515                         size = mono_array_length (child->win32_res->res_data);
5516                         data_entry.rde_size = GUINT32_TO_LE (size);
5517
5518                         memcpy (p, &data_entry, sizeof (data_entry));
5519                         p += sizeof (data_entry);
5520
5521                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5522                         p += size;
5523                 } else {
5524                         resource_tree_encode (child, begin, p, &p);
5525                 }
5526         }
5527
5528         /* IMAGE_RESOURCE_ENTRY */
5529         for (l = node->children; l; l = l->next) {
5530                 ResTreeNode *child = (ResTreeNode*)l->data;
5531
5532                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5533                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5534
5535                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5536                 entries += sizeof (dir_entry);
5537         }
5538
5539         *endbuf = p;
5540 }
5541
5542 static void
5543 resource_tree_free (ResTreeNode * node)
5544 {
5545         GSList * list;
5546         for (list = node->children; list; list = list->next)
5547                 resource_tree_free ((ResTreeNode*)list->data);
5548         g_slist_free(node->children);
5549         g_free (node);
5550 }
5551
5552 static void
5553 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5554 {
5555         char *buf;
5556         char *p;
5557         guint32 size, i;
5558         MonoReflectionWin32Resource *win32_res;
5559         ResTreeNode *tree;
5560
5561         if (!assemblyb->win32_resources)
5562                 return;
5563
5564         /*
5565          * Resources are stored in a three level tree inside the PE file.
5566          * - level one contains a node for each type of resource
5567          * - level two contains a node for each resource
5568          * - level three contains a node for each instance of a resource for a
5569          *   specific language.
5570          */
5571
5572         tree = resource_tree_create (assemblyb->win32_resources);
5573
5574         /* Estimate the size of the encoded tree */
5575         size = 0;
5576         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5577                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5578                 size += mono_array_length (win32_res->res_data);
5579         }
5580         /* Directory structure */
5581         size += mono_array_length (assemblyb->win32_resources) * 256;
5582         p = buf = g_malloc (size);
5583
5584         resource_tree_encode (tree, p, p, &p);
5585
5586         g_assert (p - buf <= size);
5587
5588         assembly->win32_res = g_malloc (p - buf);
5589         assembly->win32_res_size = p - buf;
5590         memcpy (assembly->win32_res, buf, p - buf);
5591
5592         g_free (buf);
5593         resource_tree_free (tree);
5594 }
5595
5596 static void
5597 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5598 {
5599         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5600         int i;
5601
5602         p += sizeof (MonoPEResourceDir);
5603         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5604                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5605                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5606                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5607                         fixup_resource_directory (res_section, child, rva);
5608                 } else {
5609                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5610                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5611                 }
5612
5613                 p += sizeof (MonoPEResourceDirEntry);
5614         }
5615 }
5616
5617 static void
5618 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5619 {
5620         guint32 dummy;
5621         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5622                 g_error ("WriteFile returned %d\n", GetLastError ());
5623 }
5624
5625 /*
5626  * mono_image_create_pefile:
5627  * @mb: a module builder object
5628  * 
5629  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5630  * assembly->pefile where it can be easily retrieved later in chunks.
5631  */
5632 void
5633 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5634 {
5635         MonoMSDOSHeader *msdos;
5636         MonoDotNetHeader *header;
5637         MonoSectionTable *section;
5638         MonoCLIHeader *cli_header;
5639         guint32 size, image_size, virtual_base, text_offset;
5640         guint32 header_start, section_start, file_offset, virtual_offset;
5641         MonoDynamicImage *assembly;
5642         MonoReflectionAssemblyBuilder *assemblyb;
5643         MonoDynamicStream pefile_stream = {0};
5644         MonoDynamicStream *pefile = &pefile_stream;
5645         int i, nsections;
5646         guint32 *rva, value;
5647         guchar *p;
5648         static const unsigned char msheader[] = {
5649                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5650                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5651                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5652                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5653                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5654                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5655                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5656                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5657         };
5658
5659         assemblyb = mb->assemblyb;
5660
5661         mono_image_basic_init (assemblyb);
5662         assembly = mb->dynamic_image;
5663
5664         assembly->pe_kind = assemblyb->pe_kind;
5665         assembly->machine = assemblyb->machine;
5666         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5667         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5668         
5669         mono_image_build_metadata (mb);
5670
5671         if (mb->is_main && assemblyb->resources) {
5672                 int len = mono_array_length (assemblyb->resources);
5673                 for (i = 0; i < len; ++i)
5674                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5675         }
5676
5677         if (mb->resources) {
5678                 int len = mono_array_length (mb->resources);
5679                 for (i = 0; i < len; ++i)
5680                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5681         }
5682
5683         build_compressed_metadata (assembly);
5684
5685         if (mb->is_main)
5686                 assembly_add_win32_resources (assembly, assemblyb);
5687
5688         nsections = calc_section_size (assembly);
5689         
5690         /* The DOS header and stub */
5691         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5692         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5693
5694         /* the dotnet header */
5695         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5696
5697         /* the section tables */
5698         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5699
5700         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5701         virtual_offset = VIRT_ALIGN;
5702         image_size = 0;
5703
5704         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5705                 if (!assembly->sections [i].size)
5706                         continue;
5707                 /* align offsets */
5708                 file_offset += FILE_ALIGN - 1;
5709                 file_offset &= ~(FILE_ALIGN - 1);
5710                 virtual_offset += VIRT_ALIGN - 1;
5711                 virtual_offset &= ~(VIRT_ALIGN - 1);
5712
5713                 assembly->sections [i].offset = file_offset;
5714                 assembly->sections [i].rva = virtual_offset;
5715
5716                 file_offset += assembly->sections [i].size;
5717                 virtual_offset += assembly->sections [i].size;
5718                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5719         }
5720
5721         file_offset += FILE_ALIGN - 1;
5722         file_offset &= ~(FILE_ALIGN - 1);
5723
5724         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5725
5726         /* back-patch info */
5727         msdos = (MonoMSDOSHeader*)pefile->data;
5728         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5729
5730         header = (MonoDotNetHeader*)(pefile->data + header_start);
5731         header->pesig [0] = 'P';
5732         header->pesig [1] = 'E';
5733         
5734         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5735         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5736         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5737         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5738         if (assemblyb->pekind == 1) {
5739                 /* it's a dll */
5740                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5741         } else {
5742                 /* it's an exe */
5743                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5744         }
5745
5746         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5747
5748         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5749         header->pe.pe_major = 6;
5750         header->pe.pe_minor = 0;
5751         size = assembly->sections [MONO_SECTION_TEXT].size;
5752         size += FILE_ALIGN - 1;
5753         size &= ~(FILE_ALIGN - 1);
5754         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5755         size = assembly->sections [MONO_SECTION_RSRC].size;
5756         size += FILE_ALIGN - 1;
5757         size &= ~(FILE_ALIGN - 1);
5758         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5759         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5760         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5761         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5762         /* pe_rva_entry_point always at the beginning of the text section */
5763         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5764
5765         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5766         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5767         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5768         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5769         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5770         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5771         size = section_start;
5772         size += FILE_ALIGN - 1;
5773         size &= ~(FILE_ALIGN - 1);
5774         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5775         size = image_size;
5776         size += VIRT_ALIGN - 1;
5777         size &= ~(VIRT_ALIGN - 1);
5778         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5779
5780         /*
5781         // Translate the PEFileKind value to the value expected by the Windows loader
5782         */
5783         {
5784                 short kind;
5785
5786                 /*
5787                 // PEFileKinds.Dll == 1
5788                 // PEFileKinds.ConsoleApplication == 2
5789                 // PEFileKinds.WindowApplication == 3
5790                 //
5791                 // need to get:
5792                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5793                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5794                 */
5795                 if (assemblyb->pekind == 3)
5796                         kind = 2;
5797                 else
5798                         kind = 3;
5799                 
5800                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5801         }    
5802         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5803         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5804         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5805         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5806         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5807         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5808
5809         /* fill data directory entries */
5810
5811         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5812         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5813
5814         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5815         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5816
5817         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5818         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5819         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5820         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5821         /* patch entrypoint name */
5822         if (assemblyb->pekind == 1)
5823                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5824         else
5825                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5826         /* patch imported function RVA name */
5827         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5828         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5829
5830         /* the import table */
5831         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5832         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5833         /* patch imported dll RVA name and other entries in the dir */
5834         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5835         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5836         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5837         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5838         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5839         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5840
5841         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5842         value = (assembly->text_rva + assembly->imp_names_offset);
5843         *p++ = (value) & 0xff;
5844         *p++ = (value >> 8) & (0xff);
5845         *p++ = (value >> 16) & (0xff);
5846         *p++ = (value >> 24) & (0xff);
5847
5848         /* the CLI header info */
5849         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5850         cli_header->ch_size = GUINT32_FROM_LE (72);
5851         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5852         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5853         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5854         if (assemblyb->entry_point) {
5855                 guint32 table_idx = 0;
5856                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5857                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5858                         table_idx = methodb->table_idx;
5859                 } else {
5860                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5861                 }
5862                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5863         } else {
5864                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5865         }
5866         /* The embedded managed resources */
5867         text_offset = assembly->text_rva + assembly->code.index;
5868         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5869         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5870         text_offset += assembly->resources.index;
5871         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5872         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5873         text_offset += assembly->meta_size;
5874         if (assembly->strong_name_size) {
5875                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5876                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5877                 text_offset += assembly->strong_name_size;
5878         }
5879
5880         /* write the section tables and section content */
5881         section = (MonoSectionTable*)(pefile->data + section_start);
5882         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5883                 static const char section_names [][7] = {
5884                         ".text", ".rsrc", ".reloc"
5885                 };
5886                 if (!assembly->sections [i].size)
5887                         continue;
5888                 strcpy (section->st_name, section_names [i]);
5889                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5890                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5891                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5892                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5893                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5894                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5895                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5896                 section ++;
5897         }
5898         
5899         checked_write_file (file, pefile->data, pefile->index);
5900         
5901         mono_dynamic_stream_reset (pefile);
5902         
5903         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5904                 if (!assembly->sections [i].size)
5905                         continue;
5906                 
5907                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5908                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5909                 
5910                 switch (i) {
5911                 case MONO_SECTION_TEXT:
5912                         /* patch entry point */
5913                         p = (guchar*)(assembly->code.data + 2);
5914                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5915                         *p++ = (value) & 0xff;
5916                         *p++ = (value >> 8) & 0xff;
5917                         *p++ = (value >> 16) & 0xff;
5918                         *p++ = (value >> 24) & 0xff;
5919                 
5920                         checked_write_file (file, assembly->code.data, assembly->code.index);
5921                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5922                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5923                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5924                                 
5925
5926                         g_free (assembly->image.raw_metadata);
5927                         break;
5928                 case MONO_SECTION_RELOC: {
5929                         struct {
5930                                 guint32 page_rva;
5931                                 guint32 block_size;
5932                                 guint16 type_and_offset;
5933                                 guint16 term;
5934                         } reloc;
5935                         
5936                         g_assert (sizeof (reloc) == 12);
5937                         
5938                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5939                         reloc.block_size = GUINT32_FROM_LE (12);
5940                         
5941                         /* 
5942                          * the entrypoint is always at the start of the text section 
5943                          * 3 is IMAGE_REL_BASED_HIGHLOW
5944                          * 2 is patch_size_rva - text_rva
5945                          */
5946                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5947                         reloc.term = 0;
5948                         
5949                         checked_write_file (file, &reloc, sizeof (reloc));
5950                         
5951                         break;
5952                 }
5953                 case MONO_SECTION_RSRC:
5954                         if (assembly->win32_res) {
5955
5956                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5957                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5958                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5959                         }
5960                         break;
5961                 default:
5962                         g_assert_not_reached ();
5963                 }
5964         }
5965         
5966         /* check that the file is properly padded */
5967         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5968                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5969         if (! SetEndOfFile (file))
5970                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5971         
5972         mono_dynamic_stream_reset (&assembly->code);
5973         mono_dynamic_stream_reset (&assembly->us);
5974         mono_dynamic_stream_reset (&assembly->blob);
5975         mono_dynamic_stream_reset (&assembly->guid);
5976         mono_dynamic_stream_reset (&assembly->sheap);
5977
5978         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5979         g_hash_table_destroy (assembly->blob_cache);
5980         assembly->blob_cache = NULL;
5981 }
5982
5983 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5984
5985 void
5986 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5987 {
5988         g_assert_not_reached ();
5989 }
5990
5991 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5992
5993 #ifndef DISABLE_REFLECTION_EMIT
5994
5995 MonoReflectionModule *
5996 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5997 {
5998         char *name;
5999         MonoImage *image;
6000         MonoImageOpenStatus status;
6001         MonoDynamicAssembly *assembly;
6002         guint32 module_count;
6003         MonoImage **new_modules;
6004         gboolean *new_modules_loaded;
6005         
6006         name = mono_string_to_utf8 (fileName);
6007
6008         image = mono_image_open (name, &status);
6009         if (!image) {
6010                 MonoException *exc;
6011                 if (status == MONO_IMAGE_ERROR_ERRNO)
6012                         exc = mono_get_exception_file_not_found (fileName);
6013                 else
6014                         exc = mono_get_exception_bad_image_format (name);
6015                 g_free (name);
6016                 mono_raise_exception (exc);
6017         }
6018
6019         g_free (name);
6020
6021         assembly = ab->dynamic_assembly;
6022         image->assembly = (MonoAssembly*)assembly;
6023
6024         module_count = image->assembly->image->module_count;
6025         new_modules = g_new0 (MonoImage *, module_count + 1);
6026         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6027
6028         if (image->assembly->image->modules)
6029                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6030         if (image->assembly->image->modules_loaded)
6031                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6032         new_modules [module_count] = image;
6033         new_modules_loaded [module_count] = TRUE;
6034         mono_image_addref (image);
6035
6036         g_free (image->assembly->image->modules);
6037         image->assembly->image->modules = new_modules;
6038         image->assembly->image->modules_loaded = new_modules_loaded;
6039         image->assembly->image->module_count ++;
6040
6041         mono_assembly_load_references (image, &status);
6042         if (status) {
6043                 mono_image_close (image);
6044                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6045         }
6046
6047         return mono_module_get_object (mono_domain_get (), image);
6048 }
6049
6050 #endif /* DISABLE_REFLECTION_EMIT */
6051
6052 /*
6053  * We need to return always the same object for MethodInfo, FieldInfo etc..
6054  * but we need to consider the reflected type.
6055  * type uses a different hash, since it uses custom hash/equal functions.
6056  */
6057
6058 typedef struct {
6059         gpointer item;
6060         MonoClass *refclass;
6061 } ReflectedEntry;
6062
6063 static gboolean
6064 reflected_equal (gconstpointer a, gconstpointer b) {
6065         const ReflectedEntry *ea = a;
6066         const ReflectedEntry *eb = b;
6067
6068         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6069 }
6070
6071 static guint
6072 reflected_hash (gconstpointer a) {
6073         const ReflectedEntry *ea = a;
6074         return mono_aligned_addr_hash (ea->item);
6075 }
6076
6077 #define CHECK_OBJECT(t,p,k)     \
6078         do {    \
6079                 t _obj; \
6080                 ReflectedEntry e;       \
6081                 e.item = (p);   \
6082                 e.refclass = (k);       \
6083                 mono_domain_lock (domain);      \
6084                 if (!domain->refobject_hash)    \
6085                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6086                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6087                         mono_domain_unlock (domain);    \
6088                         return _obj;    \
6089                 }       \
6090         mono_domain_unlock (domain); \
6091         } while (0)
6092
6093 #ifdef HAVE_BOEHM_GC
6094 /* ReflectedEntry doesn't need to be GC tracked */
6095 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6096 #define FREE_REFENTRY(entry) g_free ((entry))
6097 #define REFENTRY_REQUIRES_CLEANUP
6098 #else
6099 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6100 /* FIXME: */
6101 #define FREE_REFENTRY(entry)
6102 #endif
6103
6104 #define CACHE_OBJECT(t,p,o,k)   \
6105         do {    \
6106                 t _obj; \
6107         ReflectedEntry pe; \
6108         pe.item = (p); \
6109         pe.refclass = (k); \
6110         mono_domain_lock (domain); \
6111                 if (!domain->refobject_hash)    \
6112                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6113         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6114         if (!_obj) { \
6115                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6116                     e->item = (p);      \
6117                     e->refclass = (k);  \
6118                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6119             _obj = o; \
6120         } \
6121                 mono_domain_unlock (domain);    \
6122         return _obj; \
6123         } while (0)
6124
6125 static void
6126 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6127 {
6128         mono_domain_lock (domain);
6129         if (domain->refobject_hash) {
6130         ReflectedEntry pe;
6131                 gpointer orig_pe, orig_value;
6132
6133                 pe.item = o;
6134                 pe.refclass = klass;
6135                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6136                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6137                         FREE_REFENTRY (orig_pe);
6138                 }
6139         }
6140         mono_domain_unlock (domain);
6141 }
6142
6143 #ifdef REFENTRY_REQUIRES_CLEANUP
6144 static void
6145 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6146 {
6147         FREE_REFENTRY (key);
6148 }
6149 #endif
6150
6151 void
6152 mono_reflection_cleanup_domain (MonoDomain *domain)
6153 {
6154         if (domain->refobject_hash) {
6155 /*let's avoid scanning the whole hashtable if not needed*/
6156 #ifdef REFENTRY_REQUIRES_CLEANUP
6157                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6158 #endif
6159                 mono_g_hash_table_destroy (domain->refobject_hash);
6160                 domain->refobject_hash = NULL;
6161         }
6162 }
6163
6164 #ifndef DISABLE_REFLECTION_EMIT
6165 static gpointer
6166 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6167 {
6168         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6169 }
6170
6171 static gpointer
6172 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6173 {
6174         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6175 }
6176
6177 void
6178 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6179 {
6180         MonoDynamicImage *image = moduleb->dynamic_image;
6181         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6182         if (!image) {
6183                 MonoError error;
6184                 int module_count;
6185                 MonoImage **new_modules;
6186                 MonoImage *ass;
6187                 char *name, *fqname;
6188                 /*
6189                  * FIXME: we already created an image in mono_image_basic_init (), but
6190                  * we don't know which module it belongs to, since that is only 
6191                  * determined at assembly save time.
6192                  */
6193                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6194                 name = mono_string_to_utf8 (ab->name);
6195                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6196                 if (!mono_error_ok (&error)) {
6197                         g_free (name);
6198                         mono_error_raise_exception (&error);
6199                 }
6200                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6201
6202                 moduleb->module.image = &image->image;
6203                 moduleb->dynamic_image = image;
6204                 register_module (mono_object_domain (moduleb), moduleb, image);
6205
6206                 /* register the module with the assembly */
6207                 ass = ab->dynamic_assembly->assembly.image;
6208                 module_count = ass->module_count;
6209                 new_modules = g_new0 (MonoImage *, module_count + 1);
6210
6211                 if (ass->modules)
6212                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6213                 new_modules [module_count] = &image->image;
6214                 mono_image_addref (&image->image);
6215
6216                 g_free (ass->modules);
6217                 ass->modules = new_modules;
6218                 ass->module_count ++;
6219         }
6220 }
6221
6222 void
6223 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6224 {
6225         MonoDynamicImage *image = moduleb->dynamic_image;
6226
6227         g_assert (type->type);
6228         image->wrappers_type = mono_class_from_mono_type (type->type);
6229 }
6230
6231 #endif
6232
6233 /*
6234  * mono_assembly_get_object:
6235  * @domain: an app domain
6236  * @assembly: an assembly
6237  *
6238  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6239  */
6240 MonoReflectionAssembly*
6241 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6242 {
6243         static MonoClass *assembly_type;
6244         MonoReflectionAssembly *res;
6245         
6246         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6247         if (!assembly_type) {
6248                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6249                 if (class == NULL)
6250                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6251                 g_assert (class);
6252                 assembly_type = class;
6253         }
6254         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6255         res->assembly = assembly;
6256
6257         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6258 }
6259
6260
6261
6262 MonoReflectionModule*   
6263 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6264 {
6265         static MonoClass *module_type;
6266         MonoReflectionModule *res;
6267         char* basename;
6268         
6269         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6270         if (!module_type) {
6271                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6272                 if (class == NULL)
6273                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6274                 g_assert (class);
6275                 module_type = class;
6276         }
6277         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6278
6279         res->image = image;
6280         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6281
6282         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6283         basename = g_path_get_basename (image->name);
6284         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6285         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6286         
6287         g_free (basename);
6288
6289         if (image->assembly->image == image) {
6290                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6291         } else {
6292                 int i;
6293                 res->token = 0;
6294                 if (image->assembly->image->modules) {
6295                         for (i = 0; i < image->assembly->image->module_count; i++) {
6296                                 if (image->assembly->image->modules [i] == image)
6297                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6298                         }
6299                         g_assert (res->token);
6300                 }
6301         }
6302
6303         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6304 }
6305
6306 MonoReflectionModule*   
6307 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6308 {
6309         static MonoClass *module_type;
6310         MonoReflectionModule *res;
6311         MonoTableInfo *table;
6312         guint32 cols [MONO_FILE_SIZE];
6313         const char *name;
6314         guint32 i, name_idx;
6315         const char *val;
6316         
6317         if (!module_type) {
6318                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6319                 if (class == NULL)
6320                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6321                 g_assert (class);
6322                 module_type = class;
6323         }
6324         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6325
6326         table = &image->tables [MONO_TABLE_FILE];
6327         g_assert (table_index < table->rows);
6328         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6329
6330         res->image = NULL;
6331         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6332         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6333
6334         /* Check whenever the row has a corresponding row in the moduleref table */
6335         table = &image->tables [MONO_TABLE_MODULEREF];
6336         for (i = 0; i < table->rows; ++i) {
6337                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6338                 val = mono_metadata_string_heap (image, name_idx);
6339                 if (strcmp (val, name) == 0)
6340                         res->image = image->modules [i];
6341         }
6342
6343         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6344         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6345         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6346         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6347         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6348
6349         return res;
6350 }
6351
6352 static gboolean
6353 verify_safe_for_managed_space (MonoType *type)
6354 {
6355         switch (type->type) {
6356 #ifdef DEBUG_HARDER
6357         case MONO_TYPE_ARRAY:
6358                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6359         case MONO_TYPE_PTR:
6360                 return verify_safe_for_managed_space (type->data.type);
6361         case MONO_TYPE_SZARRAY:
6362                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6363         case MONO_TYPE_GENERICINST: {
6364                 MonoGenericInst *inst = type->data.generic_class->inst;
6365                 int i;
6366                 if (!inst->is_open)
6367                         break;
6368                 for (i = 0; i < inst->type_argc; ++i)
6369                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6370                                 return FALSE;
6371                 break;
6372         }
6373 #endif
6374         case MONO_TYPE_VAR:
6375         case MONO_TYPE_MVAR:
6376                 return TRUE;
6377         }
6378         return TRUE;
6379 }
6380
6381 static MonoType*
6382 mono_type_normalize (MonoType *type)
6383 {
6384         int i;
6385         MonoGenericClass *gclass;
6386         MonoGenericInst *ginst;
6387         MonoClass *gtd;
6388         MonoGenericContainer *gcontainer;
6389         MonoType **argv = NULL;
6390         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6391
6392         if (type->type != MONO_TYPE_GENERICINST)
6393                 return type;
6394
6395         gclass = type->data.generic_class;
6396         ginst = gclass->context.class_inst;
6397         if (!ginst->is_open)
6398                 return type;
6399
6400         gtd = gclass->container_class;
6401         gcontainer = gtd->generic_container;
6402         argv = g_newa (MonoType*, ginst->type_argc);
6403
6404         for (i = 0; i < ginst->type_argc; ++i) {
6405                 MonoType *t = ginst->type_argv [i], *norm;
6406                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6407                         is_denorm_gtd = FALSE;
6408                 norm = mono_type_normalize (t);
6409                 argv [i] = norm;
6410                 if (norm != t)
6411                         requires_rebind = TRUE;
6412         }
6413
6414         if (is_denorm_gtd)
6415                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6416
6417         if (requires_rebind) {
6418                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6419                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6420         }
6421
6422         return type;
6423 }
6424 /*
6425  * mono_type_get_object:
6426  * @domain: an app domain
6427  * @type: a type
6428  *
6429  * Return an System.MonoType object representing the type @type.
6430  */
6431 MonoReflectionType*
6432 mono_type_get_object (MonoDomain *domain, MonoType *type)
6433 {
6434         MonoType *norm_type;
6435         MonoReflectionType *res;
6436         MonoClass *klass = mono_class_from_mono_type (type);
6437
6438         /*we must avoid using @type as it might have come
6439          * from a mono_metadata_type_dup and the caller
6440          * expects that is can be freed.
6441          * Using the right type from 
6442          */
6443         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6444
6445         /* void is very common */
6446         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6447                 return (MonoReflectionType*)domain->typeof_void;
6448
6449         /*
6450          * If the vtable of the given class was already created, we can use
6451          * the MonoType from there and avoid all locking and hash table lookups.
6452          * 
6453          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6454          * that the resulting object is different.   
6455          */
6456         if (type == &klass->byval_arg && !klass->image->dynamic) {
6457                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6458                 if (vtable && vtable->type)
6459                         return vtable->type;
6460         }
6461
6462         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6463         mono_domain_lock (domain);
6464         if (!domain->type_hash)
6465                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6466                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6467         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6468                 mono_domain_unlock (domain);
6469                 mono_loader_unlock ();
6470                 return res;
6471         }
6472
6473         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6474          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6475          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6476          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6477          * artifact of how generics are encoded and should be transparent to managed code so we
6478          * need to weed out this diference when retrieving managed System.Type objects.
6479          */
6480         norm_type = mono_type_normalize (type);
6481         if (norm_type != type) {
6482                 res = mono_type_get_object (domain, norm_type);
6483                 mono_g_hash_table_insert (domain->type_hash, type, res);
6484                 mono_domain_unlock (domain);
6485                 mono_loader_unlock ();
6486                 return res;
6487         }
6488
6489         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6490         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6491                 g_assert (0);
6492
6493         if (!verify_safe_for_managed_space (type)) {
6494                 mono_domain_unlock (domain);
6495                 mono_loader_unlock ();
6496                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6497         }
6498
6499         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6500                 gboolean is_type_done = TRUE;
6501                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6502                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6503                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6504                 */
6505                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6506                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6507
6508                         if (gparam->owner && gparam->owner->is_method) {
6509                                 MonoMethod *method = gparam->owner->owner.method;
6510                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6511                                         is_type_done = FALSE;
6512                         } else if (gparam->owner && !gparam->owner->is_method) {
6513                                 MonoClass *klass = gparam->owner->owner.klass;
6514                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6515                                         is_type_done = FALSE;
6516                         }
6517                 } 
6518
6519                 /* g_assert_not_reached (); */
6520                 /* should this be considered an error condition? */
6521                 if (is_type_done && !type->byref) {
6522                         mono_domain_unlock (domain);
6523                         mono_loader_unlock ();
6524                         return mono_class_get_ref_info (klass);
6525                 }
6526         }
6527         /* This is stored in vtables/JITted code so it has to be pinned */
6528         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6529         res->type = type;
6530         mono_g_hash_table_insert (domain->type_hash, type, res);
6531
6532         if (type->type == MONO_TYPE_VOID)
6533                 domain->typeof_void = (MonoObject*)res;
6534
6535         mono_domain_unlock (domain);
6536         mono_loader_unlock ();
6537         return res;
6538 }
6539
6540 /*
6541  * mono_method_get_object:
6542  * @domain: an app domain
6543  * @method: a method
6544  * @refclass: the reflected type (can be NULL)
6545  *
6546  * Return an System.Reflection.MonoMethod object representing the method @method.
6547  */
6548 MonoReflectionMethod*
6549 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6550 {
6551         /*
6552          * We use the same C representation for methods and constructors, but the type 
6553          * name in C# is different.
6554          */
6555         static MonoClass *System_Reflection_MonoMethod = NULL;
6556         static MonoClass *System_Reflection_MonoCMethod = NULL;
6557         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6558         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6559         MonoClass *klass;
6560         MonoReflectionMethod *ret;
6561
6562         if (method->is_inflated) {
6563                 MonoReflectionGenericMethod *gret;
6564
6565                 refclass = method->klass;
6566                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6567                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6568                         if (!System_Reflection_MonoGenericCMethod)
6569                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6570                         klass = System_Reflection_MonoGenericCMethod;
6571                 } else {
6572                         if (!System_Reflection_MonoGenericMethod)
6573                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6574                         klass = System_Reflection_MonoGenericMethod;
6575                 }
6576                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6577                 gret->method.method = method;
6578                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6579                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6580                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6581         }
6582
6583         if (!refclass)
6584                 refclass = method->klass;
6585
6586         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6587         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6588                 if (!System_Reflection_MonoCMethod)
6589                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6590                 klass = System_Reflection_MonoCMethod;
6591         }
6592         else {
6593                 if (!System_Reflection_MonoMethod)
6594                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6595                 klass = System_Reflection_MonoMethod;
6596         }
6597         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6598         ret->method = method;
6599         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6600         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6601 }
6602
6603 /*
6604  * mono_method_clear_object:
6605  *
6606  *   Clear the cached reflection objects for the dynamic method METHOD.
6607  */
6608 void
6609 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6610 {
6611         MonoClass *klass;
6612         g_assert (method->dynamic);
6613
6614         klass = method->klass;
6615         while (klass) {
6616                 clear_cached_object (domain, method, klass);
6617                 klass = klass->parent;
6618         }
6619         /* Added by mono_param_get_objects () */
6620         clear_cached_object (domain, &(method->signature), NULL);
6621         klass = method->klass;
6622         while (klass) {
6623                 clear_cached_object (domain, &(method->signature), klass);
6624                 klass = klass->parent;
6625         }
6626 }
6627
6628 /*
6629  * mono_field_get_object:
6630  * @domain: an app domain
6631  * @klass: a type
6632  * @field: a field
6633  *
6634  * Return an System.Reflection.MonoField object representing the field @field
6635  * in class @klass.
6636  */
6637 MonoReflectionField*
6638 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6639 {
6640         MonoReflectionField *res;
6641         static MonoClass *monofield_klass;
6642
6643         CHECK_OBJECT (MonoReflectionField *, field, klass);
6644         if (!monofield_klass)
6645                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6646         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6647         res->klass = klass;
6648         res->field = field;
6649         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6650
6651         if (is_field_on_inst (field)) {
6652                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6653                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6654         } else {
6655                 if (field->type)
6656                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6657                 res->attrs = mono_field_get_flags (field);
6658         }
6659         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6660 }
6661
6662 /*
6663  * mono_property_get_object:
6664  * @domain: an app domain
6665  * @klass: a type
6666  * @property: a property
6667  *
6668  * Return an System.Reflection.MonoProperty object representing the property @property
6669  * in class @klass.
6670  */
6671 MonoReflectionProperty*
6672 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6673 {
6674         MonoReflectionProperty *res;
6675         static MonoClass *monoproperty_klass;
6676
6677         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6678         if (!monoproperty_klass)
6679                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6680         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6681         res->klass = klass;
6682         res->property = property;
6683         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6684 }
6685
6686 /*
6687  * mono_event_get_object:
6688  * @domain: an app domain
6689  * @klass: a type
6690  * @event: a event
6691  *
6692  * Return an System.Reflection.MonoEvent object representing the event @event
6693  * in class @klass.
6694  */
6695 MonoReflectionEvent*
6696 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6697 {
6698         MonoReflectionEvent *res;
6699         MonoReflectionMonoEvent *mono_event;
6700         static MonoClass *monoevent_klass;
6701
6702         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6703         if (!monoevent_klass)
6704                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6705         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6706         mono_event->klass = klass;
6707         mono_event->event = event;
6708         res = (MonoReflectionEvent*)mono_event;
6709         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6710 }
6711
6712 /**
6713  * mono_get_reflection_missing_object:
6714  * @domain: Domain where the object lives
6715  *
6716  * Returns the System.Reflection.Missing.Value singleton object
6717  * (of type System.Reflection.Missing).
6718  *
6719  * Used as the value for ParameterInfo.DefaultValue when Optional
6720  * is present
6721  */
6722 static MonoObject *
6723 mono_get_reflection_missing_object (MonoDomain *domain)
6724 {
6725         MonoObject *obj;
6726         static MonoClassField *missing_value_field = NULL;
6727         
6728         if (!missing_value_field) {
6729                 MonoClass *missing_klass;
6730                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6731                 mono_class_init (missing_klass);
6732                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6733                 g_assert (missing_value_field);
6734         }
6735         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6736         g_assert (obj);
6737         return obj;
6738 }
6739
6740 static MonoObject*
6741 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6742 {
6743         if (!*dbnull)
6744                 *dbnull = mono_get_dbnull_object (domain);
6745         return *dbnull;
6746 }
6747
6748 static MonoObject*
6749 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6750 {
6751         if (!*reflection_missing)
6752                 *reflection_missing = mono_get_reflection_missing_object (domain);
6753         return *reflection_missing;
6754 }
6755
6756 /*
6757  * mono_param_get_objects:
6758  * @domain: an app domain
6759  * @method: a method
6760  *
6761  * Return an System.Reflection.ParameterInfo array object representing the parameters
6762  * in the method @method.
6763  */
6764 MonoArray*
6765 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6766 {
6767         static MonoClass *System_Reflection_ParameterInfo;
6768         static MonoClass *System_Reflection_ParameterInfo_array;
6769         MonoError error;
6770         MonoArray *res = NULL;
6771         MonoReflectionMethod *member = NULL;
6772         MonoReflectionParameter *param = NULL;
6773         char **names, **blobs = NULL;
6774         guint32 *types = NULL;
6775         MonoType *type = NULL;
6776         MonoObject *dbnull = NULL;
6777         MonoObject *missing = NULL;
6778         MonoMarshalSpec **mspecs;
6779         MonoMethodSignature *sig;
6780         MonoVTable *pinfo_vtable;
6781         int i;
6782
6783         if (!System_Reflection_ParameterInfo_array) {
6784                 MonoClass *klass;
6785
6786                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6787                 mono_memory_barrier ();
6788                 System_Reflection_ParameterInfo = klass; 
6789         
6790                 klass = mono_array_class_get (klass, 1);
6791                 mono_memory_barrier ();
6792                 System_Reflection_ParameterInfo_array = klass;
6793         }
6794
6795         sig = mono_method_signature_checked (method, &error);
6796         if (!mono_error_ok (&error))
6797                 mono_error_raise_exception (&error);
6798
6799         if (!sig->param_count)
6800                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6801
6802         /* Note: the cache is based on the address of the signature into the method
6803          * since we already cache MethodInfos with the method as keys.
6804          */
6805         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6806
6807         member = mono_method_get_object (domain, method, refclass);
6808         names = g_new (char *, sig->param_count);
6809         mono_method_get_param_names (method, (const char **) names);
6810
6811         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6812         mono_method_get_marshal_info (method, mspecs);
6813
6814         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6815         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6816         for (i = 0; i < sig->param_count; ++i) {
6817                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6818                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6819                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6820                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6821                 param->PositionImpl = i;
6822                 param->AttrsImpl = sig->params [i]->attrs;
6823
6824                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6825                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6826                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6827                         else
6828                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6829                 } else {
6830
6831                         if (!blobs) {
6832                                 blobs = g_new0 (char *, sig->param_count);
6833                                 types = g_new0 (guint32, sig->param_count);
6834                                 get_default_param_value_blobs (method, blobs, types); 
6835                         }
6836
6837                         /* Build MonoType for the type from the Constant Table */
6838                         if (!type)
6839                                 type = g_new0 (MonoType, 1);
6840                         type->type = types [i];
6841                         type->data.klass = NULL;
6842                         if (types [i] == MONO_TYPE_CLASS)
6843                                 type->data.klass = mono_defaults.object_class;
6844                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6845                                 /* For enums, types [i] contains the base type */
6846
6847                                         type->type = MONO_TYPE_VALUETYPE;
6848                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6849                         } else
6850                                 type->data.klass = mono_class_from_mono_type (type);
6851
6852                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6853
6854                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6855                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6856                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6857                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6858                                 else
6859                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6860                         }
6861                         
6862                 }
6863
6864                 if (mspecs [i + 1])
6865                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6866                 
6867                 mono_array_setref (res, i, param);
6868         }
6869         g_free (names);
6870         g_free (blobs);
6871         g_free (types);
6872         g_free (type);
6873
6874         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6875                 if (mspecs [i])
6876                         mono_metadata_free_marshal_spec (mspecs [i]);
6877         g_free (mspecs);
6878         
6879         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6880 }
6881
6882 MonoArray*
6883 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6884 {
6885         return mono_param_get_objects_internal (domain, method, NULL);
6886 }
6887
6888 /*
6889  * mono_method_body_get_object:
6890  * @domain: an app domain
6891  * @method: a method
6892  *
6893  * Return an System.Reflection.MethodBody object representing the method @method.
6894  */
6895 MonoReflectionMethodBody*
6896 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6897 {
6898         static MonoClass *System_Reflection_MethodBody = NULL;
6899         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6900         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6901         MonoReflectionMethodBody *ret;
6902         MonoMethodHeader *header;
6903         MonoImage *image;
6904         guint32 method_rva, local_var_sig_token;
6905     char *ptr;
6906         unsigned char format, flags;
6907         int i;
6908
6909         /* for compatibility with .net */
6910     if (method->dynamic)
6911         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6912
6913         if (!System_Reflection_MethodBody)
6914                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6915         if (!System_Reflection_LocalVariableInfo)
6916                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6917         if (!System_Reflection_ExceptionHandlingClause)
6918                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6919
6920         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6921
6922         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6923                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6924             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6925             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6926                 return NULL;
6927
6928         image = method->klass->image;
6929         header = mono_method_get_header (method);
6930
6931         if (!image->dynamic) {
6932                 /* Obtain local vars signature token */
6933                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6934                 ptr = mono_image_rva_map (image, method_rva);
6935                 flags = *(const unsigned char *) ptr;
6936                 format = flags & METHOD_HEADER_FORMAT_MASK;
6937                 switch (format){
6938                 case METHOD_HEADER_TINY_FORMAT:
6939                         local_var_sig_token = 0;
6940                         break;
6941                 case METHOD_HEADER_FAT_FORMAT:
6942                         ptr += 2;
6943                         ptr += 2;
6944                         ptr += 4;
6945                         local_var_sig_token = read32 (ptr);
6946                         break;
6947                 default:
6948                         g_assert_not_reached ();
6949                 }
6950         } else
6951                 local_var_sig_token = 0; //FIXME
6952
6953         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6954
6955         ret->init_locals = header->init_locals;
6956         ret->max_stack = header->max_stack;
6957         ret->local_var_sig_token = local_var_sig_token;
6958         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6959         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6960
6961         /* Locals */
6962         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6963         for (i = 0; i < header->num_locals; ++i) {
6964                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6965                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6966                 info->is_pinned = header->locals [i]->pinned;
6967                 info->local_index = i;
6968                 mono_array_setref (ret->locals, i, info);
6969         }
6970
6971         /* Exceptions */
6972         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6973         for (i = 0; i < header->num_clauses; ++i) {
6974                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6975                 MonoExceptionClause *clause = &header->clauses [i];
6976
6977                 info->flags = clause->flags;
6978                 info->try_offset = clause->try_offset;
6979                 info->try_length = clause->try_len;
6980                 info->handler_offset = clause->handler_offset;
6981                 info->handler_length = clause->handler_len;
6982                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6983                         info->filter_offset = clause->data.filter_offset;
6984                 else if (clause->data.catch_class)
6985                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6986
6987                 mono_array_setref (ret->clauses, i, info);
6988         }
6989
6990         mono_metadata_free_mh (header);
6991         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6992         return ret;
6993 }
6994
6995 /**
6996  * mono_get_dbnull_object:
6997  * @domain: Domain where the object lives
6998  *
6999  * Returns the System.DBNull.Value singleton object
7000  *
7001  * Used as the value for ParameterInfo.DefaultValue 
7002  */
7003 MonoObject *
7004 mono_get_dbnull_object (MonoDomain *domain)
7005 {
7006         MonoObject *obj;
7007         static MonoClassField *dbnull_value_field = NULL;
7008         
7009         if (!dbnull_value_field) {
7010                 MonoClass *dbnull_klass;
7011                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7012                 mono_class_init (dbnull_klass);
7013                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7014                 g_assert (dbnull_value_field);
7015         }
7016         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7017         g_assert (obj);
7018         return obj;
7019 }
7020
7021 static void
7022 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7023 {
7024         guint32 param_index, i, lastp, crow = 0;
7025         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7026         gint32 idx;
7027
7028         MonoClass *klass = method->klass;
7029         MonoImage *image = klass->image;
7030         MonoMethodSignature *methodsig = mono_method_signature (method);
7031
7032         MonoTableInfo *constt;
7033         MonoTableInfo *methodt;
7034         MonoTableInfo *paramt;
7035
7036         if (!methodsig->param_count)
7037                 return;
7038
7039         mono_class_init (klass);
7040
7041         if (klass->image->dynamic) {
7042                 MonoReflectionMethodAux *aux;
7043                 if (method->is_inflated)
7044                         method = ((MonoMethodInflated*)method)->declaring;
7045                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7046                 if (aux && aux->param_defaults) {
7047                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7048                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7049                 }
7050                 return;
7051         }
7052
7053         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7054         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7055         constt = &image->tables [MONO_TABLE_CONSTANT];
7056
7057         idx = mono_method_get_index (method) - 1;
7058         g_assert (idx != -1);
7059
7060         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7061         if (idx + 1 < methodt->rows)
7062                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7063         else
7064                 lastp = paramt->rows + 1;
7065
7066         for (i = param_index; i < lastp; ++i) {
7067                 guint32 paramseq;
7068
7069                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7070                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7071
7072                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7073                         continue;
7074
7075                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7076                 if (!crow) {
7077                         continue;
7078                 }
7079         
7080                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7081                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7082                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7083         }
7084
7085         return;
7086 }
7087
7088 MonoObject *
7089 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7090 {
7091         void *retval;
7092         MonoClass *klass;
7093         MonoObject *object;
7094         MonoType *basetype = type;
7095
7096         if (!blob)
7097                 return NULL;
7098         
7099         klass = mono_class_from_mono_type (type);
7100         if (klass->valuetype) {
7101                 object = mono_object_new (domain, klass);
7102                 retval = ((gchar *) object + sizeof (MonoObject));
7103                 if (klass->enumtype)
7104                         basetype = mono_class_enum_basetype (klass);
7105         } else {
7106                 retval = &object;
7107         }
7108                         
7109         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7110                 return object;
7111         else
7112                 return NULL;
7113 }
7114
7115 static int
7116 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7117         int found_sep;
7118         char *s;
7119         gboolean quoted = FALSE;
7120
7121         memset (assembly, 0, sizeof (MonoAssemblyName));
7122         assembly->culture = "";
7123         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7124
7125         if (*p == '"') {
7126                 quoted = TRUE;
7127                 p++;
7128         }
7129         assembly->name = p;
7130         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7131                 p++;
7132         if (quoted) {
7133                 if (*p != '"')
7134                         return 1;
7135                 *p = 0;
7136                 p++;
7137         }
7138         if (*p != ',')
7139                 return 1;
7140         *p = 0;
7141         /* Remove trailing whitespace */
7142         s = p - 1;
7143         while (*s && g_ascii_isspace (*s))
7144                 *s-- = 0;
7145         p ++;
7146         while (g_ascii_isspace (*p))
7147                 p++;
7148         while (*p) {
7149                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7150                         p += 8;
7151                         assembly->major = strtoul (p, &s, 10);
7152                         if (s == p || *s != '.')
7153                                 return 1;
7154                         p = ++s;
7155                         assembly->minor = strtoul (p, &s, 10);
7156                         if (s == p || *s != '.')
7157                                 return 1;
7158                         p = ++s;
7159                         assembly->build = strtoul (p, &s, 10);
7160                         if (s == p || *s != '.')
7161                                 return 1;
7162                         p = ++s;
7163                         assembly->revision = strtoul (p, &s, 10);
7164                         if (s == p)
7165                                 return 1;
7166                         p = s;
7167                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7168                         p += 8;
7169                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7170                                 assembly->culture = "";
7171                                 p += 7;
7172                         } else {
7173                                 assembly->culture = p;
7174                                 while (*p && *p != ',') {
7175                                         p++;
7176                                 }
7177                         }
7178                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7179                         p += 15;
7180                         if (strncmp (p, "null", 4) == 0) {
7181                                 p += 4;
7182                         } else {
7183                                 int len;
7184                                 gchar *start = p;
7185                                 while (*p && *p != ',') {
7186                                         p++;
7187                                 }
7188                                 len = (p - start + 1);
7189                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7190                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7191                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7192                         }
7193                 } else {
7194                         while (*p && *p != ',')
7195                                 p++;
7196                 }
7197                 found_sep = 0;
7198                 while (g_ascii_isspace (*p) || *p == ',') {
7199                         *p++ = 0;
7200                         found_sep = 1;
7201                         continue;
7202                 }
7203                 /* failed */
7204                 if (!found_sep)
7205                         return 1;
7206         }
7207
7208         return 0;
7209 }
7210
7211 /*
7212  * mono_reflection_parse_type:
7213  * @name: type name
7214  *
7215  * Parse a type name as accepted by the GetType () method and output the info
7216  * extracted in the info structure.
7217  * the name param will be mangled, so, make a copy before passing it to this function.
7218  * The fields in info will be valid until the memory pointed to by name is valid.
7219  *
7220  * See also mono_type_get_name () below.
7221  *
7222  * Returns: 0 on parse error.
7223  */
7224 static int
7225 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7226                              MonoTypeNameParse *info)
7227 {
7228         char *start, *p, *w, *temp, *last_point, *startn;
7229         int in_modifiers = 0;
7230         int isbyref = 0, rank, arity = 0, i;
7231
7232         start = p = w = name;
7233
7234         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7235         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7236         info->name = info->name_space = NULL;
7237         info->nested = NULL;
7238         info->modifiers = NULL;
7239         info->type_arguments = NULL;
7240
7241         /* last_point separates the namespace from the name */
7242         last_point = NULL;
7243         /* Skips spaces */
7244         while (*p == ' ') p++, start++, w++, name++;
7245
7246         while (*p) {
7247                 switch (*p) {
7248                 case '+':
7249                         *p = 0; /* NULL terminate the name */
7250                         startn = p + 1;
7251                         info->nested = g_list_append (info->nested, startn);
7252                         /* we have parsed the nesting namespace + name */
7253                         if (info->name)
7254                                 break;
7255                         if (last_point) {
7256                                 info->name_space = start;
7257                                 *last_point = 0;
7258                                 info->name = last_point + 1;
7259                         } else {
7260                                 info->name_space = (char *)"";
7261                                 info->name = start;
7262                         }
7263                         break;
7264                 case '.':
7265                         last_point = p;
7266                         break;
7267                 case '\\':
7268                         ++p;
7269                         break;
7270                 case '&':
7271                 case '*':
7272                 case '[':
7273                 case ',':
7274                 case ']':
7275                         in_modifiers = 1;
7276                         break;
7277                 case '`':
7278                         ++p;
7279                         i = strtol (p, &temp, 10);
7280                         arity += i;
7281                         if (p == temp)
7282                                 return 0;
7283                         p = temp-1;
7284                         break;
7285                 default:
7286                         break;
7287                 }
7288                 if (in_modifiers)
7289                         break;
7290                 // *w++ = *p++;
7291                 p++;
7292         }
7293         
7294         if (!info->name) {
7295                 if (last_point) {
7296                         info->name_space = start;
7297                         *last_point = 0;
7298                         info->name = last_point + 1;
7299                 } else {
7300                         info->name_space = (char *)"";
7301                         info->name = start;
7302                 }
7303         }
7304         while (*p) {
7305                 switch (*p) {
7306                 case '&':
7307                         if (isbyref) /* only one level allowed by the spec */
7308                                 return 0;
7309                         isbyref = 1;
7310                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7311                         *p++ = 0;
7312                         break;
7313                 case '*':
7314                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7315                         *p++ = 0;
7316                         break;
7317                 case '[':
7318                         if (arity != 0) {
7319                                 *p++ = 0;
7320                                 info->type_arguments = g_ptr_array_new ();
7321                                 for (i = 0; i < arity; i++) {
7322                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7323                                         gboolean fqname = FALSE;
7324
7325                                         g_ptr_array_add (info->type_arguments, subinfo);
7326
7327                                         if (*p == '[') {
7328                                                 p++;
7329                                                 fqname = TRUE;
7330                                         }
7331
7332                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7333                                                 return 0;
7334
7335                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7336                                         if (fqname && (*p != ']')) {
7337                                                 char *aname;
7338
7339                                                 if (*p != ',')
7340                                                         return 0;
7341                                                 *p++ = 0;
7342
7343                                                 aname = p;
7344                                                 while (*p && (*p != ']'))
7345                                                         p++;
7346
7347                                                 if (*p != ']')
7348                                                         return 0;
7349
7350                                                 *p++ = 0;
7351                                                 while (*aname) {
7352                                                         if (g_ascii_isspace (*aname)) {
7353                                                                 ++aname;
7354                                                                 continue;
7355                                                         }
7356                                                         break;
7357                                                 }
7358                                                 if (!*aname ||
7359                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7360                                                         return 0;
7361                                         } else if (fqname && (*p == ']')) {
7362                                                 *p++ = 0;
7363                                         }
7364
7365                                         if (i + 1 < arity) {
7366                                                 if (*p != ',')
7367                                                         return 0;
7368                                         } else {
7369                                                 if (*p != ']')
7370                                                         return 0;
7371                                         }
7372                                         *p++ = 0;
7373                                 }
7374
7375                                 arity = 0;
7376                                 break;
7377                         }
7378                         rank = 1;
7379                         *p++ = 0;
7380                         while (*p) {
7381                                 if (*p == ']')
7382                                         break;
7383                                 if (*p == ',')
7384                                         rank++;
7385                                 else if (*p == '*') /* '*' means unknown lower bound */
7386                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7387                                 else
7388                                         return 0;
7389                                 ++p;
7390                         }
7391                         if (*p++ != ']')
7392                                 return 0;
7393                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7394                         break;
7395                 case ']':
7396                         if (is_recursed)
7397                                 goto end;
7398                         return 0;
7399                 case ',':
7400                         if (is_recursed)
7401                                 goto end;
7402                         *p++ = 0;
7403                         while (*p) {
7404                                 if (g_ascii_isspace (*p)) {
7405                                         ++p;
7406                                         continue;
7407                                 }
7408                                 break;
7409                         }
7410                         if (!*p)
7411                                 return 0; /* missing assembly name */
7412                         if (!assembly_name_to_aname (&info->assembly, p))
7413                                 return 0;
7414                         break;
7415                 default:
7416                         return 0;
7417                 }
7418                 if (info->assembly.name)
7419                         break;
7420         }
7421         // *w = 0; /* terminate class name */
7422  end:
7423         if (!info->name || !*info->name)
7424                 return 0;
7425         if (endptr)
7426                 *endptr = p;
7427         /* add other consistency checks */
7428         return 1;
7429 }
7430
7431 int
7432 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7433 {
7434         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7435 }
7436
7437 static MonoType*
7438 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7439 {
7440         gboolean type_resolve = FALSE;
7441         MonoType *type;
7442         MonoImage *rootimage = image;
7443
7444         if (info->assembly.name) {
7445                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7446                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7447                         /* 
7448                          * This could happen in the AOT compiler case when the search hook is not
7449                          * installed.
7450                          */
7451                         assembly = image->assembly;
7452                 if (!assembly) {
7453                         /* then we must load the assembly ourselve - see #60439 */
7454                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7455                         if (!assembly)
7456                                 return NULL;
7457                 }
7458                 image = assembly->image;
7459         } else if (!image) {
7460                 image = mono_defaults.corlib;
7461         }
7462
7463         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7465                 image = mono_defaults.corlib;
7466                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7467         }
7468
7469         return type;
7470 }
7471
7472 static MonoType*
7473 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7474 {
7475         MonoClass *klass;
7476         GList *mod;
7477         int modval;
7478         gboolean bounded = FALSE;
7479         
7480         if (!image)
7481                 image = mono_defaults.corlib;
7482
7483         if (ignorecase)
7484                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7485         else
7486                 klass = mono_class_from_name (image, info->name_space, info->name);
7487         if (!klass)
7488                 return NULL;
7489         for (mod = info->nested; mod; mod = mod->next) {
7490                 gpointer iter = NULL;
7491                 MonoClass *parent;
7492
7493                 parent = klass;
7494                 mono_class_init (parent);
7495
7496                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7497                         if (ignorecase) {
7498                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7499                                         break;
7500                         } else {
7501                                 if (strcmp (klass->name, mod->data) == 0)
7502                                         break;
7503                         }
7504                 }
7505                 if (!klass)
7506                         break;
7507         }
7508         if (!klass)
7509                 return NULL;
7510
7511         if (info->type_arguments) {
7512                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7513                 MonoReflectionType *the_type;
7514                 MonoType *instance;
7515                 int i;
7516
7517                 for (i = 0; i < info->type_arguments->len; i++) {
7518                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7519
7520                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7521                         if (!type_args [i]) {
7522                                 g_free (type_args);
7523                                 return NULL;
7524                         }
7525                 }
7526
7527                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7528
7529                 instance = mono_reflection_bind_generic_parameters (
7530                         the_type, info->type_arguments->len, type_args);
7531
7532                 g_free (type_args);
7533                 if (!instance)
7534                         return NULL;
7535
7536                 klass = mono_class_from_mono_type (instance);
7537         }
7538
7539         for (mod = info->modifiers; mod; mod = mod->next) {
7540                 modval = GPOINTER_TO_UINT (mod->data);
7541                 if (!modval) { /* byref: must be last modifier */
7542                         return &klass->this_arg;
7543                 } else if (modval == -1) {
7544                         klass = mono_ptr_class_get (&klass->byval_arg);
7545                 } else if (modval == -2) {
7546                         bounded = TRUE;
7547                 } else { /* array rank */
7548                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7549                 }
7550         }
7551
7552         return &klass->byval_arg;
7553 }
7554
7555 /*
7556  * mono_reflection_get_type:
7557  * @image: a metadata context
7558  * @info: type description structure
7559  * @ignorecase: flag for case-insensitive string compares
7560  * @type_resolve: whenever type resolve was already tried
7561  *
7562  * Build a MonoType from the type description in @info.
7563  * 
7564  */
7565
7566 MonoType*
7567 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7568         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7569 }
7570
7571 static MonoType*
7572 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7573 {
7574         MonoReflectionAssemblyBuilder *abuilder;
7575         MonoType *type;
7576         int i;
7577
7578         g_assert (assembly->dynamic);
7579         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7580
7581         /* Enumerate all modules */
7582
7583         type = NULL;
7584         if (abuilder->modules) {
7585                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7586                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7587                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7588                         if (type)
7589                                 break;
7590                 }
7591         }
7592
7593         if (!type && abuilder->loaded_modules) {
7594                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7595                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7596                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7597                         if (type)
7598                                 break;
7599                 }
7600         }
7601
7602         return type;
7603 }
7604         
7605 MonoType*
7606 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7607 {
7608         MonoType *type;
7609         MonoReflectionAssembly *assembly;
7610         GString *fullName;
7611         GList *mod;
7612
7613         if (image && image->dynamic)
7614                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7615         else
7616                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7617         if (type)
7618                 return type;
7619         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7620                 return NULL;
7621
7622         if (type_resolve) {
7623                 if (*type_resolve) 
7624                         return NULL;
7625                 else
7626                         *type_resolve = TRUE;
7627         }
7628         
7629         /* Reconstruct the type name */
7630         fullName = g_string_new ("");
7631         if (info->name_space && (info->name_space [0] != '\0'))
7632                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7633         else
7634                 g_string_printf (fullName, "%s", info->name);
7635         for (mod = info->nested; mod; mod = mod->next)
7636                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7637
7638         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7639         if (assembly) {
7640                 if (assembly->assembly->dynamic)
7641                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7642                 else
7643                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7644                                                                                                           info, ignorecase);
7645         }
7646         g_string_free (fullName, TRUE);
7647         return type;
7648 }
7649
7650 void
7651 mono_reflection_free_type_info (MonoTypeNameParse *info)
7652 {
7653         g_list_free (info->modifiers);
7654         g_list_free (info->nested);
7655
7656         if (info->type_arguments) {
7657                 int i;
7658
7659                 for (i = 0; i < info->type_arguments->len; i++) {
7660                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7661
7662                         mono_reflection_free_type_info (subinfo);
7663                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7664                         g_free (subinfo);
7665                 }
7666
7667                 g_ptr_array_free (info->type_arguments, TRUE);
7668         }
7669 }
7670
7671 /*
7672  * mono_reflection_type_from_name:
7673  * @name: type name.
7674  * @image: a metadata context (can be NULL).
7675  *
7676  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7677  * it defaults to get the type from @image or, if @image is NULL or loading
7678  * from it fails, uses corlib.
7679  * 
7680  */
7681 MonoType*
7682 mono_reflection_type_from_name (char *name, MonoImage *image)
7683 {
7684         MonoType *type = NULL;
7685         MonoTypeNameParse info;
7686         char *tmp;
7687
7688         /* Make a copy since parse_type modifies its argument */
7689         tmp = g_strdup (name);
7690         
7691         /*g_print ("requested type %s\n", str);*/
7692         if (mono_reflection_parse_type (tmp, &info)) {
7693                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7694         }
7695
7696         g_free (tmp);
7697         mono_reflection_free_type_info (&info);
7698         return type;
7699 }
7700
7701 /*
7702  * mono_reflection_get_token:
7703  *
7704  *   Return the metadata token of OBJ which should be an object
7705  * representing a metadata element.
7706  */
7707 guint32
7708 mono_reflection_get_token (MonoObject *obj)
7709 {
7710         MonoClass *klass;
7711         guint32 token = 0;
7712
7713         klass = obj->vtable->klass;
7714
7715         if (strcmp (klass->name, "MethodBuilder") == 0) {
7716                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7717
7718                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7719         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7720                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7721
7722                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7723         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7724                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7725
7726                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7727         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7728                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7729                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7730         } else if (strcmp (klass->name, "MonoType") == 0) {
7731                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7732                 MonoClass *mc = mono_class_from_mono_type (type);
7733                 if (!mono_class_init (mc))
7734                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7735
7736                 token = mc->type_token;
7737         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7738                    strcmp (klass->name, "MonoMethod") == 0 ||
7739                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7740                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7741                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7742                 if (m->method->is_inflated) {
7743                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7744                         return inflated->declaring->token;
7745                 } else {
7746                         token = m->method->token;
7747                 }
7748         } else if (strcmp (klass->name, "MonoField") == 0) {
7749                 MonoReflectionField *f = (MonoReflectionField*)obj;
7750
7751                 if (is_field_on_inst (f->field)) {
7752                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7753                         int field_index = f->field - dgclass->fields;
7754                         MonoObject *obj;
7755
7756                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7757                         obj = dgclass->field_objects [field_index];
7758                         return mono_reflection_get_token (obj);
7759                 }
7760                 token = mono_class_get_field_token (f->field);
7761         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7762                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7763
7764                 token = mono_class_get_property_token (p->property);
7765         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7766                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7767
7768                 token = mono_class_get_event_token (p->event);
7769         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7770                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7771                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7772                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7773
7774                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7775         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7776                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7777
7778                 token = m->token;
7779         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7780                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7781         } else {
7782                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7783                 MonoException *ex = mono_get_exception_not_implemented (msg);
7784                 g_free (msg);
7785                 mono_raise_exception (ex);
7786         }
7787
7788         return token;
7789 }
7790
7791 static void*
7792 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7793 {
7794         int slen, type = t->type;
7795         MonoClass *tklass = t->data.klass;
7796
7797 handle_enum:
7798         switch (type) {
7799         case MONO_TYPE_U1:
7800         case MONO_TYPE_I1:
7801         case MONO_TYPE_BOOLEAN: {
7802                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7803                 *bval = *p;
7804                 *end = p + 1;
7805                 return bval;
7806         }
7807         case MONO_TYPE_CHAR:
7808         case MONO_TYPE_U2:
7809         case MONO_TYPE_I2: {
7810                 guint16 *val = g_malloc (sizeof (guint16));
7811                 *val = read16 (p);
7812                 *end = p + 2;
7813                 return val;
7814         }
7815 #if SIZEOF_VOID_P == 4
7816         case MONO_TYPE_U:
7817         case MONO_TYPE_I:
7818 #endif
7819         case MONO_TYPE_R4:
7820         case MONO_TYPE_U4:
7821         case MONO_TYPE_I4: {
7822                 guint32 *val = g_malloc (sizeof (guint32));
7823                 *val = read32 (p);
7824                 *end = p + 4;
7825                 return val;
7826         }
7827 #if SIZEOF_VOID_P == 8
7828         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7829         case MONO_TYPE_I:
7830 #endif
7831         case MONO_TYPE_U8:
7832         case MONO_TYPE_I8: {
7833                 guint64 *val = g_malloc (sizeof (guint64));
7834                 *val = read64 (p);
7835                 *end = p + 8;
7836                 return val;
7837         }
7838         case MONO_TYPE_R8: {
7839                 double *val = g_malloc (sizeof (double));
7840                 readr8 (p, val);
7841                 *end = p + 8;
7842                 return val;
7843         }
7844         case MONO_TYPE_VALUETYPE:
7845                 if (t->data.klass->enumtype) {
7846                         type = mono_class_enum_basetype (t->data.klass)->type;
7847                         goto handle_enum;
7848                 } else {
7849                         MonoClass *k =  t->data.klass;
7850                         
7851                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7852                                 guint64 *val = g_malloc (sizeof (guint64));
7853                                 *val = read64 (p);
7854                                 *end = p + 8;
7855                                 return val;
7856                         }
7857                 }
7858                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7859                 break;
7860                 
7861         case MONO_TYPE_STRING:
7862                 if (*p == (char)0xFF) {
7863                         *end = p + 1;
7864                         return NULL;
7865                 }
7866                 slen = mono_metadata_decode_value (p, &p);
7867                 *end = p + slen;
7868                 return mono_string_new_len (mono_domain_get (), p, slen);
7869         case MONO_TYPE_CLASS: {
7870                 char *n;
7871                 MonoType *t;
7872                 if (*p == (char)0xFF) {
7873                         *end = p + 1;
7874                         return NULL;
7875                 }
7876 handle_type:
7877                 slen = mono_metadata_decode_value (p, &p);
7878                 n = g_memdup (p, slen + 1);
7879                 n [slen] = 0;
7880                 t = mono_reflection_type_from_name (n, image);
7881                 if (!t)
7882                         g_warning ("Cannot load type '%s'", n);
7883                 g_free (n);
7884                 *end = p + slen;
7885                 if (t)
7886                         return mono_type_get_object (mono_domain_get (), t);
7887                 else
7888                         return NULL;
7889         }
7890         case MONO_TYPE_OBJECT: {
7891                 char subt = *p++;
7892                 MonoObject *obj;
7893                 MonoClass *subc = NULL;
7894                 void *val;
7895
7896                 if (subt == 0x50) {
7897                         goto handle_type;
7898                 } else if (subt == 0x0E) {
7899                         type = MONO_TYPE_STRING;
7900                         goto handle_enum;
7901                 } else if (subt == 0x1D) {
7902                         MonoType simple_type = {{0}};
7903                         int etype = *p;
7904                         p ++;
7905
7906                         type = MONO_TYPE_SZARRAY;
7907                         if (etype == 0x50) {
7908                                 tklass = mono_defaults.systemtype_class;
7909                         } else {
7910                                 if (etype == 0x51)
7911                                         /* See Partition II, Appendix B3 */
7912                                         etype = MONO_TYPE_OBJECT;
7913                                 simple_type.type = etype;
7914                                 tklass = mono_class_from_mono_type (&simple_type);
7915                         }
7916                         goto handle_enum;
7917                 } else if (subt == 0x55) {
7918                         char *n;
7919                         MonoType *t;
7920                         slen = mono_metadata_decode_value (p, &p);
7921                         n = g_memdup (p, slen + 1);
7922                         n [slen] = 0;
7923                         t = mono_reflection_type_from_name (n, image);
7924                         if (!t)
7925                                 g_error ("Cannot load type '%s'", n);
7926                         g_free (n);
7927                         p += slen;
7928                         subc = mono_class_from_mono_type (t);
7929                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7930                         MonoType simple_type = {{0}};
7931                         simple_type.type = subt;
7932                         subc = mono_class_from_mono_type (&simple_type);
7933                 } else {
7934                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7935                 }
7936                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7937                 obj = mono_object_new (mono_domain_get (), subc);
7938                 g_assert (!subc->has_references);
7939                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7940                 g_free (val);
7941                 return obj;
7942         }
7943         case MONO_TYPE_SZARRAY: {
7944                 MonoArray *arr;
7945                 guint32 i, alen, basetype;
7946                 alen = read32 (p);
7947                 p += 4;
7948                 if (alen == 0xffffffff) {
7949                         *end = p;
7950                         return NULL;
7951                 }
7952                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7953                 basetype = tklass->byval_arg.type;
7954                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7955                         basetype = mono_class_enum_basetype (tklass)->type;
7956                 switch (basetype)
7957                 {
7958                         case MONO_TYPE_U1:
7959                         case MONO_TYPE_I1:
7960                         case MONO_TYPE_BOOLEAN:
7961                                 for (i = 0; i < alen; i++) {
7962                                         MonoBoolean val = *p++;
7963                                         mono_array_set (arr, MonoBoolean, i, val);
7964                                 }
7965                                 break;
7966                         case MONO_TYPE_CHAR:
7967                         case MONO_TYPE_U2:
7968                         case MONO_TYPE_I2:
7969                                 for (i = 0; i < alen; i++) {
7970                                         guint16 val = read16 (p);
7971                                         mono_array_set (arr, guint16, i, val);
7972                                         p += 2;
7973                                 }
7974                                 break;
7975                         case MONO_TYPE_R4:
7976                         case MONO_TYPE_U4:
7977                         case MONO_TYPE_I4:
7978                                 for (i = 0; i < alen; i++) {
7979                                         guint32 val = read32 (p);
7980                                         mono_array_set (arr, guint32, i, val);
7981                                         p += 4;
7982                                 }
7983                                 break;
7984                         case MONO_TYPE_R8:
7985                                 for (i = 0; i < alen; i++) {
7986                                         double val;
7987                                         readr8 (p, &val);
7988                                         mono_array_set (arr, double, i, val);
7989                                         p += 8;
7990                                 }
7991                                 break;
7992                         case MONO_TYPE_U8:
7993                         case MONO_TYPE_I8:
7994                                 for (i = 0; i < alen; i++) {
7995                                         guint64 val = read64 (p);
7996                                         mono_array_set (arr, guint64, i, val);
7997                                         p += 8;
7998                                 }
7999                                 break;
8000                         case MONO_TYPE_CLASS:
8001                         case MONO_TYPE_OBJECT:
8002                         case MONO_TYPE_STRING:
8003                                 for (i = 0; i < alen; i++) {
8004                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8005                                         mono_array_setref (arr, i, item);
8006                                 }
8007                                 break;
8008                         default:
8009                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8010                 }
8011                 *end=p;
8012                 return arr;
8013         }
8014         default:
8015                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8016         }
8017         return NULL;
8018 }
8019
8020 static MonoObject*
8021 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8022 {
8023         static MonoClass *klass;
8024         static MonoMethod *ctor;
8025         MonoObject *retval;
8026         void *params [2], *unboxed;
8027
8028         if (!klass)
8029                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8030         if (!ctor)
8031                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8032         
8033         params [0] = mono_type_get_object (mono_domain_get (), t);
8034         params [1] = val;
8035         retval = mono_object_new (mono_domain_get (), klass);
8036         unboxed = mono_object_unbox (retval);
8037         mono_runtime_invoke (ctor, unboxed, params, NULL);
8038
8039         return retval;
8040 }
8041
8042 static MonoObject*
8043 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8044 {
8045         static MonoClass *klass;
8046         static MonoMethod *ctor;
8047         MonoObject *retval;
8048         void *unboxed, *params [2];
8049
8050         if (!klass)
8051                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8052         if (!ctor)
8053                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8054
8055         params [0] = minfo;
8056         params [1] = typedarg;
8057         retval = mono_object_new (mono_domain_get (), klass);
8058         unboxed = mono_object_unbox (retval);
8059         mono_runtime_invoke (ctor, unboxed, params, NULL);
8060
8061         return retval;
8062 }
8063
8064 static gboolean
8065 type_is_reference (MonoType *type)
8066 {
8067         switch (type->type) {
8068         case MONO_TYPE_BOOLEAN:
8069         case MONO_TYPE_CHAR:
8070         case MONO_TYPE_U:
8071         case MONO_TYPE_I:
8072         case MONO_TYPE_U1:
8073         case MONO_TYPE_I1:
8074         case MONO_TYPE_U2:
8075         case MONO_TYPE_I2:
8076         case MONO_TYPE_U4:
8077         case MONO_TYPE_I4:
8078         case MONO_TYPE_U8:
8079         case MONO_TYPE_I8:
8080         case MONO_TYPE_R8:
8081         case MONO_TYPE_R4:
8082         case MONO_TYPE_VALUETYPE:
8083                 return FALSE;
8084         default:
8085                 return TRUE;
8086         }
8087 }
8088
8089 static void
8090 free_param_data (MonoMethodSignature *sig, void **params) {
8091         int i;
8092         for (i = 0; i < sig->param_count; ++i) {
8093                 if (!type_is_reference (sig->params [i]))
8094                         g_free (params [i]);
8095         }
8096 }
8097
8098 /*
8099  * Find the field index in the metadata FieldDef table.
8100  */
8101 static guint32
8102 find_field_index (MonoClass *klass, MonoClassField *field) {
8103         int i;
8104
8105         for (i = 0; i < klass->field.count; ++i) {
8106                 if (field == &klass->fields [i])
8107                         return klass->field.first + 1 + i;
8108         }
8109         return 0;
8110 }
8111
8112 /*
8113  * Find the property index in the metadata Property table.
8114  */
8115 static guint32
8116 find_property_index (MonoClass *klass, MonoProperty *property) {
8117         int i;
8118
8119         for (i = 0; i < klass->ext->property.count; ++i) {
8120                 if (property == &klass->ext->properties [i])
8121                         return klass->ext->property.first + 1 + i;
8122         }
8123         return 0;
8124 }
8125
8126 /*
8127  * Find the event index in the metadata Event table.
8128  */
8129 static guint32
8130 find_event_index (MonoClass *klass, MonoEvent *event) {
8131         int i;
8132
8133         for (i = 0; i < klass->ext->event.count; ++i) {
8134                 if (event == &klass->ext->events [i])
8135                         return klass->ext->event.first + 1 + i;
8136         }
8137         return 0;
8138 }
8139
8140 static MonoObject*
8141 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8142 {
8143         const char *p = (const char*)data;
8144         const char *named;
8145         guint32 i, j, num_named;
8146         MonoObject *attr;
8147         void *params_buf [32];
8148         void **params;
8149         MonoMethodSignature *sig;
8150
8151         mono_error_init (error);
8152
8153         mono_class_init (method->klass);
8154
8155         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8156                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8157                 return NULL;
8158         }
8159
8160         if (len == 0) {
8161                 attr = mono_object_new (mono_domain_get (), method->klass);
8162                 mono_runtime_invoke (method, attr, NULL, NULL);
8163                 return attr;
8164         }
8165
8166         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8167                 return NULL;
8168
8169         /*g_print ("got attr %s\n", method->klass->name);*/
8170
8171         sig = mono_method_signature (method);
8172         if (sig->param_count < 32)
8173                 params = params_buf;
8174         else
8175                 /* Allocate using GC so it gets GC tracking */
8176                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8177
8178         /* skip prolog */
8179         p += 2;
8180         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8181                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8182         }
8183
8184         named = p;
8185         attr = mono_object_new (mono_domain_get (), method->klass);
8186         mono_runtime_invoke (method, attr, params, NULL);
8187         free_param_data (method->signature, params);
8188         num_named = read16 (named);
8189         named += 2;
8190         for (j = 0; j < num_named; j++) {
8191                 gint name_len;
8192                 char *name, named_type, data_type;
8193                 named_type = *named++;
8194                 data_type = *named++; /* type of data */
8195                 if (data_type == MONO_TYPE_SZARRAY)
8196                         data_type = *named++;
8197                 if (data_type == MONO_TYPE_ENUM) {
8198                         gint type_len;
8199                         char *type_name;
8200                         type_len = mono_metadata_decode_blob_size (named, &named);
8201                         type_name = g_malloc (type_len + 1);
8202                         memcpy (type_name, named, type_len);
8203                         type_name [type_len] = 0;
8204                         named += type_len;
8205                         /* FIXME: lookup the type and check type consistency */
8206                         g_free (type_name);
8207                 }
8208                 name_len = mono_metadata_decode_blob_size (named, &named);
8209                 name = g_malloc (name_len + 1);
8210                 memcpy (name, named, name_len);
8211                 name [name_len] = 0;
8212                 named += name_len;
8213                 if (named_type == 0x53) {
8214                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8215                         void *val = load_cattr_value (image, field->type, named, &named);
8216                         mono_field_set_value (attr, field, val);
8217                         if (!type_is_reference (field->type))
8218                                 g_free (val);
8219                 } else if (named_type == 0x54) {
8220                         MonoProperty *prop;
8221                         void *pparams [1];
8222                         MonoType *prop_type;
8223
8224                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8225                         /* can we have more that 1 arg in a custom attr named property? */
8226                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8227                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8228                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8229                         mono_property_set_value (prop, attr, pparams, NULL);
8230                         if (!type_is_reference (prop_type))
8231                                 g_free (pparams [0]);
8232                 }
8233                 g_free (name);
8234         }
8235
8236         if (params != params_buf)
8237                 mono_gc_free_fixed (params);
8238
8239         return attr;
8240 }
8241         
8242 /*
8243  * mono_reflection_create_custom_attr_data_args:
8244  *
8245  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8246  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8247  * NAMED_ARG_INFO will contain information about the named arguments.
8248  */
8249 void
8250 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)
8251 {
8252         MonoArray *typedargs, *namedargs;
8253         MonoClass *attrklass;
8254         MonoDomain *domain;
8255         const char *p = (const char*)data;
8256         const char *named;
8257         guint32 i, j, num_named;
8258         CattrNamedArg *arginfo = NULL;
8259
8260         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8261                 return;
8262
8263         mono_class_init (method->klass);
8264
8265         *typed_args = NULL;
8266         *named_args = NULL;
8267         *named_arg_info = NULL;
8268         
8269         domain = mono_domain_get ();
8270
8271         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8272                 return;
8273
8274         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8275         
8276         /* skip prolog */
8277         p += 2;
8278         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8279                 MonoObject *obj;
8280                 void *val;
8281
8282                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8283                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8284                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8285                 mono_array_setref (typedargs, i, obj);
8286
8287                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8288                         g_free (val);
8289         }
8290
8291         named = p;
8292         num_named = read16 (named);
8293         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8294         named += 2;
8295         attrklass = method->klass;
8296
8297         arginfo = g_new0 (CattrNamedArg, num_named);
8298         *named_arg_info = arginfo;
8299
8300         for (j = 0; j < num_named; j++) {
8301                 gint name_len;
8302                 char *name, named_type, data_type;
8303                 named_type = *named++;
8304                 data_type = *named++; /* type of data */
8305                 if (data_type == MONO_TYPE_SZARRAY)
8306                         data_type = *named++;
8307                 if (data_type == MONO_TYPE_ENUM) {
8308                         gint type_len;
8309                         char *type_name;
8310                         type_len = mono_metadata_decode_blob_size (named, &named);
8311                         type_name = g_malloc (type_len + 1);
8312                         memcpy (type_name, named, type_len);
8313                         type_name [type_len] = 0;
8314                         named += type_len;
8315                         /* FIXME: lookup the type and check type consistency */
8316                         g_free (type_name);
8317                 }
8318                 name_len = mono_metadata_decode_blob_size (named, &named);
8319                 name = g_malloc (name_len + 1);
8320                 memcpy (name, named, name_len);
8321                 name [name_len] = 0;
8322                 named += name_len;
8323                 if (named_type == 0x53) {
8324                         MonoObject *obj;
8325                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8326                         void *val;
8327
8328                         arginfo [j].type = field->type;
8329                         arginfo [j].field = field;
8330
8331                         val = load_cattr_value (image, field->type, named, &named);
8332                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8333                         mono_array_setref (namedargs, j, obj);
8334                         if (!type_is_reference (field->type))
8335                                 g_free (val);
8336                 } else if (named_type == 0x54) {
8337                         MonoObject *obj;
8338                         MonoType *prop_type;
8339                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8340                         void *val;
8341
8342                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8343                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8344
8345                         arginfo [j].type = prop_type;
8346                         arginfo [j].prop = prop;
8347
8348                         val = load_cattr_value (image, prop_type, named, &named);
8349                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8350                         mono_array_setref (namedargs, j, obj);
8351                         if (!type_is_reference (prop_type))
8352                                 g_free (val);
8353                 }
8354                 g_free (name);
8355         }
8356
8357         *typed_args = typedargs;
8358         *named_args = namedargs;
8359 }
8360
8361 void
8362 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8363 {
8364         MonoDomain *domain;
8365         MonoArray *typedargs, *namedargs;
8366         MonoImage *image;
8367         MonoMethod *method;
8368         CattrNamedArg *arginfo;
8369         int i;
8370
8371         *ctor_args = NULL;
8372         *named_args = NULL;
8373
8374         if (len == 0)
8375                 return;
8376
8377         image = assembly->assembly->image;
8378         method = ref_method->method;
8379         domain = mono_object_domain (ref_method);
8380
8381         if (!mono_class_init (method->klass))
8382                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8383
8384         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8385         if (mono_loader_get_last_error ())
8386                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8387
8388         if (!typedargs || !namedargs)
8389                 return;
8390
8391         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8392                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8393                 MonoObject *typedarg;
8394
8395                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8396                 mono_array_setref (typedargs, i, typedarg);
8397         }
8398
8399         for (i = 0; i < mono_array_length (namedargs); ++i) {
8400                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8401                 MonoObject *typedarg, *namedarg, *minfo;
8402
8403                 if (arginfo [i].prop)
8404                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8405                 else
8406                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8407
8408                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8409                 namedarg = create_cattr_named_arg (minfo, typedarg);
8410
8411                 mono_array_setref (namedargs, i, namedarg);
8412         }
8413
8414         *ctor_args = typedargs;
8415         *named_args = namedargs;
8416 }
8417
8418 static MonoObject*
8419 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8420 {
8421         static MonoMethod *ctor;
8422         MonoDomain *domain;
8423         MonoObject *attr;
8424         void *params [4];
8425
8426         g_assert (image->assembly);
8427
8428         if (!ctor)
8429                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8430
8431         domain = mono_domain_get ();
8432         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8433         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8434         params [1] = mono_assembly_get_object (domain, image->assembly);
8435         params [2] = (gpointer)&cattr->data;
8436         params [3] = &cattr->data_size;
8437         mono_runtime_invoke (ctor, attr, params, NULL);
8438         return attr;
8439 }
8440
8441 static MonoArray*
8442 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8443 {
8444         MonoArray *result;
8445         MonoObject *attr;
8446         int i, n;
8447
8448         mono_error_init (error);
8449
8450         n = 0;
8451         for (i = 0; i < cinfo->num_attrs; ++i) {
8452                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8453                         n ++;
8454         }
8455
8456         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8457         n = 0;
8458         for (i = 0; i < cinfo->num_attrs; ++i) {
8459                 if (!cinfo->attrs [i].ctor)
8460                         /* The cattr type is not finished yet */
8461                         /* We should include the type name but cinfo doesn't contain it */
8462                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8463                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8464                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8465                         if (!mono_error_ok (error))
8466                                 return result;
8467                         mono_array_setref (result, n, attr);
8468                         n ++;
8469                 }
8470         }
8471         return result;
8472 }
8473
8474 MonoArray*
8475 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8476 {
8477         MonoError error;
8478
8479         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8480 }
8481
8482 static MonoArray*
8483 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8484 {
8485         MonoArray *result;
8486         MonoObject *attr;
8487         int i;
8488         
8489         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8490         for (i = 0; i < cinfo->num_attrs; ++i) {
8491                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8492                 mono_array_setref (result, i, attr);
8493         }
8494         return result;
8495 }
8496
8497 /**
8498  * mono_custom_attrs_from_index:
8499  *
8500  * Returns: NULL if no attributes are found or if a loading error occurs.
8501  */
8502 MonoCustomAttrInfo*
8503 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8504 {
8505         guint32 mtoken, i, len;
8506         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8507         MonoTableInfo *ca;
8508         MonoCustomAttrInfo *ainfo;
8509         GList *tmp, *list = NULL;
8510         const char *data;
8511
8512         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8513
8514         i = mono_metadata_custom_attrs_from_index (image, idx);
8515         if (!i)
8516                 return NULL;
8517         i --;
8518         while (i < ca->rows) {
8519                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8520                         break;
8521                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8522                 ++i;
8523         }
8524         len = g_list_length (list);
8525         if (!len)
8526                 return NULL;
8527         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8528         ainfo->num_attrs = len;
8529         ainfo->image = image;
8530         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8531                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8532                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8533                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8534                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8535                         mtoken |= MONO_TOKEN_METHOD_DEF;
8536                         break;
8537                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8538                         mtoken |= MONO_TOKEN_MEMBER_REF;
8539                         break;
8540                 default:
8541                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8542                         break;
8543                 }
8544                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8545                 if (!ainfo->attrs [i].ctor) {
8546                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8547                         g_list_free (list);
8548                         g_free (ainfo);
8549                         return NULL;
8550                 }
8551
8552                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8553                         /*FIXME raising an exception here doesn't make any sense*/
8554                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8555                         g_list_free (list);
8556                         g_free (ainfo);
8557                         return NULL;
8558                 }
8559                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8560                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8561                 ainfo->attrs [i].data = (guchar*)data;
8562         }
8563         g_list_free (list);
8564
8565         return ainfo;
8566 }
8567
8568 MonoCustomAttrInfo*
8569 mono_custom_attrs_from_method (MonoMethod *method)
8570 {
8571         guint32 idx;
8572
8573         /*
8574          * An instantiated method has the same cattrs as the generic method definition.
8575          *
8576          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8577          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8578          */
8579         if (method->is_inflated)
8580                 method = ((MonoMethodInflated *) method)->declaring;
8581         
8582         if (method->dynamic || method->klass->image->dynamic)
8583                 return lookup_custom_attr (method->klass->image, method);
8584
8585         if (!method->token)
8586                 /* Synthetic methods */
8587                 return NULL;
8588
8589         idx = mono_method_get_index (method);
8590         idx <<= MONO_CUSTOM_ATTR_BITS;
8591         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8592         return mono_custom_attrs_from_index (method->klass->image, idx);
8593 }
8594
8595 MonoCustomAttrInfo*
8596 mono_custom_attrs_from_class (MonoClass *klass)
8597 {
8598         guint32 idx;
8599
8600         if (klass->generic_class)
8601                 klass = klass->generic_class->container_class;
8602
8603         if (klass->image->dynamic)
8604                 return lookup_custom_attr (klass->image, klass);
8605
8606         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8607                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8608                 idx <<= MONO_CUSTOM_ATTR_BITS;
8609                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8610         } else {
8611                 idx = mono_metadata_token_index (klass->type_token);
8612                 idx <<= MONO_CUSTOM_ATTR_BITS;
8613                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8614         }
8615         return mono_custom_attrs_from_index (klass->image, idx);
8616 }
8617
8618 MonoCustomAttrInfo*
8619 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8620 {
8621         guint32 idx;
8622         
8623         if (assembly->image->dynamic)
8624                 return lookup_custom_attr (assembly->image, assembly);
8625         idx = 1; /* there is only one assembly */
8626         idx <<= MONO_CUSTOM_ATTR_BITS;
8627         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8628         return mono_custom_attrs_from_index (assembly->image, idx);
8629 }
8630
8631 static MonoCustomAttrInfo*
8632 mono_custom_attrs_from_module (MonoImage *image)
8633 {
8634         guint32 idx;
8635         
8636         if (image->dynamic)
8637                 return lookup_custom_attr (image, image);
8638         idx = 1; /* there is only one module */
8639         idx <<= MONO_CUSTOM_ATTR_BITS;
8640         idx |= MONO_CUSTOM_ATTR_MODULE;
8641         return mono_custom_attrs_from_index (image, idx);
8642 }
8643
8644 MonoCustomAttrInfo*
8645 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8646 {
8647         guint32 idx;
8648         
8649         if (klass->image->dynamic) {
8650                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8651                 return lookup_custom_attr (klass->image, property);
8652         }
8653         idx = find_property_index (klass, property);
8654         idx <<= MONO_CUSTOM_ATTR_BITS;
8655         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8656         return mono_custom_attrs_from_index (klass->image, idx);
8657 }
8658
8659 MonoCustomAttrInfo*
8660 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8661 {
8662         guint32 idx;
8663         
8664         if (klass->image->dynamic) {
8665                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8666                 return lookup_custom_attr (klass->image, event);
8667         }
8668         idx = find_event_index (klass, event);
8669         idx <<= MONO_CUSTOM_ATTR_BITS;
8670         idx |= MONO_CUSTOM_ATTR_EVENT;
8671         return mono_custom_attrs_from_index (klass->image, idx);
8672 }
8673
8674 MonoCustomAttrInfo*
8675 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8676 {
8677         guint32 idx;
8678         if (klass->image->dynamic) {
8679                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8680                 return lookup_custom_attr (klass->image, field);
8681         }
8682         idx = find_field_index (klass, field);
8683         idx <<= MONO_CUSTOM_ATTR_BITS;
8684         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8685         return mono_custom_attrs_from_index (klass->image, idx);
8686 }
8687
8688 MonoCustomAttrInfo*
8689 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8690 {
8691         MonoTableInfo *ca;
8692         guint32 i, idx, method_index;
8693         guint32 param_list, param_last, param_pos, found;
8694         MonoImage *image;
8695         MonoReflectionMethodAux *aux;
8696
8697         /*
8698          * An instantiated method has the same cattrs as the generic method definition.
8699          *
8700          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8701          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8702          */
8703         if (method->is_inflated)
8704                 method = ((MonoMethodInflated *) method)->declaring;
8705
8706         if (method->klass->image->dynamic) {
8707                 MonoCustomAttrInfo *res, *ainfo;
8708                 int size;
8709
8710                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8711                 if (!aux || !aux->param_cattr)
8712                         return NULL;
8713
8714                 /* Need to copy since it will be freed later */
8715                 ainfo = aux->param_cattr [param];
8716                 if (!ainfo)
8717                         return NULL;
8718                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8719                 res = g_malloc0 (size);
8720                 memcpy (res, ainfo, size);
8721                 return res;
8722         }
8723
8724         image = method->klass->image;
8725         method_index = mono_method_get_index (method);
8726         if (!method_index)
8727                 return NULL;
8728         ca = &image->tables [MONO_TABLE_METHOD];
8729
8730         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8731         if (method_index == ca->rows) {
8732                 ca = &image->tables [MONO_TABLE_PARAM];
8733                 param_last = ca->rows + 1;
8734         } else {
8735                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8736                 ca = &image->tables [MONO_TABLE_PARAM];
8737         }
8738         found = FALSE;
8739         for (i = param_list; i < param_last; ++i) {
8740                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8741                 if (param_pos == param) {
8742                         found = TRUE;
8743                         break;
8744                 }
8745         }
8746         if (!found)
8747                 return NULL;
8748         idx = i;
8749         idx <<= MONO_CUSTOM_ATTR_BITS;
8750         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8751         return mono_custom_attrs_from_index (image, idx);
8752 }
8753
8754 gboolean
8755 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8756 {
8757         int i;
8758         MonoClass *klass;
8759         for (i = 0; i < ainfo->num_attrs; ++i) {
8760                 klass = ainfo->attrs [i].ctor->klass;
8761                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8762                         return TRUE;
8763         }
8764         return FALSE;
8765 }
8766
8767 MonoObject*
8768 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8769 {
8770         int i, attr_index;
8771         MonoClass *klass;
8772         MonoArray *attrs;
8773
8774         attr_index = -1;
8775         for (i = 0; i < ainfo->num_attrs; ++i) {
8776                 klass = ainfo->attrs [i].ctor->klass;
8777                 if (mono_class_has_parent (klass, attr_klass)) {
8778                         attr_index = i;
8779                         break;
8780                 }
8781         }
8782         if (attr_index == -1)
8783                 return NULL;
8784
8785         attrs = mono_custom_attrs_construct (ainfo);
8786         if (attrs)
8787                 return mono_array_get (attrs, MonoObject*, attr_index);
8788         else
8789                 return NULL;
8790 }
8791
8792 /*
8793  * mono_reflection_get_custom_attrs_info:
8794  * @obj: a reflection object handle
8795  *
8796  * Return the custom attribute info for attributes defined for the
8797  * reflection handle @obj. The objects.
8798  *
8799  * FIXME this function leaks like a sieve for SRE objects.
8800  */
8801 MonoCustomAttrInfo*
8802 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8803 {
8804         MonoClass *klass;
8805         MonoCustomAttrInfo *cinfo = NULL;
8806         
8807         klass = obj->vtable->klass;
8808         if (klass == mono_defaults.monotype_class) {
8809                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8810                 klass = mono_class_from_mono_type (type);
8811                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8812                 cinfo = mono_custom_attrs_from_class (klass);
8813         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8814                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8815                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8816         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8817                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8818                 cinfo = mono_custom_attrs_from_module (module->image);
8819         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8820                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8821                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8822         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8823                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8824                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8825         } else if (strcmp ("MonoField", klass->name) == 0) {
8826                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8827                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8828         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8829                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8830                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8831         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8832                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8833                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8834         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8835                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8836                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8837                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8838                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8839                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8840                 } else if (is_sr_mono_property (member_class)) {
8841                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8842                         MonoMethod *method;
8843                         if (!(method = prop->property->get))
8844                                 method = prop->property->set;
8845                         g_assert (method);
8846
8847                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8848                 } 
8849 #ifndef DISABLE_REFLECTION_EMIT
8850                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8851                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8852                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8853                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8854                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8855                         MonoMethod *method = NULL;
8856                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8857                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8858                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8859                                 method = ((MonoReflectionMethod *)c->cb)->method;
8860                         else
8861                                 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
8862
8863                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8864                 } 
8865 #endif
8866                 else {
8867                         char *type_name = mono_type_get_full_name (member_class);
8868                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8869                         MonoException *ex = mono_get_exception_not_supported  (msg);
8870                         g_free (type_name);
8871                         g_free (msg);
8872                         mono_raise_exception (ex);
8873                 }
8874         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8875                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8876                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8877         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8878                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8879                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8880         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8881                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8882                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8883         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8884                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8885                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8886         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8887                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8888                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8889         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8890                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8891                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8892         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8893                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8894                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8895         } else { /* handle other types here... */
8896                 g_error ("get custom attrs not yet supported for %s", klass->name);
8897         }
8898
8899         return cinfo;
8900 }
8901
8902 /*
8903  * mono_reflection_get_custom_attrs_by_type:
8904  * @obj: a reflection object handle
8905  *
8906  * Return an array with all the custom attributes defined of the
8907  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8908  * of that type are returned. The objects are fully build. Return NULL if a loading error
8909  * occurs.
8910  */
8911 MonoArray*
8912 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8913 {
8914         MonoArray *result;
8915         MonoCustomAttrInfo *cinfo;
8916
8917         mono_error_init (error);
8918
8919         cinfo = mono_reflection_get_custom_attrs_info (obj);
8920         if (cinfo) {
8921                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8922                 if (!cinfo->cached)
8923                         mono_custom_attrs_free (cinfo);
8924         } else {
8925                 if (mono_loader_get_last_error ())
8926                         return NULL;
8927                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8928         }
8929
8930         return result;
8931 }
8932
8933 /*
8934  * mono_reflection_get_custom_attrs:
8935  * @obj: a reflection object handle
8936  *
8937  * Return an array with all the custom attributes defined of the
8938  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8939  * occurs.
8940  */
8941 MonoArray*
8942 mono_reflection_get_custom_attrs (MonoObject *obj)
8943 {
8944         MonoError error;
8945
8946         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8947 }
8948
8949 /*
8950  * mono_reflection_get_custom_attrs_data:
8951  * @obj: a reflection obj handle
8952  *
8953  * Returns an array of System.Reflection.CustomAttributeData,
8954  * which include information about attributes reflected on
8955  * types loaded using the Reflection Only methods
8956  */
8957 MonoArray*
8958 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8959 {
8960         MonoArray *result;
8961         MonoCustomAttrInfo *cinfo;
8962
8963         cinfo = mono_reflection_get_custom_attrs_info (obj);
8964         if (cinfo) {
8965                 result = mono_custom_attrs_data_construct (cinfo);
8966                 if (!cinfo->cached)
8967                         mono_custom_attrs_free (cinfo);
8968         } else
8969                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8970
8971         return result;
8972 }
8973
8974 static MonoReflectionType*
8975 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8976 {
8977         static MonoMethod *method_get_underlying_system_type = NULL;
8978         MonoMethod *usertype_method;
8979
8980         if (!method_get_underlying_system_type)
8981                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8982         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8983         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8984 }
8985
8986
8987 static gboolean
8988 is_corlib_type (MonoClass *class)
8989 {
8990         return class->image == mono_defaults.corlib;
8991 }
8992
8993 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8994         static MonoClass *cached_class; \
8995         if (cached_class) \
8996                 return cached_class == _class; \
8997         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8998                 cached_class = _class; \
8999                 return TRUE; \
9000         } \
9001         return FALSE; \
9002 } while (0) \
9003
9004
9005 #ifndef DISABLE_REFLECTION_EMIT
9006 static gboolean
9007 is_sre_array (MonoClass *class)
9008 {
9009         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9010 }
9011
9012 static gboolean
9013 is_sre_byref (MonoClass *class)
9014 {
9015         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9016 }
9017
9018 static gboolean
9019 is_sre_pointer (MonoClass *class)
9020 {
9021         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9022 }
9023
9024 static gboolean
9025 is_sre_generic_instance (MonoClass *class)
9026 {
9027         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9028 }
9029
9030 static gboolean
9031 is_sre_type_builder (MonoClass *class)
9032 {
9033         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9034 }
9035
9036 static gboolean
9037 is_sre_method_builder (MonoClass *class)
9038 {
9039         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9040 }
9041
9042 static gboolean
9043 is_sre_ctor_builder (MonoClass *class)
9044 {
9045         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9046 }
9047
9048 static gboolean
9049 is_sre_field_builder (MonoClass *class)
9050 {
9051         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9052 }
9053
9054 static gboolean
9055 is_sre_method_on_tb_inst (MonoClass *class)
9056 {
9057         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9058 }
9059
9060 static gboolean
9061 is_sre_ctor_on_tb_inst (MonoClass *class)
9062 {
9063         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9064 }
9065
9066 MonoType*
9067 mono_reflection_type_get_handle (MonoReflectionType* ref)
9068 {
9069         MonoClass *class;
9070         if (!ref)
9071                 return NULL;
9072         if (ref->type)
9073                 return ref->type;
9074
9075         if (is_usertype (ref)) {
9076                 ref = mono_reflection_type_get_underlying_system_type (ref);
9077                 if (ref == NULL || is_usertype (ref))
9078                         return NULL;
9079                 if (ref->type)
9080                         return ref->type;
9081         }
9082
9083         class = mono_object_class (ref);
9084
9085         if (is_sre_array (class)) {
9086                 MonoType *res;
9087                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9088                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9089                 g_assert (base);
9090                 if (sre_array->rank == 0) //single dimentional array
9091                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9092                 else
9093                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9094                 sre_array->type.type = res;
9095                 return res;
9096         } else if (is_sre_byref (class)) {
9097                 MonoType *res;
9098                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9099                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9100                 g_assert (base);
9101                 res = &mono_class_from_mono_type (base)->this_arg;
9102                 sre_byref->type.type = res;
9103                 return res;
9104         } else if (is_sre_pointer (class)) {
9105                 MonoType *res;
9106                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9107                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9108                 g_assert (base);
9109                 res = &mono_ptr_class_get (base)->byval_arg;
9110                 sre_pointer->type.type = res;
9111                 return res;
9112         } else if (is_sre_generic_instance (class)) {
9113                 MonoType *res, **types;
9114                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9115                 int i, count;
9116
9117                 count = mono_array_length (gclass->type_arguments);
9118                 types = g_new0 (MonoType*, count);
9119                 for (i = 0; i < count; ++i) {
9120                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9121                         types [i] = mono_reflection_type_get_handle (t);
9122                         if (!types[i]) {
9123                                 g_free (types);
9124                                 return NULL;
9125                         }
9126                 }
9127
9128                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9129                 g_free (types);
9130                 g_assert (res);
9131                 gclass->type.type = res;
9132                 return res;
9133         }
9134
9135         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9136         return NULL;
9137 }
9138
9139
9140
9141 void
9142 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9143 {
9144         mono_reflection_type_get_handle (type);
9145 }
9146
9147 void
9148 mono_reflection_register_with_runtime (MonoReflectionType *type)
9149 {
9150         MonoType *res = mono_reflection_type_get_handle (type);
9151         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9152         MonoClass *class;
9153
9154         if (!res)
9155                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9156
9157         class = mono_class_from_mono_type (res);
9158
9159         mono_loader_lock (); /*same locking as mono_type_get_object*/
9160         mono_domain_lock (domain);
9161
9162         if (!class->image->dynamic) {
9163                 mono_class_setup_supertypes (class);
9164         } else {
9165                 if (!domain->type_hash)
9166                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9167                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9168                 mono_g_hash_table_insert (domain->type_hash, res, type);
9169         }
9170         mono_domain_unlock (domain);
9171         mono_loader_unlock ();
9172 }
9173
9174 /**
9175  * LOCKING: Assumes the loader lock is held.
9176  */
9177 static MonoMethodSignature*
9178 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9179         MonoMethodSignature *sig;
9180         int count, i;
9181
9182         count = parameters? mono_array_length (parameters): 0;
9183
9184         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9185         sig->param_count = count;
9186         sig->sentinelpos = -1; /* FIXME */
9187         for (i = 0; i < count; ++i)
9188                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9189         return sig;
9190 }
9191
9192 /**
9193  * LOCKING: Assumes the loader lock is held.
9194  */
9195 static MonoMethodSignature*
9196 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9197         MonoMethodSignature *sig;
9198
9199         sig = parameters_to_signature (image, ctor->parameters);
9200         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9201         sig->ret = &mono_defaults.void_class->byval_arg;
9202         return sig;
9203 }
9204
9205 /**
9206  * LOCKING: Assumes the loader lock is held.
9207  */
9208 static MonoMethodSignature*
9209 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9210         MonoMethodSignature *sig;
9211
9212         sig = parameters_to_signature (image, method->parameters);
9213         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9214         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9215         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9216         return sig;
9217 }
9218
9219 static MonoMethodSignature*
9220 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9221         MonoMethodSignature *sig;
9222
9223         sig = parameters_to_signature (NULL, method->parameters);
9224         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9225         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9226         sig->generic_param_count = 0;
9227         return sig;
9228 }
9229
9230 static void
9231 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9232 {
9233         MonoClass *klass = mono_object_class (prop);
9234         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9235                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9236                 *name = mono_string_to_utf8 (pb->name);
9237                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9238         } else {
9239                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9240                 *name = g_strdup (p->property->name);
9241                 if (p->property->get)
9242                         *type = mono_method_signature (p->property->get)->ret;
9243                 else
9244                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9245         }
9246 }
9247
9248 static void
9249 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9250 {
9251         MonoClass *klass = mono_object_class (field);
9252         if (strcmp (klass->name, "FieldBuilder") == 0) {
9253                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9254                 *name = mono_string_to_utf8 (fb->name);
9255                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9256         } else {
9257                 MonoReflectionField *f = (MonoReflectionField *)field;
9258                 *name = g_strdup (mono_field_get_name (f->field));
9259                 *type = f->field->type;
9260         }
9261 }
9262
9263 #else /* DISABLE_REFLECTION_EMIT */
9264
9265 void
9266 mono_reflection_register_with_runtime (MonoReflectionType *type)
9267 {
9268         /* This is empty */
9269 }
9270
9271 static gboolean
9272 is_sre_type_builder (MonoClass *class)
9273 {
9274         return FALSE;
9275 }
9276
9277 static gboolean
9278 is_sre_generic_instance (MonoClass *class)
9279 {
9280         return FALSE;
9281 }
9282
9283 static void
9284 init_type_builder_generics (MonoObject *type)
9285 {
9286 }
9287
9288 #endif /* !DISABLE_REFLECTION_EMIT */
9289
9290
9291 static gboolean
9292 is_sr_mono_field (MonoClass *class)
9293 {
9294         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9295 }
9296
9297 static gboolean
9298 is_sr_mono_property (MonoClass *class)
9299 {
9300         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9301 }
9302
9303 static gboolean
9304 is_sr_mono_method (MonoClass *class)
9305 {
9306         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9307 }
9308
9309 static gboolean
9310 is_sr_mono_cmethod (MonoClass *class)
9311 {
9312         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9313 }
9314
9315 static gboolean
9316 is_sr_mono_generic_method (MonoClass *class)
9317 {
9318         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9319 }
9320
9321 static gboolean
9322 is_sr_mono_generic_cmethod (MonoClass *class)
9323 {
9324         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9325 }
9326
9327 gboolean
9328 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9329 {
9330         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9331 }
9332
9333 static gboolean
9334 is_usertype (MonoReflectionType *ref)
9335 {
9336         MonoClass *class = mono_object_class (ref);
9337         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9338 }
9339
9340 static MonoReflectionType*
9341 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9342 {
9343         if (!type || type->type)
9344                 return type;
9345
9346         if (is_usertype (type)) {
9347                 type = mono_reflection_type_get_underlying_system_type (type);
9348                 if (is_usertype (type))
9349                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9350         }
9351
9352         return type;
9353 }
9354 /*
9355  * Encode a value in a custom attribute stream of bytes.
9356  * The value to encode is either supplied as an object in argument val
9357  * (valuetypes are boxed), or as a pointer to the data in the
9358  * argument argval.
9359  * @type represents the type of the value
9360  * @buffer is the start of the buffer
9361  * @p the current position in the buffer
9362  * @buflen contains the size of the buffer and is used to return the new buffer size
9363  * if this needs to be realloced.
9364  * @retbuffer and @retp return the start and the position of the buffer
9365  */
9366 static void
9367 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9368 {
9369         MonoTypeEnum simple_type;
9370         
9371         if ((p-buffer) + 10 >= *buflen) {
9372                 char *newbuf;
9373                 *buflen *= 2;
9374                 newbuf = g_realloc (buffer, *buflen);
9375                 p = newbuf + (p-buffer);
9376                 buffer = newbuf;
9377         }
9378         if (!argval)
9379                 argval = ((char*)arg + sizeof (MonoObject));
9380         simple_type = type->type;
9381 handle_enum:
9382         switch (simple_type) {
9383         case MONO_TYPE_BOOLEAN:
9384         case MONO_TYPE_U1:
9385         case MONO_TYPE_I1:
9386                 *p++ = *argval;
9387                 break;
9388         case MONO_TYPE_CHAR:
9389         case MONO_TYPE_U2:
9390         case MONO_TYPE_I2:
9391                 swap_with_size (p, argval, 2, 1);
9392                 p += 2;
9393                 break;
9394         case MONO_TYPE_U4:
9395         case MONO_TYPE_I4:
9396         case MONO_TYPE_R4:
9397                 swap_with_size (p, argval, 4, 1);
9398                 p += 4;
9399                 break;
9400         case MONO_TYPE_R8:
9401 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9402                 p [0] = argval [4];
9403                 p [1] = argval [5];
9404                 p [2] = argval [6];
9405                 p [3] = argval [7];
9406                 p [4] = argval [0];
9407                 p [5] = argval [1];
9408                 p [6] = argval [2];
9409                 p [7] = argval [3];
9410 #else
9411                 swap_with_size (p, argval, 8, 1);
9412 #endif
9413                 p += 8;
9414                 break;
9415         case MONO_TYPE_U8:
9416         case MONO_TYPE_I8:
9417                 swap_with_size (p, argval, 8, 1);
9418                 p += 8;
9419                 break;
9420         case MONO_TYPE_VALUETYPE:
9421                 if (type->data.klass->enumtype) {
9422                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9423                         goto handle_enum;
9424                 } else {
9425                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9426                 }
9427                 break;
9428         case MONO_TYPE_STRING: {
9429                 char *str;
9430                 guint32 slen;
9431                 if (!arg) {
9432                         *p++ = 0xFF;
9433                         break;
9434                 }
9435                 str = mono_string_to_utf8 ((MonoString*)arg);
9436                 slen = strlen (str);
9437                 if ((p-buffer) + 10 + slen >= *buflen) {
9438                         char *newbuf;
9439                         *buflen *= 2;
9440                         *buflen += slen;
9441                         newbuf = g_realloc (buffer, *buflen);
9442                         p = newbuf + (p-buffer);
9443                         buffer = newbuf;
9444                 }
9445                 mono_metadata_encode_value (slen, p, &p);
9446                 memcpy (p, str, slen);
9447                 p += slen;
9448                 g_free (str);
9449                 break;
9450         }
9451         case MONO_TYPE_CLASS: {
9452                 char *str;
9453                 guint32 slen;
9454                 if (!arg) {
9455                         *p++ = 0xFF;
9456                         break;
9457                 }
9458 handle_type:
9459                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9460                 slen = strlen (str);
9461                 if ((p-buffer) + 10 + slen >= *buflen) {
9462                         char *newbuf;
9463                         *buflen *= 2;
9464                         *buflen += slen;
9465                         newbuf = g_realloc (buffer, *buflen);
9466                         p = newbuf + (p-buffer);
9467                         buffer = newbuf;
9468                 }
9469                 mono_metadata_encode_value (slen, p, &p);
9470                 memcpy (p, str, slen);
9471                 p += slen;
9472                 g_free (str);
9473                 break;
9474         }
9475         case MONO_TYPE_SZARRAY: {
9476                 int len, i;
9477                 MonoClass *eclass, *arg_eclass;
9478
9479                 if (!arg) {
9480                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9481                         break;
9482                 }
9483                 len = mono_array_length ((MonoArray*)arg);
9484                 *p++ = len & 0xff;
9485                 *p++ = (len >> 8) & 0xff;
9486                 *p++ = (len >> 16) & 0xff;
9487                 *p++ = (len >> 24) & 0xff;
9488                 *retp = p;
9489                 *retbuffer = buffer;
9490                 eclass = type->data.klass;
9491                 arg_eclass = mono_object_class (arg)->element_class;
9492
9493                 if (!eclass) {
9494                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9495                         eclass = mono_defaults.object_class;
9496                 }
9497                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9498                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9499                         int elsize = mono_class_array_element_size (arg_eclass);
9500                         for (i = 0; i < len; ++i) {
9501                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9502                                 elptr += elsize;
9503                         }
9504                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9505                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9506                         int elsize = mono_class_array_element_size (eclass);
9507                         for (i = 0; i < len; ++i) {
9508                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9509                                 elptr += elsize;
9510                         }
9511                 } else {
9512                         for (i = 0; i < len; ++i) {
9513                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9514                         }
9515                 }
9516                 break;
9517         }
9518         case MONO_TYPE_OBJECT: {
9519                 MonoClass *klass;
9520                 char *str;
9521                 guint32 slen;
9522
9523                 /*
9524                  * The parameter type is 'object' but the type of the actual
9525                  * argument is not. So we have to add type information to the blob
9526                  * too. This is completely undocumented in the spec.
9527                  */
9528
9529                 if (arg == NULL) {
9530                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9531                         *p++ = 0xFF;
9532                         break;
9533                 }
9534                 
9535                 klass = mono_object_class (arg);
9536
9537                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9538                         *p++ = 0x50;
9539                         goto handle_type;
9540                 } else if (klass->enumtype) {
9541                         *p++ = 0x55;
9542                 } else if (klass == mono_defaults.string_class) {
9543                         simple_type = MONO_TYPE_STRING;
9544                         *p++ = 0x0E;
9545                         goto handle_enum;
9546                 } else if (klass->rank == 1) {
9547                         *p++ = 0x1D;
9548                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9549                                 /* See Partition II, Appendix B3 */
9550                                 *p++ = 0x51;
9551                         else
9552                                 *p++ = klass->element_class->byval_arg.type;
9553                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9554                         break;
9555                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9556                         *p++ = simple_type = klass->byval_arg.type;
9557                         goto handle_enum;
9558                 } else {
9559                         g_error ("unhandled type in custom attr");
9560                 }
9561                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9562                 slen = strlen (str);
9563                 if ((p-buffer) + 10 + slen >= *buflen) {
9564                         char *newbuf;
9565                         *buflen *= 2;
9566                         *buflen += slen;
9567                         newbuf = g_realloc (buffer, *buflen);
9568                         p = newbuf + (p-buffer);
9569                         buffer = newbuf;
9570                 }
9571                 mono_metadata_encode_value (slen, p, &p);
9572                 memcpy (p, str, slen);
9573                 p += slen;
9574                 g_free (str);
9575                 simple_type = mono_class_enum_basetype (klass)->type;
9576                 goto handle_enum;
9577         }
9578         default:
9579                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9580         }
9581         *retp = p;
9582         *retbuffer = buffer;
9583 }
9584
9585 static void
9586 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9587 {
9588         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9589                 char *str = type_get_qualified_name (type, NULL);
9590                 int slen = strlen (str);
9591
9592                 *p++ = 0x55;
9593                 /*
9594                  * This seems to be optional...
9595                  * *p++ = 0x80;
9596                  */
9597                 mono_metadata_encode_value (slen, p, &p);
9598                 memcpy (p, str, slen);
9599                 p += slen;
9600                 g_free (str);
9601         } else if (type->type == MONO_TYPE_OBJECT) {
9602                 *p++ = 0x51;
9603         } else if (type->type == MONO_TYPE_CLASS) {
9604                 /* it should be a type: encode_cattr_value () has the check */
9605                 *p++ = 0x50;
9606         } else {
9607                 mono_metadata_encode_value (type->type, p, &p);
9608                 if (type->type == MONO_TYPE_SZARRAY)
9609                         /* See the examples in Partition VI, Annex B */
9610                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9611         }
9612
9613         *retp = p;
9614 }
9615
9616 #ifndef DISABLE_REFLECTION_EMIT
9617 static void
9618 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9619 {
9620         int len;
9621         /* Preallocate a large enough buffer */
9622         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9623                 char *str = type_get_qualified_name (type, NULL);
9624                 len = strlen (str);
9625                 g_free (str);
9626         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9627                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9628                 len = strlen (str);
9629                 g_free (str);
9630         } else {
9631                 len = 0;
9632         }
9633         len += strlen (name);
9634
9635         if ((p-buffer) + 20 + len >= *buflen) {
9636                 char *newbuf;
9637                 *buflen *= 2;
9638                 *buflen += len;
9639                 newbuf = g_realloc (buffer, *buflen);
9640                 p = newbuf + (p-buffer);
9641                 buffer = newbuf;
9642         }
9643
9644         encode_field_or_prop_type (type, p, &p);
9645
9646         len = strlen (name);
9647         mono_metadata_encode_value (len, p, &p);
9648         memcpy (p, name, len);
9649         p += len;
9650         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9651         *retp = p;
9652         *retbuffer = buffer;
9653 }
9654
9655 /*
9656  * mono_reflection_get_custom_attrs_blob:
9657  * @ctor: custom attribute constructor
9658  * @ctorArgs: arguments o the constructor
9659  * @properties:
9660  * @propValues:
9661  * @fields:
9662  * @fieldValues:
9663  * 
9664  * Creates the blob of data that needs to be saved in the metadata and that represents
9665  * the custom attributed described by @ctor, @ctorArgs etc.
9666  * Returns: a Byte array representing the blob of data.
9667  */
9668 MonoArray*
9669 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9670 {
9671         MonoArray *result;
9672         MonoMethodSignature *sig;
9673         MonoObject *arg;
9674         char *buffer, *p;
9675         guint32 buflen, i;
9676
9677         MONO_ARCH_SAVE_REGS;
9678
9679         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9680                 /* sig is freed later so allocate it in the heap */
9681                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9682         } else {
9683                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9684         }
9685
9686         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9687         buflen = 256;
9688         p = buffer = g_malloc (buflen);
9689         /* write the prolog */
9690         *p++ = 1;
9691         *p++ = 0;
9692         for (i = 0; i < sig->param_count; ++i) {
9693                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9694                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9695         }
9696         i = 0;
9697         if (properties)
9698                 i += mono_array_length (properties);
9699         if (fields)
9700                 i += mono_array_length (fields);
9701         *p++ = i & 0xff;
9702         *p++ = (i >> 8) & 0xff;
9703         if (properties) {
9704                 MonoObject *prop;
9705                 for (i = 0; i < mono_array_length (properties); ++i) {
9706                         MonoType *ptype;
9707                         char *pname;
9708
9709                         prop = mono_array_get (properties, gpointer, i);
9710                         get_prop_name_and_type (prop, &pname, &ptype);
9711                         *p++ = 0x54; /* PROPERTY signature */
9712                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9713                         g_free (pname);
9714                 }
9715         }
9716
9717         if (fields) {
9718                 MonoObject *field;
9719                 for (i = 0; i < mono_array_length (fields); ++i) {
9720                         MonoType *ftype;
9721                         char *fname;
9722
9723                         field = mono_array_get (fields, gpointer, i);
9724                         get_field_name_and_type (field, &fname, &ftype);
9725                         *p++ = 0x53; /* FIELD signature */
9726                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9727                         g_free (fname);
9728                 }
9729         }
9730
9731         g_assert (p - buffer <= buflen);
9732         buflen = p - buffer;
9733         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9734         p = mono_array_addr (result, char, 0);
9735         memcpy (p, buffer, buflen);
9736         g_free (buffer);
9737         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9738                 g_free (sig);
9739         return result;
9740 }
9741
9742 /*
9743  * mono_reflection_setup_internal_class:
9744  * @tb: a TypeBuilder object
9745  *
9746  * Creates a MonoClass that represents the TypeBuilder.
9747  * This is a trick that lets us simplify a lot of reflection code
9748  * (and will allow us to support Build and Run assemblies easier).
9749  */
9750 void
9751 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9752 {
9753         MonoError error;
9754         MonoClass *klass, *parent;
9755
9756         MONO_ARCH_SAVE_REGS;
9757
9758         RESOLVE_TYPE (tb->parent);
9759
9760         mono_loader_lock ();
9761
9762         if (tb->parent) {
9763                 /* check so we can compile corlib correctly */
9764                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9765                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9766                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9767                 } else {
9768                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9769                 }
9770         } else {
9771                 parent = NULL;
9772         }
9773         
9774         /* the type has already being created: it means we just have to change the parent */
9775         if (tb->type.type) {
9776                 klass = mono_class_from_mono_type (tb->type.type);
9777                 klass->parent = NULL;
9778                 /* fool mono_class_setup_parent */
9779                 klass->supertypes = NULL;
9780                 mono_class_setup_parent (klass, parent);
9781                 mono_class_setup_mono_type (klass);
9782                 mono_loader_unlock ();
9783                 return;
9784         }
9785
9786         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9787
9788         klass->image = &tb->module->dynamic_image->image;
9789
9790         klass->inited = 1; /* we lie to the runtime */
9791         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9792         if (!mono_error_ok (&error))
9793                 goto failure;
9794         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9795         if (!mono_error_ok (&error))
9796                 goto failure;
9797         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9798         klass->flags = tb->attrs;
9799         
9800         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9801
9802         klass->element_class = klass;
9803
9804         if (mono_class_get_ref_info (klass) == NULL) {
9805
9806                 mono_class_set_ref_info (klass, tb);
9807
9808                 /* Put into cache so mono_class_get () will find it.
9809                 Skip nested types as those should not be available on the global scope. */
9810                 if (!tb->nesting_type) {
9811                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9812                 } else {
9813                         klass->image->reflection_info_unregister_classes =
9814                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9815                 }
9816         } else {
9817                 g_assert (mono_class_get_ref_info (klass) == tb);
9818         }
9819
9820         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9821                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9822
9823         if (parent != NULL) {
9824                 mono_class_setup_parent (klass, parent);
9825         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9826                 const char *old_n = klass->name;
9827                 /* trick to get relative numbering right when compiling corlib */
9828                 klass->name = "BuildingObject";
9829                 mono_class_setup_parent (klass, mono_defaults.object_class);
9830                 klass->name = old_n;
9831         }
9832
9833         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9834                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9835                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9836                 klass->instance_size = sizeof (MonoObject);
9837                 klass->size_inited = 1;
9838                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9839         }
9840
9841         mono_class_setup_mono_type (klass);
9842
9843         mono_class_setup_supertypes (klass);
9844
9845         /*
9846          * FIXME: handle interfaces.
9847          */
9848
9849         tb->type.type = &klass->byval_arg;
9850
9851         if (tb->nesting_type) {
9852                 g_assert (tb->nesting_type->type);
9853                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9854         }
9855
9856         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9857
9858         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9859         
9860         mono_loader_unlock ();
9861         return;
9862
9863 failure:
9864         mono_loader_unlock ();
9865         mono_error_raise_exception (&error);
9866 }
9867
9868 /*
9869  * mono_reflection_setup_generic_class:
9870  * @tb: a TypeBuilder object
9871  *
9872  * Setup the generic class before adding the first generic parameter.
9873  */
9874 void
9875 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9876 {
9877 }
9878
9879 /*
9880  * mono_reflection_create_generic_class:
9881  * @tb: a TypeBuilder object
9882  *
9883  * Creates the generic class after all generic parameters have been added.
9884  */
9885 void
9886 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9887 {
9888         MonoClass *klass;
9889         int count, i;
9890
9891         MONO_ARCH_SAVE_REGS;
9892
9893         klass = mono_class_from_mono_type (tb->type.type);
9894
9895         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9896
9897         if (klass->generic_container || (count == 0))
9898                 return;
9899
9900         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9901
9902         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9903
9904         klass->generic_container->owner.klass = klass;
9905         klass->generic_container->type_argc = count;
9906         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9907
9908         klass->is_generic = 1;
9909
9910         for (i = 0; i < count; i++) {
9911                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9912                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9913                 klass->generic_container->type_params [i] = *param;
9914                 /*Make sure we are a diferent type instance */
9915                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9916                 klass->generic_container->type_params [i].info.pklass = NULL;
9917                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9918
9919                 g_assert (klass->generic_container->type_params [i].param.owner);
9920         }
9921
9922         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9923 }
9924
9925 /*
9926  * mono_reflection_create_internal_class:
9927  * @tb: a TypeBuilder object
9928  *
9929  * Actually create the MonoClass that is associated with the TypeBuilder.
9930  */
9931 void
9932 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9933 {
9934         MonoClass *klass;
9935
9936         MONO_ARCH_SAVE_REGS;
9937
9938         klass = mono_class_from_mono_type (tb->type.type);
9939
9940         mono_loader_lock ();
9941         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9942                 MonoReflectionFieldBuilder *fb;
9943                 MonoClass *ec;
9944                 MonoType *enum_basetype;
9945
9946                 g_assert (tb->fields != NULL);
9947                 g_assert (mono_array_length (tb->fields) >= 1);
9948
9949                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9950
9951                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9952                         mono_loader_unlock ();
9953                         return;
9954                 }
9955
9956                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9957                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9958                 if (!klass->element_class)
9959                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9960
9961                 /*
9962                  * get the element_class from the current corlib.
9963                  */
9964                 ec = default_class_from_mono_type (enum_basetype);
9965                 klass->instance_size = ec->instance_size;
9966                 klass->size_inited = 1;
9967                 /* 
9968                  * this is almost safe to do with enums and it's needed to be able
9969                  * to create objects of the enum type (for use in SetConstant).
9970                  */
9971                 /* FIXME: Does this mean enums can't have method overrides ? */
9972                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9973         }
9974         mono_loader_unlock ();
9975 }
9976
9977 static MonoMarshalSpec*
9978 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9979                                                                 MonoReflectionMarshal *minfo)
9980 {
9981         MonoMarshalSpec *res;
9982
9983         res = image_g_new0 (image, MonoMarshalSpec, 1);
9984         res->native = minfo->type;
9985
9986         switch (minfo->type) {
9987         case MONO_NATIVE_LPARRAY:
9988                 res->data.array_data.elem_type = minfo->eltype;
9989                 if (minfo->has_size) {
9990                         res->data.array_data.param_num = minfo->param_num;
9991                         res->data.array_data.num_elem = minfo->count;
9992                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9993                 }
9994                 else {
9995                         res->data.array_data.param_num = -1;
9996                         res->data.array_data.num_elem = -1;
9997                         res->data.array_data.elem_mult = -1;
9998                 }
9999                 break;
10000
10001         case MONO_NATIVE_BYVALTSTR:
10002         case MONO_NATIVE_BYVALARRAY:
10003                 res->data.array_data.num_elem = minfo->count;
10004                 break;
10005
10006         case MONO_NATIVE_CUSTOM:
10007                 if (minfo->marshaltyperef)
10008                         res->data.custom_data.custom_name =
10009                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10010                 if (minfo->mcookie)
10011                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10012                 break;
10013
10014         default:
10015                 break;
10016         }
10017
10018         return res;
10019 }
10020 #endif /* !DISABLE_REFLECTION_EMIT */
10021
10022 MonoReflectionMarshal*
10023 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10024                                                                                    MonoMarshalSpec *spec)
10025 {
10026         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10027         MonoReflectionMarshal *minfo;
10028         MonoType *mtype;
10029
10030         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10031                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10032                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10033                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10034         }
10035
10036         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10037         minfo->type = spec->native;
10038
10039         switch (minfo->type) {
10040         case MONO_NATIVE_LPARRAY:
10041                 minfo->eltype = spec->data.array_data.elem_type;
10042                 minfo->count = spec->data.array_data.num_elem;
10043                 minfo->param_num = spec->data.array_data.param_num;
10044                 break;
10045
10046         case MONO_NATIVE_BYVALTSTR:
10047         case MONO_NATIVE_BYVALARRAY:
10048                 minfo->count = spec->data.array_data.num_elem;
10049                 break;
10050
10051         case MONO_NATIVE_CUSTOM:
10052                 if (spec->data.custom_data.custom_name) {
10053                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10054                         if (mtype)
10055                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10056
10057                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10058                 }
10059                 if (spec->data.custom_data.cookie)
10060                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10061                 break;
10062
10063         default:
10064                 break;
10065         }
10066
10067         return minfo;
10068 }
10069
10070 #ifndef DISABLE_REFLECTION_EMIT
10071 static MonoMethod*
10072 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10073                                          ReflectionMethodBuilder *rmb,
10074                                          MonoMethodSignature *sig)
10075 {
10076         MonoError error;
10077         MonoMethod *m;
10078         MonoMethodWrapper *wrapperm;
10079         MonoMarshalSpec **specs;
10080         MonoReflectionMethodAux *method_aux;
10081         MonoImage *image;
10082         gboolean dynamic;
10083         int i;
10084
10085         mono_error_init (&error);
10086         /*
10087          * Methods created using a MethodBuilder should have their memory allocated
10088          * inside the image mempool, while dynamic methods should have their memory
10089          * malloc'd.
10090          */
10091         dynamic = rmb->refs != NULL;
10092         image = dynamic ? NULL : klass->image;
10093
10094         if (!dynamic)
10095                 g_assert (!klass->generic_class);
10096
10097         mono_loader_lock ();
10098
10099         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10100                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10101                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10102         else
10103                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10104
10105         wrapperm = (MonoMethodWrapper*)m;
10106
10107         m->dynamic = dynamic;
10108         m->slot = -1;
10109         m->flags = rmb->attrs;
10110         m->iflags = rmb->iattrs;
10111         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10112         m->klass = klass;
10113         m->signature = sig;
10114         m->sre_method = TRUE;
10115         m->skip_visibility = rmb->skip_visibility;
10116         if (rmb->table_idx)
10117                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10118
10119         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10120                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10121                         m->string_ctor = 1;
10122
10123                 m->signature->pinvoke = 1;
10124         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10125                 m->signature->pinvoke = 1;
10126
10127                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10128
10129                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10130                 g_assert (mono_error_ok (&error));
10131                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10132                 g_assert (mono_error_ok (&error));
10133                 
10134                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10135
10136                 if (klass->image->dynamic)
10137                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10138
10139                 mono_loader_unlock ();
10140
10141                 return m;
10142         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10143                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10144                 MonoMethodHeader *header;
10145                 guint32 code_size;
10146                 gint32 max_stack, i;
10147                 gint32 num_locals = 0;
10148                 gint32 num_clauses = 0;
10149                 guint8 *code;
10150
10151                 if (rmb->ilgen) {
10152                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10153                         code_size = rmb->ilgen->code_len;
10154                         max_stack = rmb->ilgen->max_stack;
10155                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10156                         if (rmb->ilgen->ex_handlers)
10157                                 num_clauses = method_count_clauses (rmb->ilgen);
10158                 } else {
10159                         if (rmb->code) {
10160                                 code = mono_array_addr (rmb->code, guint8, 0);
10161                                 code_size = mono_array_length (rmb->code);
10162                                 /* we probably need to run a verifier on the code... */
10163                                 max_stack = 8; 
10164                         }
10165                         else {
10166                                 code = NULL;
10167                                 code_size = 0;
10168                                 max_stack = 8;
10169                         }
10170                 }
10171
10172                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10173                 header->code_size = code_size;
10174                 header->code = image_g_malloc (image, code_size);
10175                 memcpy ((char*)header->code, code, code_size);
10176                 header->max_stack = max_stack;
10177                 header->init_locals = rmb->init_locals;
10178                 header->num_locals = num_locals;
10179
10180                 for (i = 0; i < num_locals; ++i) {
10181                         MonoReflectionLocalBuilder *lb = 
10182                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10183
10184                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10185                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10186                 }
10187
10188                 header->num_clauses = num_clauses;
10189                 if (num_clauses) {
10190                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10191                                  rmb->ilgen, num_clauses);
10192                 }
10193
10194                 wrapperm->header = header;
10195         }
10196
10197         if (rmb->generic_params) {
10198                 int count = mono_array_length (rmb->generic_params);
10199                 MonoGenericContainer *container = rmb->generic_container;
10200
10201                 g_assert (container);
10202
10203                 container->type_argc = count;
10204                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10205                 container->owner.method = m;
10206
10207                 m->is_generic = TRUE;
10208                 mono_method_set_generic_container (m, container);
10209
10210                 for (i = 0; i < count; i++) {
10211                         MonoReflectionGenericParam *gp =
10212                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10213                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10214                         container->type_params [i] = *param;
10215                 }
10216
10217                 /*
10218                  * The method signature might have pointers to generic parameters that belong to other methods.
10219                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10220                  * generic parameters.
10221                  */
10222                 for (i = 0; i < m->signature->param_count; ++i) {
10223                         MonoType *t = m->signature->params [i];
10224                         if (t->type == MONO_TYPE_MVAR) {
10225                                 MonoGenericParam *gparam =  t->data.generic_param;
10226                                 if (gparam->num < count) {
10227                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10228                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10229                                 }
10230
10231                         }
10232                 }
10233
10234                 if (klass->generic_container) {
10235                         container->parent = klass->generic_container;
10236                         container->context.class_inst = klass->generic_container->context.class_inst;
10237                 }
10238                 container->context.method_inst = mono_get_shared_generic_inst (container);
10239         }
10240
10241         if (rmb->refs) {
10242                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10243                 int i;
10244                 void **data;
10245
10246                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10247
10248                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10249                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10250                 for (i = 0; i < rmb->nrefs; ++i)
10251                         data [i + 1] = rmb->refs [i];
10252         }
10253
10254         method_aux = NULL;
10255
10256         /* Parameter info */
10257         if (rmb->pinfo) {
10258                 if (!method_aux)
10259                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10260                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10261                 for (i = 0; i <= m->signature->param_count; ++i) {
10262                         MonoReflectionParamBuilder *pb;
10263                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10264                                 if ((i > 0) && (pb->attrs)) {
10265                                         /* Make a copy since it might point to a shared type structure */
10266                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10267                                         m->signature->params [i - 1]->attrs = pb->attrs;
10268                                 }
10269
10270                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10271                                         MonoDynamicImage *assembly;
10272                                         guint32 idx, def_type, len;
10273                                         char *p;
10274                                         const char *p2;
10275
10276                                         if (!method_aux->param_defaults) {
10277                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10278                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10279                                         }
10280                                         assembly = (MonoDynamicImage*)klass->image;
10281                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10282                                         /* Copy the data from the blob since it might get realloc-ed */
10283                                         p = assembly->blob.data + idx;
10284                                         len = mono_metadata_decode_blob_size (p, &p2);
10285                                         len += p2 - p;
10286                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10287                                         method_aux->param_default_types [i] = def_type;
10288                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10289                                 }
10290
10291                                 if (pb->name) {
10292                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10293                                         g_assert (mono_error_ok (&error));
10294                                 }
10295                                 if (pb->cattrs) {
10296                                         if (!method_aux->param_cattr)
10297                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10298                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10299                                 }
10300                         }
10301                 }
10302         }
10303
10304         /* Parameter marshalling */
10305         specs = NULL;
10306         if (rmb->pinfo)         
10307                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10308                         MonoReflectionParamBuilder *pb;
10309                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10310                                 if (pb->marshal_info) {
10311                                         if (specs == NULL)
10312                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10313                                         specs [pb->position] = 
10314                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10315                                 }
10316                         }
10317                 }
10318         if (specs != NULL) {
10319                 if (!method_aux)
10320                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10321                 method_aux->param_marshall = specs;
10322         }
10323
10324         if (klass->image->dynamic && method_aux)
10325                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10326
10327         mono_loader_unlock ();
10328
10329         return m;
10330 }       
10331
10332 static MonoMethod*
10333 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10334 {
10335         ReflectionMethodBuilder rmb;
10336         MonoMethodSignature *sig;
10337
10338         mono_loader_lock ();
10339         sig = ctor_builder_to_signature (klass->image, mb);
10340         mono_loader_unlock ();
10341
10342         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10343
10344         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10345         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10346
10347         /* If we are in a generic class, we might be called multiple times from inflate_method */
10348         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10349                 /* ilgen is no longer needed */
10350                 mb->ilgen = NULL;
10351         }
10352
10353         return mb->mhandle;
10354 }
10355
10356 static MonoMethod*
10357 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10358 {
10359         ReflectionMethodBuilder rmb;
10360         MonoMethodSignature *sig;
10361
10362         mono_loader_lock ();
10363         sig = method_builder_to_signature (klass->image, mb);
10364         mono_loader_unlock ();
10365
10366         reflection_methodbuilder_from_method_builder (&rmb, mb);
10367
10368         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10369         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10370
10371         /* If we are in a generic class, we might be called multiple times from inflate_method */
10372         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10373                 /* ilgen is no longer needed */
10374                 mb->ilgen = NULL;
10375         }
10376         return mb->mhandle;
10377 }
10378
10379 static MonoClassField*
10380 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10381 {
10382         MonoClassField *field;
10383         MonoType *custom;
10384         MonoError error;
10385
10386         field = g_new0 (MonoClassField, 1);
10387
10388         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10389         g_assert (mono_error_ok (&error));
10390         if (fb->attrs || fb->modreq || fb->modopt) {
10391                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10392                 field->type->attrs = fb->attrs;
10393
10394                 g_assert (klass->image->dynamic);
10395                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10396                 g_free (field->type);
10397                 field->type = mono_metadata_type_dup (klass->image, custom);
10398                 g_free (custom);
10399         } else {
10400                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10401         }
10402         if (fb->offset != -1)
10403                 field->offset = fb->offset;
10404         field->parent = klass;
10405         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10406
10407         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10408
10409         return field;
10410 }
10411 #endif
10412
10413 MonoType*
10414 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10415 {
10416         MonoClass *klass;
10417         MonoReflectionTypeBuilder *tb = NULL;
10418         gboolean is_dynamic = FALSE;
10419         MonoDomain *domain;
10420         MonoClass *geninst;
10421
10422         mono_loader_lock ();
10423
10424         domain = mono_object_domain (type);
10425
10426         if (is_sre_type_builder (mono_object_class (type))) {
10427                 tb = (MonoReflectionTypeBuilder *) type;
10428
10429                 is_dynamic = TRUE;
10430         } else if (is_sre_generic_instance (mono_object_class (type))) {
10431                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10432                 MonoReflectionType *gtd = rgi->generic_type;
10433
10434                 if (is_sre_type_builder (mono_object_class (gtd))) {
10435                         tb = (MonoReflectionTypeBuilder *)gtd;
10436                         is_dynamic = TRUE;
10437                 }
10438         }
10439
10440         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10441         if (tb && tb->generic_container)
10442                 mono_reflection_create_generic_class (tb);
10443
10444         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10445         if (!klass->generic_container) {
10446                 mono_loader_unlock ();
10447                 return NULL;
10448         }
10449
10450         if (klass->wastypebuilder) {
10451                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10452
10453                 is_dynamic = TRUE;
10454         }
10455
10456         mono_loader_unlock ();
10457
10458         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10459
10460         return &geninst->byval_arg;
10461 }
10462
10463 MonoClass*
10464 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10465 {
10466         MonoGenericClass *gclass;
10467         MonoGenericInst *inst;
10468
10469         g_assert (klass->generic_container);
10470
10471         inst = mono_metadata_get_generic_inst (type_argc, types);
10472         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10473
10474         return mono_generic_class_get_class (gclass);
10475 }
10476
10477 MonoReflectionMethod*
10478 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10479 {
10480         MonoClass *klass;
10481         MonoMethod *method, *inflated;
10482         MonoMethodInflated *imethod;
10483         MonoGenericContext tmp_context;
10484         MonoGenericInst *ginst;
10485         MonoType **type_argv;
10486         int count, i;
10487
10488         MONO_ARCH_SAVE_REGS;
10489
10490         /*FIXME but this no longer should happen*/
10491         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10492 #ifndef DISABLE_REFLECTION_EMIT
10493                 MonoReflectionMethodBuilder *mb = NULL;
10494                 MonoReflectionTypeBuilder *tb;
10495                 MonoClass *klass;
10496
10497                 mb = (MonoReflectionMethodBuilder *) rmethod;
10498                 tb = (MonoReflectionTypeBuilder *) mb->type;
10499                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10500
10501                 method = methodbuilder_to_mono_method (klass, mb);
10502 #else
10503                 g_assert_not_reached ();
10504                 method = NULL;
10505 #endif
10506         } else {
10507                 method = rmethod->method;
10508         }
10509
10510         klass = method->klass;
10511
10512         if (method->is_inflated)
10513                 method = ((MonoMethodInflated *) method)->declaring;
10514
10515         count = mono_method_signature (method)->generic_param_count;
10516         if (count != mono_array_length (types))
10517                 return NULL;
10518
10519         type_argv = g_new0 (MonoType *, count);
10520         for (i = 0; i < count; i++) {
10521                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10522                 type_argv [i] = mono_reflection_type_get_handle (garg);
10523         }
10524         ginst = mono_metadata_get_generic_inst (count, type_argv);
10525         g_free (type_argv);
10526
10527         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10528         tmp_context.method_inst = ginst;
10529
10530         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10531         imethod = (MonoMethodInflated *) inflated;
10532
10533         /*FIXME but I think this is no longer necessary*/
10534         if (method->klass->image->dynamic) {
10535                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10536                 /*
10537                  * This table maps metadata structures representing inflated methods/fields
10538                  * to the reflection objects representing their generic definitions.
10539                  */
10540                 mono_loader_lock ();
10541                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10542                 mono_loader_unlock ();
10543         }
10544
10545         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10546                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10547         
10548         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10549 }
10550
10551 #ifndef DISABLE_REFLECTION_EMIT
10552
10553 static MonoMethod *
10554 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10555 {
10556         MonoMethodInflated *imethod;
10557         MonoGenericContext *context;
10558         int i;
10559
10560         /*
10561          * With generic code sharing the klass might not be inflated.
10562          * This can happen because classes inflated with their own
10563          * type arguments are "normalized" to the uninflated class.
10564          */
10565         if (!klass->generic_class)
10566                 return method;
10567
10568         context = mono_class_get_context (klass);
10569
10570         if (klass->method.count && klass->methods) {
10571                 /* Find the already created inflated method */
10572                 for (i = 0; i < klass->method.count; ++i) {
10573                         g_assert (klass->methods [i]->is_inflated);
10574                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10575                                 break;
10576                 }
10577                 g_assert (i < klass->method.count);
10578                 imethod = (MonoMethodInflated*)klass->methods [i];
10579         } else {
10580                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10581         }
10582
10583         if (method->is_generic && method->klass->image->dynamic) {
10584                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10585
10586                 mono_loader_lock ();
10587                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10588                 mono_loader_unlock ();
10589         }
10590         return (MonoMethod *) imethod;
10591 }
10592
10593 static MonoMethod *
10594 inflate_method (MonoReflectionType *type, MonoObject *obj)
10595 {
10596         MonoMethod *method;
10597         MonoClass *gklass;
10598
10599         MonoClass *type_class = mono_object_class (type);
10600
10601         if (is_sre_generic_instance (type_class)) {
10602                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10603                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10604         } else if (is_sre_type_builder (type_class)) {
10605                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10606         } else if (type->type) {
10607                 gklass = mono_class_from_mono_type (type->type);
10608                 gklass = mono_class_get_generic_type_definition (gklass);
10609         } else {
10610                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10611         }
10612
10613         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10614                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10615                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10616                 else
10617                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10618         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10619                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10620         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10621                 method = ((MonoReflectionMethod *) obj)->method;
10622         else {
10623                 method = NULL; /* prevent compiler warning */
10624                 g_error ("can't handle type %s", obj->vtable->klass->name);
10625         }
10626
10627         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10628 }
10629
10630 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10631 void
10632 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10633 {
10634         MonoGenericClass *gclass;
10635         MonoDynamicGenericClass *dgclass;
10636         MonoClass *klass, *gklass;
10637         MonoType *gtype;
10638         int i;
10639
10640         MONO_ARCH_SAVE_REGS;
10641
10642         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10643         klass = mono_class_from_mono_type (gtype);
10644         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10645         gclass = gtype->data.generic_class;
10646
10647         if (!gclass->is_dynamic)
10648                 return;
10649
10650         dgclass = (MonoDynamicGenericClass *) gclass;
10651
10652         if (dgclass->initialized)
10653                 return;
10654
10655         gklass = gclass->container_class;
10656         mono_class_init (gklass);
10657
10658         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10659
10660         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10661         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10662         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10663
10664         for (i = 0; i < dgclass->count_fields; i++) {
10665                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10666                 MonoClassField *field, *inflated_field = NULL;
10667
10668                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10669                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10670                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10671                         field = ((MonoReflectionField *) obj)->field;
10672                 else {
10673                         field = NULL; /* prevent compiler warning */
10674                         g_assert_not_reached ();
10675                 }
10676
10677                 dgclass->fields [i] = *field;
10678                 dgclass->fields [i].parent = klass;
10679                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10680                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10681                 dgclass->field_generic_types [i] = field->type;
10682                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10683                 dgclass->field_objects [i] = obj;
10684
10685                 if (inflated_field) {
10686                         g_free (inflated_field);
10687                 } else {
10688                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10689                 }
10690         }
10691
10692         dgclass->initialized = TRUE;
10693 }
10694
10695 void
10696 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10697 {
10698         MonoDynamicGenericClass *dgclass;
10699         int i;
10700
10701         g_assert (gclass->is_dynamic);
10702
10703         dgclass = (MonoDynamicGenericClass *)gclass;
10704
10705         for (i = 0; i < dgclass->count_fields; ++i) {
10706                 MonoClassField *field = dgclass->fields + i;
10707                 mono_metadata_free_type (field->type);
10708                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10709         }
10710 }
10711
10712 static void
10713 fix_partial_generic_class (MonoClass *klass)
10714 {
10715         MonoClass *gklass = klass->generic_class->container_class;
10716         MonoDynamicGenericClass *dgclass;
10717         int i;
10718
10719         if (klass->wastypebuilder)
10720                 return;
10721
10722         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10723         if (klass->parent != gklass->parent) {
10724                 MonoError error;
10725                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10726                 if (mono_error_ok (&error)) {
10727                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10728                         mono_metadata_free_type (parent_type);
10729                         if (parent != klass->parent) {
10730                                 /*fool mono_class_setup_parent*/
10731                                 klass->supertypes = NULL;
10732                                 mono_class_setup_parent (klass, parent);
10733                         }
10734                 } else {
10735                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10736                         mono_error_cleanup (&error);
10737                         if (gklass->wastypebuilder)
10738                                 klass->wastypebuilder = TRUE;
10739                         return;
10740                 }
10741         }
10742
10743         if (!dgclass->initialized)
10744                 return;
10745
10746         if (klass->method.count != gklass->method.count) {
10747                 klass->method.count = gklass->method.count;
10748                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10749
10750                 for (i = 0; i < klass->method.count; i++) {
10751                         klass->methods [i] = mono_class_inflate_generic_method_full (
10752                                 gklass->methods [i], klass, mono_class_get_context (klass));
10753                 }
10754         }
10755
10756         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10757                 klass->interface_count = gklass->interface_count;
10758                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10759                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10760
10761                 for (i = 0; i < gklass->interface_count; ++i) {
10762                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10763                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10764                         mono_metadata_free_type (iface_type);
10765
10766                         ensure_runtime_vtable (klass->interfaces [i]);
10767                 }
10768                 klass->interfaces_inited = 1;
10769         }
10770
10771         if (klass->field.count != gklass->field.count) {
10772                 klass->field.count = gklass->field.count;
10773                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10774
10775                 for (i = 0; i < klass->field.count; i++) {
10776                         klass->fields [i] = gklass->fields [i];
10777                         klass->fields [i].parent = klass;
10778                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10779                 }
10780         }
10781
10782         /*We can only finish with this klass once it's parent has as well*/
10783         if (gklass->wastypebuilder)
10784                 klass->wastypebuilder = TRUE;
10785         return;
10786 }
10787
10788 static void
10789 ensure_generic_class_runtime_vtable (MonoClass *klass)
10790 {
10791         MonoClass *gklass = klass->generic_class->container_class;
10792
10793         ensure_runtime_vtable (gklass); 
10794
10795         fix_partial_generic_class (klass);
10796 }
10797
10798 static void
10799 ensure_runtime_vtable (MonoClass *klass)
10800 {
10801         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10802         int i, num, j;
10803
10804         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10805                 return;
10806         if (klass->parent)
10807                 ensure_runtime_vtable (klass->parent);
10808
10809         if (tb) {
10810                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10811                 num += tb->num_methods;
10812                 klass->method.count = num;
10813                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10814                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10815                 for (i = 0; i < num; ++i)
10816                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10817                 num = tb->num_methods;
10818                 j = i;
10819                 for (i = 0; i < num; ++i)
10820                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10821         
10822                 if (tb->interfaces) {
10823                         klass->interface_count = mono_array_length (tb->interfaces);
10824                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10825                         for (i = 0; i < klass->interface_count; ++i) {
10826                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10827                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10828                                 ensure_runtime_vtable (klass->interfaces [i]);
10829                         }
10830                         klass->interfaces_inited = 1;
10831                 }
10832         } else if (klass->generic_class){
10833                 ensure_generic_class_runtime_vtable (klass);
10834         }
10835
10836         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10837                 int slot_num = 0;
10838                 for (i = 0; i < klass->method.count; ++i) {
10839                         MonoMethod *im = klass->methods [i];
10840                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10841                                 im->slot = slot_num++;
10842                 }
10843                 
10844                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10845                 mono_class_setup_interface_offsets (klass);
10846                 mono_class_setup_interface_id (klass);
10847         }
10848
10849         /*
10850          * The generic vtable is needed even if image->run is not set since some
10851          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10852          * method->slot being defined.
10853          */
10854
10855         /* 
10856          * tb->methods could not be freed since it is used for determining 
10857          * overrides during dynamic vtable construction.
10858          */
10859 }
10860
10861 static MonoMethod*
10862 mono_reflection_method_get_handle (MonoObject *method)
10863 {
10864         MonoClass *class = mono_object_class (method);
10865         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10866                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10867                 return sr_method->method;
10868         }
10869         if (is_sre_method_builder (class)) {
10870                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10871                 return mb->mhandle;
10872         }
10873         if (is_sre_method_on_tb_inst (class)) {
10874                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10875                 MonoMethod *result;
10876                 /*FIXME move this to a proper method and unify with resolve_object*/
10877                 if (m->method_args) {
10878                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10879                 } else {
10880                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10881                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10882                         MonoMethod *mono_method;
10883
10884                         if (is_sre_method_builder (mono_object_class (m->mb)))
10885                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10886                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10887                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10888                         else
10889                                 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)));
10890
10891                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10892                 }
10893                 return result;
10894         }
10895
10896         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10897         return NULL;
10898 }
10899
10900 void
10901 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10902 {
10903         MonoReflectionTypeBuilder *tb;
10904         int i, j, onum;
10905         MonoReflectionMethod *m;
10906
10907         *overrides = NULL;
10908         *num_overrides = 0;
10909
10910         g_assert (klass->image->dynamic);
10911
10912         if (!mono_class_get_ref_info (klass))
10913                 return;
10914
10915         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10916
10917         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10918
10919         onum = 0;
10920         if (tb->methods) {
10921                 for (i = 0; i < tb->num_methods; ++i) {
10922                         MonoReflectionMethodBuilder *mb = 
10923                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10924                         if (mb->override_methods)
10925                                 onum += mono_array_length (mb->override_methods);
10926                 }
10927         }
10928
10929         if (onum) {
10930                 *overrides = g_new0 (MonoMethod*, onum * 2);
10931
10932                 onum = 0;
10933                 for (i = 0; i < tb->num_methods; ++i) {
10934                         MonoReflectionMethodBuilder *mb = 
10935                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10936                         if (mb->override_methods) {
10937                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10938                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10939
10940                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10941                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10942
10943                                         g_assert (mb->mhandle);
10944
10945                                         onum ++;
10946                                 }
10947                         }
10948                 }
10949         }
10950
10951         *num_overrides = onum;
10952 }
10953
10954 static void
10955 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10956 {
10957         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10958         MonoReflectionFieldBuilder *fb;
10959         MonoClassField *field;
10960         MonoImage *image = klass->image;
10961         const char *p, *p2;
10962         int i;
10963         guint32 len, idx, real_size = 0;
10964
10965         klass->field.count = tb->num_fields;
10966         klass->field.first = 0;
10967
10968         mono_error_init (error);
10969
10970         if (tb->class_size) {
10971                 if ((tb->packing_size & 0xfffffff0) != 0) {
10972                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10973                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10974                         return;
10975                 }
10976                 klass->packing_size = tb->packing_size;
10977                 real_size = klass->instance_size + tb->class_size;
10978         }
10979
10980         if (!klass->field.count) {
10981                 klass->instance_size = MAX (klass->instance_size, real_size);
10982                 return;
10983         }
10984         
10985         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10986         mono_class_alloc_ext (klass);
10987         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10988         /*
10989         This is, guess what, a hack.
10990         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10991         On the static path no field class is resolved, only types are built. This is the right thing to do
10992         but we suck.
10993         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10994         */
10995         klass->size_inited = 1;
10996
10997         for (i = 0; i < klass->field.count; ++i) {
10998                 MonoArray *rva_data;
10999                 fb = mono_array_get (tb->fields, gpointer, i);
11000                 field = &klass->fields [i];
11001                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11002                 if (!mono_error_ok (error))
11003                         return;
11004                 if (fb->attrs) {
11005                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11006                         field->type->attrs = fb->attrs;
11007                 } else {
11008                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11009                 }
11010
11011                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11012                         char *base = mono_array_addr (rva_data, char, 0);
11013                         size_t size = mono_array_length (rva_data);
11014                         char *data = mono_image_alloc (klass->image, size);
11015                         memcpy (data, base, size);
11016                         klass->ext->field_def_values [i].data = data;
11017                 }
11018                 if (fb->offset != -1)
11019                         field->offset = fb->offset;
11020                 field->parent = klass;
11021                 fb->handle = field;
11022                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11023
11024                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11025                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11026                 }
11027                 if (fb->def_value) {
11028                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11029                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11030                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11031                         /* Copy the data from the blob since it might get realloc-ed */
11032                         p = assembly->blob.data + idx;
11033                         len = mono_metadata_decode_blob_size (p, &p2);
11034                         len += p2 - p;
11035                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11036                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11037                 }
11038         }
11039
11040         klass->instance_size = MAX (klass->instance_size, real_size);
11041         mono_class_layout_fields (klass);
11042 }
11043
11044 static void
11045 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11046 {
11047         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11048         MonoReflectionPropertyBuilder *pb;
11049         MonoImage *image = klass->image;
11050         MonoProperty *properties;
11051         int i;
11052
11053         mono_error_init (error);
11054
11055         if (!klass->ext)
11056                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11057
11058         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11059         klass->ext->property.first = 0;
11060
11061         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11062         klass->ext->properties = properties;
11063         for (i = 0; i < klass->ext->property.count; ++i) {
11064                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11065                 properties [i].parent = klass;
11066                 properties [i].attrs = pb->attrs;
11067                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11068                 if (!mono_error_ok (error))
11069                         return;
11070                 if (pb->get_method)
11071                         properties [i].get = pb->get_method->mhandle;
11072                 if (pb->set_method)
11073                         properties [i].set = pb->set_method->mhandle;
11074
11075                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11076                 if (pb->def_value) {
11077                         guint32 len, idx;
11078                         const char *p, *p2;
11079                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11080                         if (!klass->ext->prop_def_values)
11081                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11082                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11083                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11084                         /* Copy the data from the blob since it might get realloc-ed */
11085                         p = assembly->blob.data + idx;
11086                         len = mono_metadata_decode_blob_size (p, &p2);
11087                         len += p2 - p;
11088                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11089                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11090                 }
11091         }
11092 }
11093
11094 MonoReflectionEvent *
11095 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11096 {
11097         MonoEvent *event = g_new0 (MonoEvent, 1);
11098         MonoClass *klass;
11099
11100         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11101
11102         event->parent = klass;
11103         event->attrs = eb->attrs;
11104         event->name = mono_string_to_utf8 (eb->name);
11105         if (eb->add_method)
11106                 event->add = eb->add_method->mhandle;
11107         if (eb->remove_method)
11108                 event->remove = eb->remove_method->mhandle;
11109         if (eb->raise_method)
11110                 event->raise = eb->raise_method->mhandle;
11111
11112 #ifndef MONO_SMALL_CONFIG
11113         if (eb->other_methods) {
11114                 int j;
11115                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11116                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11117                         MonoReflectionMethodBuilder *mb = 
11118                                 mono_array_get (eb->other_methods,
11119                                                 MonoReflectionMethodBuilder*, j);
11120                         event->other [j] = mb->mhandle;
11121                 }
11122         }
11123 #endif
11124
11125         return mono_event_get_object (mono_object_domain (tb), klass, event);
11126 }
11127
11128 static void
11129 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11130 {
11131         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11132         MonoReflectionEventBuilder *eb;
11133         MonoImage *image = klass->image;
11134         MonoEvent *events;
11135         int i;
11136
11137         mono_error_init (error);
11138
11139         if (!klass->ext)
11140                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11141
11142         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11143         klass->ext->event.first = 0;
11144
11145         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11146         klass->ext->events = events;
11147         for (i = 0; i < klass->ext->event.count; ++i) {
11148                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11149                 events [i].parent = klass;
11150                 events [i].attrs = eb->attrs;
11151                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11152                 if (!mono_error_ok (error))
11153                         return;
11154                 if (eb->add_method)
11155                         events [i].add = eb->add_method->mhandle;
11156                 if (eb->remove_method)
11157                         events [i].remove = eb->remove_method->mhandle;
11158                 if (eb->raise_method)
11159                         events [i].raise = eb->raise_method->mhandle;
11160
11161 #ifndef MONO_SMALL_CONFIG
11162                 if (eb->other_methods) {
11163                         int j;
11164                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11165                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11166                                 MonoReflectionMethodBuilder *mb = 
11167                                         mono_array_get (eb->other_methods,
11168                                                                         MonoReflectionMethodBuilder*, j);
11169                                 events [i].other [j] = mb->mhandle;
11170                         }
11171                 }
11172 #endif
11173                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11174         }
11175 }
11176
11177 static gboolean
11178 remove_instantiations_of_and_ensure_contents (gpointer key,
11179                                                   gpointer value,
11180                                                   gpointer user_data)
11181 {
11182         MonoType *type = (MonoType*)key;
11183         MonoClass *klass = (MonoClass*)user_data;
11184
11185         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11186                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11187                 return TRUE;
11188         } else
11189                 return FALSE;
11190 }
11191
11192 static void
11193 check_array_for_usertypes (MonoArray *arr)
11194 {
11195         int i;
11196
11197         if (!arr)
11198                 return;
11199
11200         for (i = 0; i < mono_array_length (arr); ++i)
11201                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11202 }
11203
11204 MonoReflectionType*
11205 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11206 {
11207         MonoError error;
11208         MonoClass *klass;
11209         MonoDomain* domain;
11210         MonoReflectionType* res;
11211         int i, j;
11212
11213         MONO_ARCH_SAVE_REGS;
11214
11215         domain = mono_object_domain (tb);
11216         klass = mono_class_from_mono_type (tb->type.type);
11217
11218         /*
11219          * Check for user defined Type subclasses.
11220          */
11221         RESOLVE_TYPE (tb->parent);
11222         check_array_for_usertypes (tb->interfaces);
11223         if (tb->fields) {
11224                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11225                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11226                         if (fb) {
11227                                 RESOLVE_TYPE (fb->type);
11228                                 check_array_for_usertypes (fb->modreq);
11229                                 check_array_for_usertypes (fb->modopt);
11230                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11231                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11232                         }
11233                 }
11234         }
11235         if (tb->methods) {
11236                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11237                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11238                         if (mb) {
11239                                 RESOLVE_TYPE (mb->rtype);
11240                                 check_array_for_usertypes (mb->return_modreq);
11241                                 check_array_for_usertypes (mb->return_modopt);
11242                                 check_array_for_usertypes (mb->parameters);
11243                                 if (mb->param_modreq)
11244                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11245                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11246                                 if (mb->param_modopt)
11247                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11248                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11249                         }
11250                 }
11251         }
11252         if (tb->ctors) {
11253                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11254                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11255                         if (mb) {
11256                                 check_array_for_usertypes (mb->parameters);
11257                                 if (mb->param_modreq)
11258                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11259                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11260                                 if (mb->param_modopt)
11261                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11262                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11263                         }
11264                 }
11265         }
11266
11267         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11268
11269         /* 
11270          * we need to lock the domain because the lock will be taken inside
11271          * So, we need to keep the locking order correct.
11272          */
11273         mono_loader_lock ();
11274         mono_domain_lock (domain);
11275         if (klass->wastypebuilder) {
11276                 mono_domain_unlock (domain);
11277                 mono_loader_unlock ();
11278                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11279         }
11280         /*
11281          * Fields to set in klass:
11282          * the various flags: delegate/unicode/contextbound etc.
11283          */
11284         klass->flags = tb->attrs;
11285         klass->has_cctor = 1;
11286         klass->has_finalize = 1;
11287         klass->has_finalize_inited = 1;
11288
11289         /* fool mono_class_setup_parent */
11290         klass->supertypes = NULL;
11291         mono_class_setup_parent (klass, klass->parent);
11292         mono_class_setup_mono_type (klass);
11293
11294 #if 0
11295         if (!((MonoDynamicImage*)klass->image)->run) {
11296                 if (klass->generic_container) {
11297                         /* FIXME: The code below can't handle generic classes */
11298                         klass->wastypebuilder = TRUE;
11299                         mono_loader_unlock ();
11300                         mono_domain_unlock (domain);
11301                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11302                 }
11303         }
11304 #endif
11305
11306         /* enums are done right away */
11307         if (!klass->enumtype)
11308                 ensure_runtime_vtable (klass);
11309
11310         if (tb->subtypes) {
11311                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11312                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11313                         mono_class_alloc_ext (klass);
11314                         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)));
11315                 }
11316         }
11317
11318         klass->nested_classes_inited = TRUE;
11319
11320         /* fields and object layout */
11321         if (klass->parent) {
11322                 if (!klass->parent->size_inited)
11323                         mono_class_init (klass->parent);
11324                 klass->instance_size = klass->parent->instance_size;
11325                 klass->sizes.class_size = 0;
11326                 klass->min_align = klass->parent->min_align;
11327                 /* if the type has no fields we won't call the field_setup
11328                  * routine which sets up klass->has_references.
11329                  */
11330                 klass->has_references |= klass->parent->has_references;
11331         } else {
11332                 klass->instance_size = sizeof (MonoObject);
11333                 klass->min_align = 1;
11334         }
11335
11336         /* FIXME: handle packing_size and instance_size */
11337         typebuilder_setup_fields (klass, &error);
11338         if (!mono_error_ok (&error))
11339                 goto failure;
11340         typebuilder_setup_properties (klass, &error);
11341         if (!mono_error_ok (&error))
11342                 goto failure;
11343
11344         typebuilder_setup_events (klass, &error);
11345         if (!mono_error_ok (&error))
11346                 goto failure;
11347
11348         klass->wastypebuilder = TRUE;
11349
11350         /* 
11351          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11352          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11353          * we want to return normal System.MonoType objects, so clear these out from the cache.
11354          *
11355          * Together with this we must ensure the contents of all instances to match the created type.
11356          */
11357         if (domain->type_hash && klass->generic_container)
11358                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11359
11360         mono_domain_unlock (domain);
11361         mono_loader_unlock ();
11362
11363         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11364                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11365                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11366         }
11367
11368         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11369         g_assert (res != (MonoReflectionType*)tb);
11370
11371         return res;
11372
11373 failure:
11374         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11375         klass->wastypebuilder = TRUE;
11376         mono_domain_unlock (domain);
11377         mono_loader_unlock ();
11378         mono_error_raise_exception (&error);
11379         return NULL;
11380 }
11381
11382 void
11383 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11384 {
11385         MonoGenericParamFull *param;
11386         MonoImage *image;
11387         MonoClass *pklass;
11388         MonoError error;
11389
11390         MONO_ARCH_SAVE_REGS;
11391
11392         image = &gparam->tbuilder->module->dynamic_image->image;
11393
11394         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11395
11396         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11397         g_assert (mono_error_ok (&error));
11398         param->param.num = gparam->index;
11399
11400         if (gparam->mbuilder) {
11401                 if (!gparam->mbuilder->generic_container) {
11402                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11403                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11404                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11405                         gparam->mbuilder->generic_container->is_method = TRUE;
11406                         /* 
11407                          * Cannot set owner.method, since the MonoMethod is not created yet.
11408                          * Set the image field instead, so type_in_image () works.
11409                          */
11410                         gparam->mbuilder->generic_container->image = klass->image;
11411                 }
11412                 param->param.owner = gparam->mbuilder->generic_container;
11413         } else if (gparam->tbuilder) {
11414                 if (!gparam->tbuilder->generic_container) {
11415                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11416                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11417                         gparam->tbuilder->generic_container->owner.klass = klass;
11418                 }
11419                 param->param.owner = gparam->tbuilder->generic_container;
11420         }
11421
11422         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11423
11424         gparam->type.type = &pklass->byval_arg;
11425
11426         mono_class_set_ref_info (pklass, gparam);
11427         mono_image_lock (image);
11428         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11429         mono_image_unlock (image);
11430 }
11431
11432 MonoArray *
11433 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11434 {
11435         MonoReflectionModuleBuilder *module = sig->module;
11436         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11437         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11438         guint32 buflen, i;
11439         MonoArray *result;
11440         SigBuffer buf;
11441
11442         check_array_for_usertypes (sig->arguments);
11443
11444         sigbuffer_init (&buf, 32);
11445
11446         sigbuffer_add_value (&buf, 0x07);
11447         sigbuffer_add_value (&buf, na);
11448         if (assembly != NULL){
11449                 for (i = 0; i < na; ++i) {
11450                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11451                         encode_reflection_type (assembly, type, &buf);
11452                 }
11453         }
11454
11455         buflen = buf.p - buf.buf;
11456         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11457         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11458         sigbuffer_free (&buf);
11459
11460         return result;
11461 }
11462
11463 MonoArray *
11464 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11465 {
11466         MonoDynamicImage *assembly = sig->module->dynamic_image;
11467         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11468         guint32 buflen, i;
11469         MonoArray *result;
11470         SigBuffer buf;
11471
11472         check_array_for_usertypes (sig->arguments);
11473
11474         sigbuffer_init (&buf, 32);
11475
11476         sigbuffer_add_value (&buf, 0x06);
11477         for (i = 0; i < na; ++i) {
11478                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11479                 encode_reflection_type (assembly, type, &buf);
11480         }
11481
11482         buflen = buf.p - buf.buf;
11483         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11484         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11485         sigbuffer_free (&buf);
11486
11487         return result;
11488 }
11489
11490 typedef struct {
11491         MonoMethod *handle;
11492         MonoDomain *domain;
11493 } DynamicMethodReleaseData;
11494
11495 /*
11496  * The runtime automatically clean up those after finalization.
11497 */      
11498 static MonoReferenceQueue *dynamic_method_queue;
11499
11500 static void
11501 free_dynamic_method (void *dynamic_method)
11502 {
11503         DynamicMethodReleaseData *data = dynamic_method;
11504
11505         mono_runtime_free_method (data->domain, data->handle);
11506         g_free (data);
11507 }
11508
11509 void 
11510 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11511 {
11512         MonoReferenceQueue *queue;
11513         MonoMethod *handle;
11514         DynamicMethodReleaseData *release_data;
11515         ReflectionMethodBuilder rmb;
11516         MonoMethodSignature *sig;
11517         MonoClass *klass;
11518         GSList *l;
11519         int i;
11520
11521         if (mono_runtime_is_shutting_down ())
11522                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11523
11524         if (!(queue = dynamic_method_queue)) {
11525                 mono_loader_lock ();
11526                 if (!(queue = dynamic_method_queue))
11527                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11528                 mono_loader_unlock ();
11529         }
11530
11531         sig = dynamic_method_to_signature (mb);
11532
11533         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11534
11535         /*
11536          * Resolve references.
11537          */
11538         /* 
11539          * Every second entry in the refs array is reserved for storing handle_class,
11540          * which is needed by the ldtoken implementation in the JIT.
11541          */
11542         rmb.nrefs = mb->nrefs;
11543         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11544         for (i = 0; i < mb->nrefs; i += 2) {
11545                 MonoClass *handle_class;
11546                 gpointer ref;
11547                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11548
11549                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11550                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11551                         /*
11552                          * The referenced DynamicMethod should already be created by the managed
11553                          * code, except in the case of circular references. In that case, we store
11554                          * method in the refs array, and fix it up later when the referenced 
11555                          * DynamicMethod is created.
11556                          */
11557                         if (method->mhandle) {
11558                                 ref = method->mhandle;
11559                         } else {
11560                                 /* FIXME: GC object stored in unmanaged memory */
11561                                 ref = method;
11562
11563                                 /* FIXME: GC object stored in unmanaged memory */
11564                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11565                         }
11566                         handle_class = mono_defaults.methodhandle_class;
11567                 } else {
11568                         MonoException *ex = NULL;
11569                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11570                         if (!ref)
11571                                 ex = mono_get_exception_type_load (NULL, NULL);
11572                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11573                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11574
11575                         if (ex) {
11576                                 g_free (rmb.refs);
11577                                 mono_raise_exception (ex);
11578                                 return;
11579                         }
11580                 }
11581
11582                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11583                 rmb.refs [i + 1] = handle_class;
11584         }               
11585
11586         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11587
11588         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11589         release_data = g_new (DynamicMethodReleaseData, 1);
11590         release_data->handle = handle;
11591         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11592         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11593                 g_free (release_data);
11594
11595         /* Fix up refs entries pointing at us */
11596         for (l = mb->referenced_by; l; l = l->next) {
11597                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11598                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11599                 gpointer *data;
11600                 
11601                 g_assert (method->mhandle);
11602
11603                 data = (gpointer*)wrapper->method_data;
11604                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11605                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11606                                 data [i + 1] = mb->mhandle;
11607                 }
11608         }
11609         g_slist_free (mb->referenced_by);
11610
11611         g_free (rmb.refs);
11612
11613         /* ilgen is no longer needed */
11614         mb->ilgen = NULL;
11615 }
11616
11617 #endif /* DISABLE_REFLECTION_EMIT */
11618
11619 /**
11620  * 
11621  * mono_reflection_is_valid_dynamic_token:
11622  * 
11623  * Returns TRUE if token is valid.
11624  * 
11625  */
11626 gboolean
11627 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11628 {
11629         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11630 }
11631
11632 MonoMethodSignature *
11633 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11634 {
11635         MonoMethodSignature *sig;
11636         g_assert (image->dynamic);
11637
11638         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11639         if (sig)
11640                 return sig;
11641
11642         return mono_method_signature (method);
11643 }
11644
11645 #ifndef DISABLE_REFLECTION_EMIT
11646
11647 /**
11648  * mono_reflection_lookup_dynamic_token:
11649  *
11650  * Finish the Builder object pointed to by TOKEN and return the corresponding
11651  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11652  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11653  * mapping table.
11654  *
11655  * LOCKING: Take the loader lock
11656  */
11657 gpointer
11658 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11659 {
11660         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11661         MonoObject *obj;
11662         MonoClass *klass;
11663
11664         mono_loader_lock ();
11665         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11666         mono_loader_unlock ();
11667         if (!obj) {
11668                 if (valid_token)
11669                         g_error ("Could not find required dynamic token 0x%08x", token);
11670                 else
11671                         return NULL;
11672         }
11673
11674         if (!handle_class)
11675                 handle_class = &klass;
11676         return resolve_object (image, obj, handle_class, context);
11677 }
11678
11679 /*
11680  * ensure_complete_type:
11681  *
11682  *   Ensure that KLASS is completed if it is a dynamic type, or references
11683  * dynamic types.
11684  */
11685 static void
11686 ensure_complete_type (MonoClass *klass)
11687 {
11688         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11689                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11690
11691                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11692
11693                 // Asserting here could break a lot of code
11694                 //g_assert (klass->wastypebuilder);
11695         }
11696
11697         if (klass->generic_class) {
11698                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11699                 int i;
11700
11701                 for (i = 0; i < inst->type_argc; ++i) {
11702                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11703                 }
11704         }
11705 }
11706
11707 static gpointer
11708 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11709 {
11710         gpointer result = NULL;
11711
11712         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11713                 result = mono_string_intern ((MonoString*)obj);
11714                 *handle_class = mono_defaults.string_class;
11715                 g_assert (result);
11716         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11717                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11718                 MonoClass *mc = mono_class_from_mono_type (type);
11719                 if (!mono_class_init (mc))
11720                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11721
11722                 if (context) {
11723                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11724                         result = mono_class_from_mono_type (inflated);
11725                         mono_metadata_free_type (inflated);
11726                 } else {
11727                         result = mono_class_from_mono_type (type);
11728                 }
11729                 *handle_class = mono_defaults.typehandle_class;
11730                 g_assert (result);
11731         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11732                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11733                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11734                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11735                 result = ((MonoReflectionMethod*)obj)->method;
11736                 if (context)
11737                         result = mono_class_inflate_generic_method (result, context);
11738                 *handle_class = mono_defaults.methodhandle_class;
11739                 g_assert (result);
11740         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11741                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11742                 result = mb->mhandle;
11743                 if (!result) {
11744                         /* Type is not yet created */
11745                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11746
11747                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11748
11749                         /*
11750                          * Hopefully this has been filled in by calling CreateType() on the
11751                          * TypeBuilder.
11752                          */
11753                         /*
11754                          * TODO: This won't work if the application finishes another 
11755                          * TypeBuilder instance instead of this one.
11756                          */
11757                         result = mb->mhandle;
11758                 }
11759                 if (context)
11760                         result = mono_class_inflate_generic_method (result, context);
11761                 *handle_class = mono_defaults.methodhandle_class;
11762         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11763                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11764
11765                 result = cb->mhandle;
11766                 if (!result) {
11767                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11768
11769                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11770                         result = cb->mhandle;
11771                 }
11772                 if (context)
11773                         result = mono_class_inflate_generic_method (result, context);
11774                 *handle_class = mono_defaults.methodhandle_class;
11775         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11776                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11777
11778                 ensure_complete_type (field->parent);
11779                 if (context) {
11780                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11781                         MonoClass *class = mono_class_from_mono_type (inflated);
11782                         MonoClassField *inflated_field;
11783                         gpointer iter = NULL;
11784                         mono_metadata_free_type (inflated);
11785                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11786                                 if (!strcmp (field->name, inflated_field->name))
11787                                         break;
11788                         }
11789                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11790                         result = inflated_field;
11791                 } else {
11792                         result = field;
11793                 }
11794                 *handle_class = mono_defaults.fieldhandle_class;
11795                 g_assert (result);
11796         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11797                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11798                 result = fb->handle;
11799
11800                 if (!result) {
11801                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11802
11803                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11804                         result = fb->handle;
11805                 }
11806
11807                 if (fb->handle && fb->handle->parent->generic_container) {
11808                         MonoClass *klass = fb->handle->parent;
11809                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11810                         MonoClass *inflated = mono_class_from_mono_type (type);
11811
11812                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11813                         g_assert (result);
11814                         mono_metadata_free_type (type);
11815                 }
11816                 *handle_class = mono_defaults.fieldhandle_class;
11817         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11818                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11819                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11820                 MonoClass *klass;
11821
11822                 klass = type->data.klass;
11823                 if (klass->wastypebuilder) {
11824                         /* Already created */
11825                         result = klass;
11826                 }
11827                 else {
11828                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11829                         result = type->data.klass;
11830                         g_assert (result);
11831                 }
11832                 *handle_class = mono_defaults.typehandle_class;
11833         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11834                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11835                 MonoMethodSignature *sig;
11836                 int nargs, i;
11837
11838                 if (helper->arguments)
11839                         nargs = mono_array_length (helper->arguments);
11840                 else
11841                         nargs = 0;
11842
11843                 sig = mono_metadata_signature_alloc (image, nargs);
11844                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11845                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11846
11847                 if (helper->unmanaged_call_conv) { /* unmanaged */
11848                         sig->call_convention = helper->unmanaged_call_conv - 1;
11849                         sig->pinvoke = TRUE;
11850                 } else if (helper->call_conv & 0x02) {
11851                         sig->call_convention = MONO_CALL_VARARG;
11852                 } else {
11853                         sig->call_convention = MONO_CALL_DEFAULT;
11854                 }
11855
11856                 sig->param_count = nargs;
11857                 /* TODO: Copy type ? */
11858                 sig->ret = helper->return_type->type;
11859                 for (i = 0; i < nargs; ++i)
11860                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11861
11862                 result = sig;
11863                 *handle_class = NULL;
11864         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11865                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11866                 /* Already created by the managed code */
11867                 g_assert (method->mhandle);
11868                 result = method->mhandle;
11869                 *handle_class = mono_defaults.methodhandle_class;
11870         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11871                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11872                 type = mono_class_inflate_generic_type (type, context);
11873                 result = mono_class_from_mono_type (type);
11874                 *handle_class = mono_defaults.typehandle_class;
11875                 g_assert (result);
11876                 mono_metadata_free_type (type);
11877         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11878                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11879                 type = mono_class_inflate_generic_type (type, context);
11880                 result = mono_class_from_mono_type (type);
11881                 *handle_class = mono_defaults.typehandle_class;
11882                 g_assert (result);
11883                 mono_metadata_free_type (type);
11884         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11885                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11886                 MonoClass *inflated;
11887                 MonoType *type;
11888                 MonoClassField *field;
11889
11890                 if (is_sre_field_builder (mono_object_class (f->fb)))
11891                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11892                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11893                         field = ((MonoReflectionField*)f->fb)->field;
11894                 else
11895                         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)));
11896
11897                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11898                 inflated = mono_class_from_mono_type (type);
11899
11900                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11901                 ensure_complete_type (field->parent);
11902                 g_assert (result);
11903                 mono_metadata_free_type (type);
11904                 *handle_class = mono_defaults.fieldhandle_class;
11905         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11906                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11907                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11908                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11909                 MonoMethod *method;
11910
11911                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11912                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11913                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11914                         method = ((MonoReflectionMethod *)c->cb)->method;
11915                 else
11916                         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)));
11917
11918                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11919                 *handle_class = mono_defaults.methodhandle_class;
11920                 mono_metadata_free_type (type);
11921         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11922                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11923                 if (m->method_args) {
11924                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11925                         if (context)
11926                                 result = mono_class_inflate_generic_method (result, context);
11927                 } else {
11928                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11929                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11930                         MonoMethod *method;
11931
11932                         if (is_sre_method_builder (mono_object_class (m->mb)))
11933                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11934                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11935                                 method = ((MonoReflectionMethod *)m->mb)->method;
11936                         else
11937                                 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)));
11938
11939                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11940                         mono_metadata_free_type (type);
11941                 }
11942                 *handle_class = mono_defaults.methodhandle_class;
11943         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11944                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11945                 MonoType *mtype;
11946                 MonoClass *klass;
11947                 MonoMethod *method;
11948                 gpointer iter;
11949                 char *name;
11950
11951                 mtype = mono_reflection_type_get_handle (m->parent);
11952                 klass = mono_class_from_mono_type (mtype);
11953
11954                 /* Find the method */
11955
11956                 name = mono_string_to_utf8 (m->name);
11957                 iter = NULL;
11958                 while ((method = mono_class_get_methods (klass, &iter))) {
11959                         if (!strcmp (method->name, name))
11960                                 break;
11961                 }
11962                 g_free (name);
11963
11964                 // FIXME:
11965                 g_assert (method);
11966                 // FIXME: Check parameters/return value etc. match
11967
11968                 result = method;
11969                 *handle_class = mono_defaults.methodhandle_class;
11970         } else if (is_sre_array (mono_object_get_class(obj)) ||
11971                                 is_sre_byref (mono_object_get_class(obj)) ||
11972                                 is_sre_pointer (mono_object_get_class(obj))) {
11973                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11974                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11975
11976                 if (context) {
11977                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11978                         result = mono_class_from_mono_type (inflated);
11979                         mono_metadata_free_type (inflated);
11980                 } else {
11981                         result = mono_class_from_mono_type (type);
11982                 }
11983                 *handle_class = mono_defaults.typehandle_class;
11984         } else {
11985                 g_print ("%s\n", obj->vtable->klass->name);
11986                 g_assert_not_reached ();
11987         }
11988         return result;
11989 }
11990
11991 #else /* DISABLE_REFLECTION_EMIT */
11992
11993 MonoArray*
11994 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11995 {
11996         g_assert_not_reached ();
11997         return NULL;
11998 }
11999
12000 void
12001 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12002 {
12003         g_assert_not_reached ();
12004 }
12005
12006 void
12007 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12008 {
12009         g_assert_not_reached ();
12010 }
12011
12012 void
12013 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12014 {
12015         g_assert_not_reached ();
12016 }
12017
12018 void
12019 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12020 {
12021         g_assert_not_reached ();
12022 }
12023
12024 void
12025 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12026 {
12027         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12028 }
12029
12030 void
12031 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12032 {
12033         g_assert_not_reached ();
12034 }
12035
12036 void
12037 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12038 {
12039         g_assert_not_reached ();
12040 }
12041
12042 MonoReflectionModule *
12043 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12044 {
12045         g_assert_not_reached ();
12046         return NULL;
12047 }
12048
12049 guint32
12050 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12051 {
12052         g_assert_not_reached ();
12053         return 0;
12054 }
12055
12056 guint32
12057 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12058 {
12059         g_assert_not_reached ();
12060         return 0;
12061 }
12062
12063 guint32
12064 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12065                                                  gboolean create_open_instance, gboolean register_token)
12066 {
12067         g_assert_not_reached ();
12068         return 0;
12069 }
12070
12071 void
12072 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12073 {
12074 }
12075
12076 void
12077 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12078 {
12079         g_assert_not_reached ();
12080 }
12081
12082 void
12083 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12084 {
12085         *overrides = NULL;
12086         *num_overrides = 0;
12087 }
12088
12089 MonoReflectionEvent *
12090 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12091 {
12092         g_assert_not_reached ();
12093         return NULL;
12094 }
12095
12096 MonoReflectionType*
12097 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12098 {
12099         g_assert_not_reached ();
12100         return NULL;
12101 }
12102
12103 void
12104 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12105 {
12106         g_assert_not_reached ();
12107 }
12108
12109 MonoArray *
12110 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12111 {
12112         g_assert_not_reached ();
12113         return NULL;
12114 }
12115
12116 MonoArray *
12117 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12118 {
12119         g_assert_not_reached ();
12120         return NULL;
12121 }
12122
12123 void 
12124 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12125 {
12126 }
12127
12128 gpointer
12129 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12130 {
12131         return NULL;
12132 }
12133
12134 MonoType*
12135 mono_reflection_type_get_handle (MonoReflectionType* ref)
12136 {
12137         if (!ref)
12138                 return NULL;
12139         return ref->type;
12140 }
12141
12142 void
12143 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12144 {
12145         g_assert_not_reached ();
12146 }
12147
12148 #endif /* DISABLE_REFLECTION_EMIT */
12149
12150 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12151 const static guint32 declsec_flags_map[] = {
12152         0x00000000,                                     /* empty */
12153         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12154         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12155         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12156         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12157         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12158         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12159         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12160         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12161         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12162         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12163         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12164         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12165         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12166         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12167         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12168         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12169         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12170         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12171 };
12172
12173 /*
12174  * Returns flags that includes all available security action associated to the handle.
12175  * @token: metadata token (either for a class or a method)
12176  * @image: image where resides the metadata.
12177  */
12178 static guint32
12179 mono_declsec_get_flags (MonoImage *image, guint32 token)
12180 {
12181         int index = mono_metadata_declsec_from_index (image, token);
12182         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12183         guint32 result = 0;
12184         guint32 action;
12185         int i;
12186
12187         /* HasSecurity can be present for other, not specially encoded, attributes,
12188            e.g. SuppressUnmanagedCodeSecurityAttribute */
12189         if (index < 0)
12190                 return 0;
12191
12192         for (i = index; i < t->rows; i++) {
12193                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12194
12195                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12196                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12197                         break;
12198
12199                 action = cols [MONO_DECL_SECURITY_ACTION];
12200                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12201                         result |= declsec_flags_map [action];
12202                 } else {
12203                         g_assert_not_reached ();
12204                 }
12205         }
12206         return result;
12207 }
12208
12209 /*
12210  * Get the security actions (in the form of flags) associated with the specified method.
12211  *
12212  * @method: The method for which we want the declarative security flags.
12213  * Return the declarative security flags for the method (only).
12214  *
12215  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12216  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12217  */
12218 guint32
12219 mono_declsec_flags_from_method (MonoMethod *method)
12220 {
12221         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12222                 /* FIXME: No cache (for the moment) */
12223                 guint32 idx = mono_method_get_index (method);
12224                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12225                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12226                 return mono_declsec_get_flags (method->klass->image, idx);
12227         }
12228         return 0;
12229 }
12230
12231 /*
12232  * Get the security actions (in the form of flags) associated with the specified class.
12233  *
12234  * @klass: The class for which we want the declarative security flags.
12235  * Return the declarative security flags for the class.
12236  *
12237  * Note: We cache the flags inside the MonoClass structure as this will get 
12238  *       called very often (at least for each method).
12239  */
12240 guint32
12241 mono_declsec_flags_from_class (MonoClass *klass)
12242 {
12243         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12244                 if (!klass->ext || !klass->ext->declsec_flags) {
12245                         guint32 idx;
12246
12247                         idx = mono_metadata_token_index (klass->type_token);
12248                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12249                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12250                         mono_loader_lock ();
12251                         mono_class_alloc_ext (klass);
12252                         mono_loader_unlock ();
12253                         /* we cache the flags on classes */
12254                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12255                 }
12256                 return klass->ext->declsec_flags;
12257         }
12258         return 0;
12259 }
12260
12261 /*
12262  * Get the security actions (in the form of flags) associated with the specified assembly.
12263  *
12264  * @assembly: The assembly for which we want the declarative security flags.
12265  * Return the declarative security flags for the assembly.
12266  */
12267 guint32
12268 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12269 {
12270         guint32 idx = 1; /* there is only one assembly */
12271         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12272         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12273         return mono_declsec_get_flags (assembly->image, idx);
12274 }
12275
12276
12277 /*
12278  * Fill actions for the specific index (which may either be an encoded class token or
12279  * an encoded method token) from the metadata image.
12280  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12281  */
12282 static MonoBoolean
12283 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12284         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12285 {
12286         MonoBoolean result = FALSE;
12287         MonoTableInfo *t;
12288         guint32 cols [MONO_DECL_SECURITY_SIZE];
12289         int index = mono_metadata_declsec_from_index (image, token);
12290         int i;
12291
12292         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12293         for (i = index; i < t->rows; i++) {
12294                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12295
12296                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12297                         return result;
12298
12299                 /* if present only replace (class) permissions with method permissions */
12300                 /* if empty accept either class or method permissions */
12301                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12302                         if (!actions->demand.blob) {
12303                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12304                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12305                                 actions->demand.blob = (char*) (blob + 2);
12306                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12307                                 result = TRUE;
12308                         }
12309                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12310                         if (!actions->noncasdemand.blob) {
12311                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12312                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12313                                 actions->noncasdemand.blob = (char*) (blob + 2);
12314                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12315                                 result = TRUE;
12316                         }
12317                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12318                         if (!actions->demandchoice.blob) {
12319                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12320                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12321                                 actions->demandchoice.blob = (char*) (blob + 2);
12322                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12323                                 result = TRUE;
12324                         }
12325                 }
12326         }
12327
12328         return result;
12329 }
12330
12331 static MonoBoolean
12332 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12333         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12334 {
12335         guint32 idx = mono_metadata_token_index (klass->type_token);
12336         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12337         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12338         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12339 }
12340
12341 static MonoBoolean
12342 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12343         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12344 {
12345         guint32 idx = mono_method_get_index (method);
12346         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12347         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12348         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12349 }
12350
12351 /*
12352  * Collect all actions (that requires to generate code in mini) assigned for
12353  * the specified method.
12354  * Note: Don't use the content of actions if the function return FALSE.
12355  */
12356 MonoBoolean
12357 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12358 {
12359         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12360                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12361         MonoBoolean result = FALSE;
12362         guint32 flags;
12363
12364         /* quick exit if no declarative security is present in the metadata */
12365         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12366                 return FALSE;
12367
12368         /* we want the original as the wrapper is "free" of the security informations */
12369         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12370                 method = mono_marshal_method_from_wrapper (method);
12371                 if (!method)
12372                         return FALSE;
12373         }
12374
12375         /* First we look for method-level attributes */
12376         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12377                 mono_class_init (method->klass);
12378                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12379
12380                 result = mono_declsec_get_method_demands_params (method, demands, 
12381                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12382         }
12383
12384         /* Here we use (or create) the class declarative cache to look for demands */
12385         flags = mono_declsec_flags_from_class (method->klass);
12386         if (flags & mask) {
12387                 if (!result) {
12388                         mono_class_init (method->klass);
12389                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12390                 }
12391                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12392                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12393         }
12394
12395         /* The boolean return value is used as a shortcut in case nothing needs to
12396            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12397         return result;
12398 }
12399
12400
12401 /*
12402  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12403  *
12404  * Note: Don't use the content of actions if the function return FALSE.
12405  */
12406 MonoBoolean
12407 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12408 {
12409         MonoBoolean result = FALSE;
12410         guint32 flags;
12411
12412         /* quick exit if no declarative security is present in the metadata */
12413         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12414                 return FALSE;
12415
12416         /* we want the original as the wrapper is "free" of the security informations */
12417         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12418                 method = mono_marshal_method_from_wrapper (method);
12419                 if (!method)
12420                         return FALSE;
12421         }
12422
12423         /* results are independant - zeroize both */
12424         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12425         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12426
12427         /* First we look for method-level attributes */
12428         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12429                 mono_class_init (method->klass);
12430
12431                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12432                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12433         }
12434
12435         /* Here we use (or create) the class declarative cache to look for demands */
12436         flags = mono_declsec_flags_from_class (method->klass);
12437         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12438                 mono_class_init (method->klass);
12439
12440                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12441                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12442         }
12443
12444         return result;
12445 }
12446
12447 /*
12448  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12449  *
12450  * @klass       The inherited class - this is the class that provides the security check (attributes)
12451  * @demans      
12452  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12453  * 
12454  * Note: Don't use the content of actions if the function return FALSE.
12455  */
12456 MonoBoolean
12457 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12458 {
12459         MonoBoolean result = FALSE;
12460         guint32 flags;
12461
12462         /* quick exit if no declarative security is present in the metadata */
12463         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12464                 return FALSE;
12465
12466         /* Here we use (or create) the class declarative cache to look for demands */
12467         flags = mono_declsec_flags_from_class (klass);
12468         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12469                 mono_class_init (klass);
12470                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12471
12472                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12473                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12474         }
12475
12476         return result;
12477 }
12478
12479 /*
12480  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12481  *
12482  * Note: Don't use the content of actions if the function return FALSE.
12483  */
12484 MonoBoolean
12485 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12486 {
12487         /* quick exit if no declarative security is present in the metadata */
12488         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12489                 return FALSE;
12490
12491         /* we want the original as the wrapper is "free" of the security informations */
12492         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12493                 method = mono_marshal_method_from_wrapper (method);
12494                 if (!method)
12495                         return FALSE;
12496         }
12497
12498         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12499                 mono_class_init (method->klass);
12500                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12501
12502                 return mono_declsec_get_method_demands_params (method, demands, 
12503                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12504         }
12505         return FALSE;
12506 }
12507
12508
12509 static MonoBoolean
12510 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12511 {
12512         guint32 cols [MONO_DECL_SECURITY_SIZE];
12513         MonoTableInfo *t;
12514         int i;
12515
12516         int index = mono_metadata_declsec_from_index (image, token);
12517         if (index == -1)
12518                 return FALSE;
12519
12520         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12521         for (i = index; i < t->rows; i++) {
12522                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12523
12524                 /* shortcut - index are ordered */
12525                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12526                         return FALSE;
12527
12528                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12529                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12530                         entry->blob = (char*) (metadata + 2);
12531                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12532                         return TRUE;
12533                 }
12534         }
12535
12536         return FALSE;
12537 }
12538
12539 MonoBoolean
12540 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12541 {
12542         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12543                 guint32 idx = mono_method_get_index (method);
12544                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12545                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12546                 return get_declsec_action (method->klass->image, idx, action, entry);
12547         }
12548         return FALSE;
12549 }
12550
12551 MonoBoolean
12552 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12553 {
12554         /* use cache */
12555         guint32 flags = mono_declsec_flags_from_class (klass);
12556         if (declsec_flags_map [action] & flags) {
12557                 guint32 idx = mono_metadata_token_index (klass->type_token);
12558                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12559                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12560                 return get_declsec_action (klass->image, idx, action, entry);
12561         }
12562         return FALSE;
12563 }
12564
12565 MonoBoolean
12566 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12567 {
12568         guint32 idx = 1; /* there is only one assembly */
12569         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12570         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12571
12572         return get_declsec_action (assembly->image, idx, action, entry);
12573 }
12574
12575 gboolean
12576 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12577 {
12578         MonoObject *res, *exc;
12579         void *params [1];
12580         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12581         static MonoMethod *method = NULL;
12582
12583         if (!System_Reflection_Emit_TypeBuilder) {
12584                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12585                 g_assert (System_Reflection_Emit_TypeBuilder);
12586         }
12587         if (method == NULL) {
12588                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12589                 g_assert (method);
12590         }
12591
12592         /* 
12593          * The result of mono_type_get_object () might be a System.MonoType but we
12594          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12595          */
12596         g_assert (mono_class_get_ref_info (klass));
12597         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12598
12599         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12600
12601         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12602         if (exc)
12603                 return FALSE;
12604         else
12605                 return *(MonoBoolean*)mono_object_unbox (res);
12606 }
12607
12608 /**
12609  * mono_reflection_type_get_type:
12610  * @reftype: the System.Type object
12611  *
12612  * Returns the MonoType* associated with the C# System.Type object @reftype.
12613  */
12614 MonoType*
12615 mono_reflection_type_get_type (MonoReflectionType *reftype)
12616 {
12617         g_assert (reftype);
12618
12619         return mono_reflection_type_get_handle (reftype);
12620 }
12621