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