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