BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 void
206 mono_reflection_init (void)
207 {
208 }
209
210 static void
211 sigbuffer_init (SigBuffer *buf, int size)
212 {
213         buf->buf = g_malloc (size);
214         buf->p = buf->buf;
215         buf->end = buf->buf + size;
216 }
217
218 static void
219 sigbuffer_make_room (SigBuffer *buf, int size)
220 {
221         if (buf->end - buf->p < size) {
222                 int new_size = buf->end - buf->buf + size + 32;
223                 char *p = g_realloc (buf->buf, new_size);
224                 size = buf->p - buf->buf;
225                 buf->buf = p;
226                 buf->p = p + size;
227                 buf->end = buf->buf + new_size;
228         }
229 }
230
231 static void
232 sigbuffer_add_value (SigBuffer *buf, guint32 val)
233 {
234         sigbuffer_make_room (buf, 6);
235         mono_metadata_encode_value (val, buf->p, &buf->p);
236 }
237
238 static void
239 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
240 {
241         sigbuffer_make_room (buf, 1);
242         buf->p [0] = val;
243         buf->p++;
244 }
245
246 static void
247 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
248 {
249         sigbuffer_make_room (buf, size);
250         memcpy (buf->p, p, size);
251         buf->p += size;
252 }
253
254 static void
255 sigbuffer_free (SigBuffer *buf)
256 {
257         g_free (buf->buf);
258 }
259
260 #ifndef DISABLE_REFLECTION_EMIT
261 /**
262  * mp_g_alloc:
263  *
264  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
265  * from the C heap.
266  */
267 static gpointer
268 image_g_malloc (MonoImage *image, guint size)
269 {
270         if (image)
271                 return mono_image_alloc (image, size);
272         else
273                 return g_malloc (size);
274 }
275 #endif /* !DISABLE_REFLECTION_EMIT */
276
277 /**
278  * image_g_alloc0:
279  *
280  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281  * from the C heap.
282  */
283 static gpointer
284 image_g_malloc0 (MonoImage *image, guint size)
285 {
286         if (image)
287                 return mono_image_alloc0 (image, size);
288         else
289                 return g_malloc0 (size);
290 }
291
292 #ifndef DISABLE_REFLECTION_EMIT
293 static char*
294 image_strdup (MonoImage *image, const char *s)
295 {
296         if (image)
297                 return mono_image_strdup (image, s);
298         else
299                 return g_strdup (s);
300 }
301 #endif
302
303 #define image_g_new(image,struct_type, n_structs)               \
304     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
305
306 #define image_g_new0(image,struct_type, n_structs)              \
307     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
308
309
310 static void
311 alloc_table (MonoDynamicTable *table, guint nrows)
312 {
313         table->rows = nrows;
314         g_assert (table->columns);
315         if (nrows + 1 >= table->alloc_rows) {
316                 while (nrows + 1 >= table->alloc_rows) {
317                         if (table->alloc_rows == 0)
318                                 table->alloc_rows = 16;
319                         else
320                                 table->alloc_rows *= 2;
321                 }
322
323                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
324         }
325 }
326
327 static void
328 make_room_in_stream (MonoDynamicStream *stream, int size)
329 {
330         if (size <= stream->alloc_size)
331                 return;
332         
333         while (stream->alloc_size <= size) {
334                 if (stream->alloc_size < 4096)
335                         stream->alloc_size = 4096;
336                 else
337                         stream->alloc_size *= 2;
338         }
339         
340         stream->data = g_realloc (stream->data, stream->alloc_size);
341 }
342
343 static guint32
344 string_heap_insert (MonoDynamicStream *sh, const char *str)
345 {
346         guint32 idx;
347         guint32 len;
348         gpointer oldkey, oldval;
349
350         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
351                 return GPOINTER_TO_UINT (oldval);
352
353         len = strlen (str) + 1;
354         idx = sh->index;
355         
356         make_room_in_stream (sh, idx + len);
357
358         /*
359          * We strdup the string even if we already copy them in sh->data
360          * so that the string pointers in the hash remain valid even if
361          * we need to realloc sh->data. We may want to avoid that later.
362          */
363         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
364         memcpy (sh->data + idx, str, len);
365         sh->index += len;
366         return idx;
367 }
368
369 static guint32
370 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
371 {
372         char *name = mono_string_to_utf8 (str);
373         guint32 idx;
374         idx = string_heap_insert (sh, name);
375         g_free (name);
376         return idx;
377 }
378
379 #ifndef DISABLE_REFLECTION_EMIT
380 static void
381 string_heap_init (MonoDynamicStream *sh)
382 {
383         sh->index = 0;
384         sh->alloc_size = 4096;
385         sh->data = g_malloc (4096);
386         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
387         string_heap_insert (sh, "");
388 }
389 #endif
390
391 static guint32
392 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
393 {
394         guint32 idx;
395         
396         make_room_in_stream (stream, stream->index + len);
397         memcpy (stream->data + stream->index, data, len);
398         idx = stream->index;
399         stream->index += len;
400         /* 
401          * align index? Not without adding an additional param that controls it since
402          * we may store a blob value in pieces.
403          */
404         return idx;
405 }
406
407 static guint32
408 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
409 {
410         guint32 idx;
411         
412         make_room_in_stream (stream, stream->index + len);
413         memset (stream->data + stream->index, 0, len);
414         idx = stream->index;
415         stream->index += len;
416         return idx;
417 }
418
419 static void
420 stream_data_align (MonoDynamicStream *stream)
421 {
422         char buf [4] = {0};
423         guint32 count = stream->index % 4;
424
425         /* we assume the stream data will be aligned */
426         if (count)
427                 mono_image_add_stream_data (stream, buf, 4 - count);
428 }
429
430 #ifndef DISABLE_REFLECTION_EMIT
431 static int
432 mono_blob_entry_hash (const char* str)
433 {
434         guint len, h;
435         const char *end;
436         len = mono_metadata_decode_blob_size (str, &str);
437         if (len > 0) {
438                 end = str + len;
439                 h = *str;
440                 for (str += 1; str < end; str++)
441                         h = (h << 5) - h + *str;
442                 return h;
443         } else {
444                 return 0;
445         }
446 }
447
448 static gboolean
449 mono_blob_entry_equal (const char *str1, const char *str2) {
450         int len, len2;
451         const char *end1;
452         const char *end2;
453         len = mono_metadata_decode_blob_size (str1, &end1);
454         len2 = mono_metadata_decode_blob_size (str2, &end2);
455         if (len != len2)
456                 return 0;
457         return memcmp (end1, end2, len) == 0;
458 }
459 #endif
460 static guint32
461 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
462 {
463         guint32 idx;
464         char *copy;
465         gpointer oldkey, oldval;
466
467         copy = g_malloc (s1+s2);
468         memcpy (copy, b1, s1);
469         memcpy (copy + s1, b2, s2);
470         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
471                 g_free (copy);
472                 idx = GPOINTER_TO_UINT (oldval);
473         } else {
474                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
475                 mono_image_add_stream_data (&assembly->blob, b2, s2);
476                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
477         }
478         return idx;
479 }
480
481 static guint32
482 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
483 {
484         char blob_size [8];
485         char *b = blob_size;
486         guint32 size = buf->p - buf->buf;
487         /* store length */
488         g_assert (size <= (buf->end - buf->buf));
489         mono_metadata_encode_value (size, b, &b);
490         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
491 }
492
493 /*
494  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
495  * dest may be misaligned.
496  */
497 static void
498 swap_with_size (char *dest, const char* val, int len, int nelem) {
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
500         int elem;
501
502         for (elem = 0; elem < nelem; ++elem) {
503                 switch (len) {
504                 case 1:
505                         *dest = *val;
506                         break;
507                 case 2:
508                         dest [0] = val [1];
509                         dest [1] = val [0];
510                         break;
511                 case 4:
512                         dest [0] = val [3];
513                         dest [1] = val [2];
514                         dest [2] = val [1];
515                         dest [3] = val [0];
516                         break;
517                 case 8:
518                         dest [0] = val [7];
519                         dest [1] = val [6];
520                         dest [2] = val [5];
521                         dest [3] = val [4];
522                         dest [4] = val [3];
523                         dest [5] = val [2];
524                         dest [6] = val [1];
525                         dest [7] = val [0];
526                         break;
527                 default:
528                         g_assert_not_reached ();
529                 }
530                 dest += len;
531                 val += len;
532         }
533 #else
534         memcpy (dest, val, len * nelem);
535 #endif
536 }
537
538 static guint32
539 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
540 {
541         char blob_size [64];
542         char *b = blob_size;
543         guint32 idx = 0, len;
544
545         len = str->length * 2;
546         mono_metadata_encode_value (len, b, &b);
547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
548         {
549                 char *swapped = g_malloc (2 * mono_string_length (str));
550                 const char *p = (const char*)mono_string_chars (str);
551
552                 swap_with_size (swapped, p, 2, mono_string_length (str));
553                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
554                 g_free (swapped);
555         }
556 #else
557         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
558 #endif
559         return idx;
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static MonoClass *
564 default_class_from_mono_type (MonoType *type)
565 {
566         switch (type->type) {
567         case MONO_TYPE_OBJECT:
568                 return mono_defaults.object_class;
569         case MONO_TYPE_VOID:
570                 return mono_defaults.void_class;
571         case MONO_TYPE_BOOLEAN:
572                 return mono_defaults.boolean_class;
573         case MONO_TYPE_CHAR:
574                 return mono_defaults.char_class;
575         case MONO_TYPE_I1:
576                 return mono_defaults.sbyte_class;
577         case MONO_TYPE_U1:
578                 return mono_defaults.byte_class;
579         case MONO_TYPE_I2:
580                 return mono_defaults.int16_class;
581         case MONO_TYPE_U2:
582                 return mono_defaults.uint16_class;
583         case MONO_TYPE_I4:
584                 return mono_defaults.int32_class;
585         case MONO_TYPE_U4:
586                 return mono_defaults.uint32_class;
587         case MONO_TYPE_I:
588                 return mono_defaults.int_class;
589         case MONO_TYPE_U:
590                 return mono_defaults.uint_class;
591         case MONO_TYPE_I8:
592                 return mono_defaults.int64_class;
593         case MONO_TYPE_U8:
594                 return mono_defaults.uint64_class;
595         case MONO_TYPE_R4:
596                 return mono_defaults.single_class;
597         case MONO_TYPE_R8:
598                 return mono_defaults.double_class;
599         case MONO_TYPE_STRING:
600                 return mono_defaults.string_class;
601         default:
602                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
603                 g_assert_not_reached ();
604         }
605         
606         return NULL;
607 }
608 #endif
609
610 /*
611  * mono_class_get_ref_info:
612  *
613  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
614  */
615 gpointer
616 mono_class_get_ref_info (MonoClass *klass)
617 {
618         if (klass->ref_info_handle == 0)
619                 return NULL;
620         else
621                 return mono_gchandle_get_target (klass->ref_info_handle);
622 }
623
624 void
625 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
626 {
627         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
628         g_assert (klass->ref_info_handle != 0);
629 }
630
631 void
632 mono_class_free_ref_info (MonoClass *klass)
633 {
634         if (klass->ref_info_handle) {
635                 mono_gchandle_free (klass->ref_info_handle);
636                 klass->ref_info_handle = 0;
637         }
638 }
639
640 static void
641 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
642 {
643         int i;
644         MonoGenericInst *class_inst;
645         MonoClass *klass;
646
647         g_assert (gclass);
648
649         class_inst = gclass->context.class_inst;
650
651         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
652         klass = gclass->container_class;
653         sigbuffer_add_value (buf, klass->byval_arg.type);
654         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
655
656         sigbuffer_add_value (buf, class_inst->type_argc);
657         for (i = 0; i < class_inst->type_argc; ++i)
658                 encode_type (assembly, class_inst->type_argv [i], buf);
659
660 }
661
662 static void
663 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
664 {
665         if (!type) {
666                 g_assert_not_reached ();
667                 return;
668         }
669                 
670         if (type->byref)
671                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
672
673         switch (type->type){
674         case MONO_TYPE_VOID:
675         case MONO_TYPE_BOOLEAN:
676         case MONO_TYPE_CHAR:
677         case MONO_TYPE_I1:
678         case MONO_TYPE_U1:
679         case MONO_TYPE_I2:
680         case MONO_TYPE_U2:
681         case MONO_TYPE_I4:
682         case MONO_TYPE_U4:
683         case MONO_TYPE_I8:
684         case MONO_TYPE_U8:
685         case MONO_TYPE_R4:
686         case MONO_TYPE_R8:
687         case MONO_TYPE_I:
688         case MONO_TYPE_U:
689         case MONO_TYPE_STRING:
690         case MONO_TYPE_OBJECT:
691         case MONO_TYPE_TYPEDBYREF:
692                 sigbuffer_add_value (buf, type->type);
693                 break;
694         case MONO_TYPE_PTR:
695                 sigbuffer_add_value (buf, type->type);
696                 encode_type (assembly, type->data.type, buf);
697                 break;
698         case MONO_TYPE_SZARRAY:
699                 sigbuffer_add_value (buf, type->type);
700                 encode_type (assembly, &type->data.klass->byval_arg, buf);
701                 break;
702         case MONO_TYPE_VALUETYPE:
703         case MONO_TYPE_CLASS: {
704                 MonoClass *k = mono_class_from_mono_type (type);
705
706                 if (k->generic_container) {
707                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
708                         encode_generic_class (assembly, gclass, buf);
709                 } else {
710                         /*
711                          * Make sure we use the correct type.
712                          */
713                         sigbuffer_add_value (buf, k->byval_arg.type);
714                         /*
715                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
716                          * otherwise two typerefs could point to the same type, leading to
717                          * verification errors.
718                          */
719                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
720                 }
721                 break;
722         }
723         case MONO_TYPE_ARRAY:
724                 sigbuffer_add_value (buf, type->type);
725                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
726                 sigbuffer_add_value (buf, type->data.array->rank);
727                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
728                 sigbuffer_add_value (buf, 0);
729                 break;
730         case MONO_TYPE_GENERICINST:
731                 encode_generic_class (assembly, type->data.generic_class, buf);
732                 break;
733         case MONO_TYPE_VAR:
734         case MONO_TYPE_MVAR:
735                 sigbuffer_add_value (buf, type->type);
736                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
737                 break;
738         default:
739                 g_error ("need to encode type %x", type->type);
740         }
741 }
742
743 static void
744 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
745 {
746         if (!type) {
747                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
748                 return;
749         }
750
751         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
752 }
753
754 static void
755 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
756 {
757         int i;
758
759         if (modreq) {
760                 for (i = 0; i < mono_array_length (modreq); ++i) {
761                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
762                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
763                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
764                 }
765         }
766         if (modopt) {
767                 for (i = 0; i < mono_array_length (modopt); ++i) {
768                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
769                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
770                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
771                 }
772         }
773 }
774
775 #ifndef DISABLE_REFLECTION_EMIT
776 static guint32
777 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
778 {
779         SigBuffer buf;
780         int i;
781         guint32 nparams =  sig->param_count;
782         guint32 idx;
783
784         if (!assembly->save)
785                 return 0;
786
787         sigbuffer_init (&buf, 32);
788         /*
789          * FIXME: vararg, explicit_this, differenc call_conv values...
790          */
791         idx = sig->call_convention;
792         if (sig->hasthis)
793                 idx |= 0x20; /* hasthis */
794         if (sig->generic_param_count)
795                 idx |= 0x10; /* generic */
796         sigbuffer_add_byte (&buf, idx);
797         if (sig->generic_param_count)
798                 sigbuffer_add_value (&buf, sig->generic_param_count);
799         sigbuffer_add_value (&buf, nparams);
800         encode_type (assembly, sig->ret, &buf);
801         for (i = 0; i < nparams; ++i) {
802                 if (i == sig->sentinelpos)
803                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804                 encode_type (assembly, sig->params [i], &buf);
805         }
806         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807         sigbuffer_free (&buf);
808         return idx;
809 }
810 #endif
811
812 static guint32
813 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
814 {
815         /*
816          * FIXME: reuse code from method_encode_signature().
817          */
818         SigBuffer buf;
819         int i;
820         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
821         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
822         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
823         guint32 idx;
824
825         sigbuffer_init (&buf, 32);
826         /* LAMESPEC: all the call conv spec is foobared */
827         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
828         if (mb->call_conv & 2)
829                 idx |= 0x5; /* vararg */
830         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
831                 idx |= 0x20; /* hasthis */
832         if (ngparams)
833                 idx |= 0x10; /* generic */
834         sigbuffer_add_byte (&buf, idx);
835         if (ngparams)
836                 sigbuffer_add_value (&buf, ngparams);
837         sigbuffer_add_value (&buf, nparams + notypes);
838         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
839         encode_reflection_type (assembly, mb->rtype, &buf);
840         for (i = 0; i < nparams; ++i) {
841                 MonoArray *modreq = NULL;
842                 MonoArray *modopt = NULL;
843                 MonoReflectionType *pt;
844
845                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
846                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
847                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
848                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
849                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
850                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
851                 encode_reflection_type (assembly, pt, &buf);
852         }
853         if (notypes)
854                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
855         for (i = 0; i < notypes; ++i) {
856                 MonoReflectionType *pt;
857
858                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
859                 encode_reflection_type (assembly, pt, &buf);
860         }
861
862         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
863         sigbuffer_free (&buf);
864         return idx;
865 }
866
867 static guint32
868 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
869 {
870         MonoDynamicTable *table;
871         guint32 *values;
872         guint32 idx, sig_idx;
873         guint nl = mono_array_length (ilgen->locals);
874         SigBuffer buf;
875         int i;
876
877         sigbuffer_init (&buf, 32);
878         sigbuffer_add_value (&buf, 0x07);
879         sigbuffer_add_value (&buf, nl);
880         for (i = 0; i < nl; ++i) {
881                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
882                 
883                 if (lb->is_pinned)
884                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
885                 
886                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
887         }
888         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
889         sigbuffer_free (&buf);
890
891         if (assembly->standalonesig_cache == NULL)
892                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
893         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
894         if (idx)
895                 return idx;
896
897         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
898         idx = table->next_idx ++;
899         table->rows ++;
900         alloc_table (table, table->rows);
901         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
902
903         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
904
905         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
906
907         return idx;
908 }
909
910 static guint32
911 method_count_clauses (MonoReflectionILGen *ilgen)
912 {
913         guint32 num_clauses = 0;
914         int i;
915
916         MonoILExceptionInfo *ex_info;
917         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
918                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
919                 if (ex_info->handlers)
920                         num_clauses += mono_array_length (ex_info->handlers);
921                 else
922                         num_clauses++;
923         }
924
925         return num_clauses;
926 }
927
928 #ifndef DISABLE_REFLECTION_EMIT
929 static MonoExceptionClause*
930 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
931 {
932         MonoExceptionClause *clauses;
933         MonoExceptionClause *clause;
934         MonoILExceptionInfo *ex_info;
935         MonoILExceptionBlock *ex_block;
936         guint32 finally_start;
937         int i, j, clause_index;;
938
939         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
940
941         clause_index = 0;
942         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
943                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
944                 finally_start = ex_info->start + ex_info->len;
945                 if (!ex_info->handlers)
946                         continue;
947                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
948                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
949                         clause = &(clauses [clause_index]);
950
951                         clause->flags = ex_block->type;
952                         clause->try_offset = ex_info->start;
953
954                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
955                                 clause->try_len = finally_start - ex_info->start;
956                         else
957                                 clause->try_len = ex_info->len;
958                         clause->handler_offset = ex_block->start;
959                         clause->handler_len = ex_block->len;
960                         if (ex_block->extype) {
961                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
962                         } else {
963                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
964                                         clause->data.filter_offset = ex_block->filter_offset;
965                                 else
966                                         clause->data.filter_offset = 0;
967                         }
968                         finally_start = ex_block->start + ex_block->len;
969
970                         clause_index ++;
971                 }
972         }
973
974         return clauses;
975 }
976 #endif /* !DISABLE_REFLECTION_EMIT */
977
978 static guint32
979 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
980 {
981         char flags = 0;
982         guint32 idx;
983         guint32 code_size;
984         gint32 max_stack, i;
985         gint32 num_locals = 0;
986         gint32 num_exception = 0;
987         gint maybe_small;
988         guint32 fat_flags;
989         char fat_header [12];
990         guint32 int_value;
991         guint16 short_value;
992         guint32 local_sig = 0;
993         guint32 header_size = 12;
994         MonoArray *code;
995
996         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
997                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
998                 return 0;
999
1000         /*if (mb->name)
1001                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1002         if (mb->ilgen) {
1003                 code = mb->ilgen->code;
1004                 code_size = mb->ilgen->code_len;
1005                 max_stack = mb->ilgen->max_stack;
1006                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1007                 if (mb->ilgen->ex_handlers)
1008                         num_exception = method_count_clauses (mb->ilgen);
1009         } else {
1010                 code = mb->code;
1011                 if (code == NULL){
1012                         char *name = mono_string_to_utf8 (mb->name);
1013                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1014                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1015                         g_free (str);
1016                         g_free (name);
1017                         mono_raise_exception (exception);
1018                 }
1019
1020                 code_size = mono_array_length (code);
1021                 max_stack = 8; /* we probably need to run a verifier on the code... */
1022         }
1023
1024         stream_data_align (&assembly->code);
1025
1026         /* check for exceptions, maxstack, locals */
1027         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1028         if (maybe_small) {
1029                 if (code_size < 64 && !(code_size & 1)) {
1030                         flags = (code_size << 2) | 0x2;
1031                 } else if (code_size < 32 && (code_size & 1)) {
1032                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1033                 } else {
1034                         goto fat_header;
1035                 }
1036                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1037                 /* add to the fixup todo list */
1038                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1039                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1040                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1041                 return assembly->text_rva + idx;
1042         } 
1043 fat_header:
1044         if (num_locals)
1045                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1046         /* 
1047          * FIXME: need to set also the header size in fat_flags.
1048          * (and more sects and init locals flags)
1049          */
1050         fat_flags =  0x03;
1051         if (num_exception)
1052                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1053         if (mb->init_locals)
1054                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1055         fat_header [0] = fat_flags;
1056         fat_header [1] = (header_size / 4 ) << 4;
1057         short_value = GUINT16_TO_LE (max_stack);
1058         memcpy (fat_header + 2, &short_value, 2);
1059         int_value = GUINT32_TO_LE (code_size);
1060         memcpy (fat_header + 4, &int_value, 4);
1061         int_value = GUINT32_TO_LE (local_sig);
1062         memcpy (fat_header + 8, &int_value, 4);
1063         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1064         /* add to the fixup todo list */
1065         if (mb->ilgen && mb->ilgen->num_token_fixups)
1066                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1067         
1068         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1069         if (num_exception) {
1070                 unsigned char sheader [4];
1071                 MonoILExceptionInfo * ex_info;
1072                 MonoILExceptionBlock * ex_block;
1073                 int j;
1074
1075                 stream_data_align (&assembly->code);
1076                 /* always use fat format for now */
1077                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1078                 num_exception *= 6 * sizeof (guint32);
1079                 num_exception += 4; /* include the size of the header */
1080                 sheader [1] = num_exception & 0xff;
1081                 sheader [2] = (num_exception >> 8) & 0xff;
1082                 sheader [3] = (num_exception >> 16) & 0xff;
1083                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1084                 /* fat header, so we are already aligned */
1085                 /* reverse order */
1086                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1087                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1088                         if (ex_info->handlers) {
1089                                 int finally_start = ex_info->start + ex_info->len;
1090                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1091                                         guint32 val;
1092                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1093                                         /* the flags */
1094                                         val = GUINT32_TO_LE (ex_block->type);
1095                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1096                                         /* try offset */
1097                                         val = GUINT32_TO_LE (ex_info->start);
1098                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1099                                         /* need fault, too, probably */
1100                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1101                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1102                                         else
1103                                                 val = GUINT32_TO_LE (ex_info->len);
1104                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105                                         /* handler offset */
1106                                         val = GUINT32_TO_LE (ex_block->start);
1107                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108                                         /* handler len */
1109                                         val = GUINT32_TO_LE (ex_block->len);
1110                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1111                                         finally_start = ex_block->start + ex_block->len;
1112                                         if (ex_block->extype) {
1113                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1114                                         } else {
1115                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1116                                                         val = ex_block->filter_offset;
1117                                                 else
1118                                                         val = 0;
1119                                         }
1120                                         val = GUINT32_TO_LE (val);
1121                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1123                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1124                                 }
1125                         } else {
1126                                 g_error ("No clauses for ex info block %d", i);
1127                         }
1128                 }
1129         }
1130         return assembly->text_rva + idx;
1131 }
1132
1133 static guint32
1134 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1135 {
1136         int i;
1137         MonoDynamicTable *table;
1138         guint32 *values;
1139         
1140         table = &assembly->tables [table_idx];
1141
1142         g_assert (col < table->columns);
1143
1144         values = table->values + table->columns;
1145         for (i = 1; i <= table->rows; ++i) {
1146                 if (values [col] == token)
1147                         return i;
1148                 values += table->columns;
1149         }
1150         return 0;
1151 }
1152
1153 /*
1154  * LOCKING: Acquires the loader lock. 
1155  */
1156 static MonoCustomAttrInfo*
1157 lookup_custom_attr (MonoImage *image, gpointer member)
1158 {
1159         MonoCustomAttrInfo* res;
1160
1161         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1162
1163         if (!res)
1164                 return NULL;
1165
1166         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1167         res->cached = 0;
1168         return res;
1169 }
1170
1171 static gboolean
1172 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1173 {
1174         /* FIXME: Need to do more checks */
1175         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1176                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1177
1178                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1179                         return FALSE;
1180         }
1181
1182         return TRUE;
1183 }
1184
1185 static MonoCustomAttrInfo*
1186 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1187 {
1188         int i, index, count, not_visible;
1189         MonoCustomAttrInfo *ainfo;
1190         MonoReflectionCustomAttr *cattr;
1191
1192         if (!cattrs)
1193                 return NULL;
1194         /* FIXME: check in assembly the Run flag is set */
1195
1196         count = mono_array_length (cattrs);
1197
1198         /* Skip nonpublic attributes since MS.NET seems to do the same */
1199         /* FIXME: This needs to be done more globally */
1200         not_visible = 0;
1201         for (i = 0; i < count; ++i) {
1202                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1203                 if (!custom_attr_visible (image, cattr))
1204                         not_visible ++;
1205         }
1206         count -= not_visible;
1207
1208         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1209
1210         ainfo->image = image;
1211         ainfo->num_attrs = count;
1212         ainfo->cached = alloc_img != NULL;
1213         index = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (custom_attr_visible (image, cattr)) {
1217                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1218                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1219                         ainfo->attrs [index].ctor = cattr->ctor->method;
1220                         ainfo->attrs [index].data = saved;
1221                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1222                         index ++;
1223                 }
1224         }
1225
1226         return ainfo;
1227 }
1228
1229 #ifndef DISABLE_REFLECTION_EMIT
1230 /*
1231  * LOCKING: Acquires the loader lock. 
1232  */
1233 static void
1234 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1235 {
1236         MonoCustomAttrInfo *ainfo, *tmp;
1237
1238         if (!cattrs || !mono_array_length (cattrs))
1239                 return;
1240
1241         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1242
1243         mono_loader_lock ();
1244         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1245         if (tmp)
1246                 mono_custom_attrs_free (tmp);
1247         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1248         mono_loader_unlock ();
1249
1250 }
1251 #endif
1252
1253 void
1254 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1255 {
1256         if (!ainfo->cached)
1257                 g_free (ainfo);
1258 }
1259
1260 /*
1261  * idx is the table index of the object
1262  * type is one of MONO_CUSTOM_ATTR_*
1263  */
1264 static void
1265 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1266 {
1267         MonoDynamicTable *table;
1268         MonoReflectionCustomAttr *cattr;
1269         guint32 *values;
1270         guint32 count, i, token;
1271         char blob_size [6];
1272         char *p = blob_size;
1273         
1274         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1275         if (!cattrs)
1276                 return;
1277         count = mono_array_length (cattrs);
1278         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1279         table->rows += count;
1280         alloc_table (table, table->rows);
1281         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1282         idx <<= MONO_CUSTOM_ATTR_BITS;
1283         idx |= type;
1284         for (i = 0; i < count; ++i) {
1285                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1286                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1287                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1288                 type = mono_metadata_token_index (token);
1289                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1290                 switch (mono_metadata_token_table (token)) {
1291                 case MONO_TABLE_METHOD:
1292                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1293                         break;
1294                 case MONO_TABLE_MEMBERREF:
1295                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1296                         break;
1297                 default:
1298                         g_warning ("got wrong token in custom attr");
1299                         continue;
1300                 }
1301                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1302                 p = blob_size;
1303                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1304                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1305                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1306                 values += MONO_CUSTOM_ATTR_SIZE;
1307                 ++table->next_idx;
1308         }
1309 }
1310
1311 static void
1312 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1313 {
1314         MonoDynamicTable *table;
1315         guint32 *values;
1316         guint32 count, i, idx;
1317         MonoReflectionPermissionSet *perm;
1318
1319         if (!permissions)
1320                 return;
1321
1322         count = mono_array_length (permissions);
1323         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1324         table->rows += count;
1325         alloc_table (table, table->rows);
1326
1327         for (i = 0; i < mono_array_length (permissions); ++i) {
1328                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1329
1330                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1331
1332                 idx = mono_metadata_token_index (parent_token);
1333                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1334                 switch (mono_metadata_token_table (parent_token)) {
1335                 case MONO_TABLE_TYPEDEF:
1336                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1337                         break;
1338                 case MONO_TABLE_METHOD:
1339                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1340                         break;
1341                 case MONO_TABLE_ASSEMBLY:
1342                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1343                         break;
1344                 default:
1345                         g_assert_not_reached ();
1346                 }
1347
1348                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1349                 values [MONO_DECL_SECURITY_PARENT] = idx;
1350                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1351
1352                 ++table->next_idx;
1353         }
1354 }
1355
1356 /*
1357  * Fill in the MethodDef and ParamDef tables for a method.
1358  * This is used for both normal methods and constructors.
1359  */
1360 static void
1361 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1362 {
1363         MonoDynamicTable *table;
1364         guint32 *values;
1365         guint i, count;
1366
1367         /* room in this table is already allocated */
1368         table = &assembly->tables [MONO_TABLE_METHOD];
1369         *mb->table_idx = table->next_idx ++;
1370         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1371         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1372         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1373         values [MONO_METHOD_FLAGS] = mb->attrs;
1374         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1375         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1376         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1377         
1378         table = &assembly->tables [MONO_TABLE_PARAM];
1379         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1380
1381         mono_image_add_decl_security (assembly, 
1382                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1383
1384         if (mb->pinfo) {
1385                 MonoDynamicTable *mtable;
1386                 guint32 *mvalues;
1387                 
1388                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1389                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1390                 
1391                 count = 0;
1392                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1393                         if (mono_array_get (mb->pinfo, gpointer, i))
1394                                 count++;
1395                 }
1396                 table->rows += count;
1397                 alloc_table (table, table->rows);
1398                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1399                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1400                         MonoReflectionParamBuilder *pb;
1401                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1402                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1403                                 values [MONO_PARAM_SEQUENCE] = i;
1404                                 if (pb->name != NULL) {
1405                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1406                                 } else {
1407                                         values [MONO_PARAM_NAME] = 0;
1408                                 }
1409                                 values += MONO_PARAM_SIZE;
1410                                 if (pb->marshal_info) {
1411                                         mtable->rows++;
1412                                         alloc_table (mtable, mtable->rows);
1413                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1414                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1415                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1416                                 }
1417                                 pb->table_idx = table->next_idx++;
1418                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1419                                         guint32 field_type = 0;
1420                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1421                                         mtable->rows ++;
1422                                         alloc_table (mtable, mtable->rows);
1423                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1424                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1425                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1426                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1427                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1428                                 }
1429                         }
1430                 }
1431         }
1432 }
1433
1434 #ifndef DISABLE_REFLECTION_EMIT
1435 static void
1436 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1437 {
1438         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1439
1440         rmb->ilgen = mb->ilgen;
1441         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1442         rmb->parameters = mb->parameters;
1443         rmb->generic_params = mb->generic_params;
1444         rmb->generic_container = mb->generic_container;
1445         rmb->opt_types = NULL;
1446         rmb->pinfo = mb->pinfo;
1447         rmb->attrs = mb->attrs;
1448         rmb->iattrs = mb->iattrs;
1449         rmb->call_conv = mb->call_conv;
1450         rmb->code = mb->code;
1451         rmb->type = mb->type;
1452         rmb->name = mb->name;
1453         rmb->table_idx = &mb->table_idx;
1454         rmb->init_locals = mb->init_locals;
1455         rmb->skip_visibility = FALSE;
1456         rmb->return_modreq = mb->return_modreq;
1457         rmb->return_modopt = mb->return_modopt;
1458         rmb->param_modreq = mb->param_modreq;
1459         rmb->param_modopt = mb->param_modopt;
1460         rmb->permissions = mb->permissions;
1461         rmb->mhandle = mb->mhandle;
1462         rmb->nrefs = 0;
1463         rmb->refs = NULL;
1464
1465         if (mb->dll) {
1466                 rmb->charset = mb->charset;
1467                 rmb->extra_flags = mb->extra_flags;
1468                 rmb->native_cc = mb->native_cc;
1469                 rmb->dllentry = mb->dllentry;
1470                 rmb->dll = mb->dll;
1471         }
1472 }
1473
1474 static void
1475 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1476 {
1477         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1478
1479         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1480
1481         rmb->ilgen = mb->ilgen;
1482         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1483         rmb->parameters = mb->parameters;
1484         rmb->generic_params = NULL;
1485         rmb->generic_container = NULL;
1486         rmb->opt_types = NULL;
1487         rmb->pinfo = mb->pinfo;
1488         rmb->attrs = mb->attrs;
1489         rmb->iattrs = mb->iattrs;
1490         rmb->call_conv = mb->call_conv;
1491         rmb->code = NULL;
1492         rmb->type = mb->type;
1493         rmb->name = mono_string_new (mono_domain_get (), name);
1494         rmb->table_idx = &mb->table_idx;
1495         rmb->init_locals = mb->init_locals;
1496         rmb->skip_visibility = FALSE;
1497         rmb->return_modreq = NULL;
1498         rmb->return_modopt = NULL;
1499         rmb->param_modreq = mb->param_modreq;
1500         rmb->param_modopt = mb->param_modopt;
1501         rmb->permissions = mb->permissions;
1502         rmb->mhandle = mb->mhandle;
1503         rmb->nrefs = 0;
1504         rmb->refs = NULL;
1505 }
1506
1507 static void
1508 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1509 {
1510         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1511
1512         rmb->ilgen = mb->ilgen;
1513         rmb->rtype = mb->rtype;
1514         rmb->parameters = mb->parameters;
1515         rmb->generic_params = NULL;
1516         rmb->generic_container = NULL;
1517         rmb->opt_types = NULL;
1518         rmb->pinfo = NULL;
1519         rmb->attrs = mb->attrs;
1520         rmb->iattrs = 0;
1521         rmb->call_conv = mb->call_conv;
1522         rmb->code = NULL;
1523         rmb->type = (MonoObject *) mb->owner;
1524         rmb->name = mb->name;
1525         rmb->table_idx = NULL;
1526         rmb->init_locals = mb->init_locals;
1527         rmb->skip_visibility = mb->skip_visibility;
1528         rmb->return_modreq = NULL;
1529         rmb->return_modopt = NULL;
1530         rmb->param_modreq = NULL;
1531         rmb->param_modopt = NULL;
1532         rmb->permissions = NULL;
1533         rmb->mhandle = mb->mhandle;
1534         rmb->nrefs = 0;
1535         rmb->refs = NULL;
1536 }       
1537 #endif
1538
1539 static void
1540 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1541 {
1542         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1543         MonoDynamicTable *table;
1544         guint32 *values;
1545         guint32 tok;
1546
1547         if (!mb->override_method)
1548                 return;
1549
1550         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1551         table->rows ++;
1552         alloc_table (table, table->rows);
1553         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1554         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1555         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1556
1557         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1558         switch (mono_metadata_token_table (tok)) {
1559         case MONO_TABLE_MEMBERREF:
1560                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1561                 break;
1562         case MONO_TABLE_METHOD:
1563                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1564                 break;
1565         default:
1566                 g_assert_not_reached ();
1567         }
1568         values [MONO_METHODIMPL_DECLARATION] = tok;
1569 }
1570
1571 #ifndef DISABLE_REFLECTION_EMIT
1572 static void
1573 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1574 {
1575         MonoDynamicTable *table;
1576         guint32 *values;
1577         ReflectionMethodBuilder rmb;
1578         int i;
1579
1580         reflection_methodbuilder_from_method_builder (&rmb, mb);
1581
1582         mono_image_basic_method (&rmb, assembly);
1583         mb->table_idx = *rmb.table_idx;
1584
1585         if (mb->dll) { /* It's a P/Invoke method */
1586                 guint32 moduleref;
1587                 /* map CharSet values to on-disk values */
1588                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1589                 int extra_flags = mb->extra_flags;
1590                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1591                 table->rows ++;
1592                 alloc_table (table, table->rows);
1593                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1594                 
1595                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1596                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1597                 if (mb->dllentry)
1598                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1599                 else
1600                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1601                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1602                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1603                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1604                         table->rows ++;
1605                         alloc_table (table, table->rows);
1606                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1607                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1608                 }
1609         }
1610
1611         if (mb->generic_params) {
1612                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1613                 table->rows += mono_array_length (mb->generic_params);
1614                 alloc_table (table, table->rows);
1615                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1616                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1617
1618                         mono_image_get_generic_param_info (
1619                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1620                 }
1621         }
1622
1623 }
1624
1625 static void
1626 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1627 {
1628         ReflectionMethodBuilder rmb;
1629
1630         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1631
1632         mono_image_basic_method (&rmb, assembly);
1633         mb->table_idx = *rmb.table_idx;
1634 }
1635 #endif
1636
1637 static char*
1638 type_get_fully_qualified_name (MonoType *type)
1639 {
1640         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1641 }
1642
1643 static char*
1644 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1645         MonoClass *klass;
1646         MonoAssembly *ta;
1647
1648         klass = mono_class_from_mono_type (type);
1649         if (!klass) 
1650                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1651         ta = klass->image->assembly;
1652         if (ta->dynamic || (ta == ass)) {
1653                 if (klass->generic_class || klass->generic_container)
1654                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1655                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1656                 else
1657                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1658         }
1659
1660         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1661 }
1662
1663 #ifndef DISABLE_REFLECTION_EMIT
1664 /*field_image is the image to which the eventual custom mods have been encoded against*/
1665 static guint32
1666 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1667 {
1668         SigBuffer buf;
1669         guint32 idx, i, token;
1670
1671         if (!assembly->save)
1672                 return 0;
1673
1674         sigbuffer_init (&buf, 32);
1675         
1676         sigbuffer_add_value (&buf, 0x06);
1677         /* encode custom attributes before the type */
1678         if (type->num_mods) {
1679                 for (i = 0; i < type->num_mods; ++i) {
1680                         if (field_image) {
1681                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1682                                 g_assert (class);
1683                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1684                         } else {
1685                                 token = type->modifiers [i].token;
1686                         }
1687
1688                         if (type->modifiers [i].required)
1689                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1690                         else
1691                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1692
1693                         sigbuffer_add_value (&buf, token);
1694                 }
1695         }
1696         encode_type (assembly, type, &buf);
1697         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1698         sigbuffer_free (&buf);
1699         return idx;
1700 }
1701 #endif
1702
1703 static guint32
1704 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1705 {
1706         SigBuffer buf;
1707         guint32 idx;
1708         guint32 typespec = 0;
1709         MonoType *type;
1710         MonoClass *class;
1711
1712         init_type_builder_generics (fb->type);
1713
1714         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1715         class = mono_class_from_mono_type (type);
1716
1717         sigbuffer_init (&buf, 32);
1718         
1719         sigbuffer_add_value (&buf, 0x06);
1720         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1721         /* encode custom attributes before the type */
1722
1723         if (class->generic_container)
1724                 typespec = create_typespec (assembly, type);
1725
1726         if (typespec) {
1727                 MonoGenericClass *gclass;
1728                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1729                 encode_generic_class (assembly, gclass, &buf);
1730         } else {
1731                 encode_type (assembly, type, &buf);
1732         }
1733         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1734         sigbuffer_free (&buf);
1735         return idx;
1736 }
1737
1738 static guint32
1739 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1740         char blob_size [64];
1741         char *b = blob_size;
1742         char *p, *box_val;
1743         char* buf;
1744         guint32 idx = 0, len = 0, dummy = 0;
1745 #ifdef ARM_FPU_FPA
1746 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1747         guint32 fpa_double [2];
1748         guint32 *fpa_p;
1749 #endif
1750 #endif
1751         
1752         p = buf = g_malloc (64);
1753         if (!val) {
1754                 *ret_type = MONO_TYPE_CLASS;
1755                 len = 4;
1756                 box_val = (char*)&dummy;
1757         } else {
1758                 box_val = ((char*)val) + sizeof (MonoObject);
1759                 *ret_type = val->vtable->klass->byval_arg.type;
1760         }
1761 handle_enum:
1762         switch (*ret_type) {
1763         case MONO_TYPE_BOOLEAN:
1764         case MONO_TYPE_U1:
1765         case MONO_TYPE_I1:
1766                 len = 1;
1767                 break;
1768         case MONO_TYPE_CHAR:
1769         case MONO_TYPE_U2:
1770         case MONO_TYPE_I2:
1771                 len = 2;
1772                 break;
1773         case MONO_TYPE_U4:
1774         case MONO_TYPE_I4:
1775         case MONO_TYPE_R4:
1776                 len = 4;
1777                 break;
1778         case MONO_TYPE_U8:
1779         case MONO_TYPE_I8:
1780                 len = 8;
1781                 break;
1782         case MONO_TYPE_R8:
1783                 len = 8;
1784 #ifdef ARM_FPU_FPA
1785 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1786                 fpa_p = (guint32*)box_val;
1787                 fpa_double [0] = fpa_p [1];
1788                 fpa_double [1] = fpa_p [0];
1789                 box_val = (char*)fpa_double;
1790 #endif
1791 #endif
1792                 break;
1793         case MONO_TYPE_VALUETYPE: {
1794                 MonoClass *klass = val->vtable->klass;
1795                 
1796                 if (klass->enumtype) {
1797                         *ret_type = mono_class_enum_basetype (klass)->type;
1798                         goto handle_enum;
1799                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1800                         len = 8;
1801                 } else 
1802                         g_error ("we can't encode valuetypes, we should have never reached this line");
1803                 break;
1804         }
1805         case MONO_TYPE_CLASS:
1806                 break;
1807         case MONO_TYPE_STRING: {
1808                 MonoString *str = (MonoString*)val;
1809                 /* there is no signature */
1810                 len = str->length * 2;
1811                 mono_metadata_encode_value (len, b, &b);
1812 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1813                 {
1814                         char *swapped = g_malloc (2 * mono_string_length (str));
1815                         const char *p = (const char*)mono_string_chars (str);
1816
1817                         swap_with_size (swapped, p, 2, mono_string_length (str));
1818                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1819                         g_free (swapped);
1820                 }
1821 #else
1822                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1823 #endif
1824
1825                 g_free (buf);
1826                 return idx;
1827         }
1828         case MONO_TYPE_GENERICINST:
1829                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1830                 goto handle_enum;
1831         default:
1832                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1833         }
1834
1835         /* there is no signature */
1836         mono_metadata_encode_value (len, b, &b);
1837 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1838         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1839         swap_with_size (blob_size, box_val, len, 1);
1840         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1841 #else
1842         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1843 #endif
1844
1845         g_free (buf);
1846         return idx;
1847 }
1848
1849 static guint32
1850 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1851         char *str;
1852         SigBuffer buf;
1853         guint32 idx, len;
1854
1855         sigbuffer_init (&buf, 32);
1856
1857         sigbuffer_add_value (&buf, minfo->type);
1858
1859         switch (minfo->type) {
1860         case MONO_NATIVE_BYVALTSTR:
1861         case MONO_NATIVE_BYVALARRAY:
1862                 sigbuffer_add_value (&buf, minfo->count);
1863                 break;
1864         case MONO_NATIVE_LPARRAY:
1865                 if (minfo->eltype || minfo->has_size) {
1866                         sigbuffer_add_value (&buf, minfo->eltype);
1867                         if (minfo->has_size) {
1868                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1869                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1870
1871                                 /* LAMESPEC: ElemMult is undocumented */
1872                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1873                         }
1874                 }
1875                 break;
1876         case MONO_NATIVE_SAFEARRAY:
1877                 if (minfo->eltype)
1878                         sigbuffer_add_value (&buf, minfo->eltype);
1879                 break;
1880         case MONO_NATIVE_CUSTOM:
1881                 if (minfo->guid) {
1882                         str = mono_string_to_utf8 (minfo->guid);
1883                         len = strlen (str);
1884                         sigbuffer_add_value (&buf, len);
1885                         sigbuffer_add_mem (&buf, str, len);
1886                         g_free (str);
1887                 } else {
1888                         sigbuffer_add_value (&buf, 0);
1889                 }
1890                 /* native type name */
1891                 sigbuffer_add_value (&buf, 0);
1892                 /* custom marshaler type name */
1893                 if (minfo->marshaltype || minfo->marshaltyperef) {
1894                         if (minfo->marshaltyperef)
1895                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1896                         else
1897                                 str = mono_string_to_utf8 (minfo->marshaltype);
1898                         len = strlen (str);
1899                         sigbuffer_add_value (&buf, len);
1900                         sigbuffer_add_mem (&buf, str, len);
1901                         g_free (str);
1902                 } else {
1903                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1904                         sigbuffer_add_value (&buf, 0);
1905                 }
1906                 if (minfo->mcookie) {
1907                         str = mono_string_to_utf8 (minfo->mcookie);
1908                         len = strlen (str);
1909                         sigbuffer_add_value (&buf, len);
1910                         sigbuffer_add_mem (&buf, str, len);
1911                         g_free (str);
1912                 } else {
1913                         sigbuffer_add_value (&buf, 0);
1914                 }
1915                 break;
1916         default:
1917                 break;
1918         }
1919         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1920         sigbuffer_free (&buf);
1921         return idx;
1922 }
1923
1924 static void
1925 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1926 {
1927         MonoDynamicTable *table;
1928         guint32 *values;
1929
1930         /* maybe this fixup should be done in the C# code */
1931         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1932                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1933         table = &assembly->tables [MONO_TABLE_FIELD];
1934         fb->table_idx = table->next_idx ++;
1935         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1936         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1937         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1938         values [MONO_FIELD_FLAGS] = fb->attrs;
1939         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1940
1941         if (fb->offset != -1) {
1942                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1943                 table->rows ++;
1944                 alloc_table (table, table->rows);
1945                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1946                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1947                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1948         }
1949         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1950                 guint32 field_type = 0;
1951                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1952                 table->rows ++;
1953                 alloc_table (table, table->rows);
1954                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1955                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1956                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1957                 values [MONO_CONSTANT_TYPE] = field_type;
1958                 values [MONO_CONSTANT_PADDING] = 0;
1959         }
1960         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1961                 guint32 rva_idx;
1962                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1963                 table->rows ++;
1964                 alloc_table (table, table->rows);
1965                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1966                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1967                 /*
1968                  * We store it in the code section because it's simpler for now.
1969                  */
1970                 if (fb->rva_data) {
1971                         if (mono_array_length (fb->rva_data) >= 10)
1972                                 stream_data_align (&assembly->code);
1973                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1974                 } else
1975                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1976                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1977         }
1978         if (fb->marshal_info) {
1979                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1980                 table->rows ++;
1981                 alloc_table (table, table->rows);
1982                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1983                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1984                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1985         }
1986 }
1987
1988 static guint32
1989 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1990 {
1991         SigBuffer buf;
1992         guint32 nparams = 0;
1993         MonoReflectionMethodBuilder *mb = fb->get_method;
1994         MonoReflectionMethodBuilder *smb = fb->set_method;
1995         guint32 idx, i;
1996
1997         if (mb && mb->parameters)
1998                 nparams = mono_array_length (mb->parameters);
1999         if (!mb && smb && smb->parameters)
2000                 nparams = mono_array_length (smb->parameters) - 1;
2001         sigbuffer_init (&buf, 32);
2002         if (fb->call_conv & 0x20)
2003                 sigbuffer_add_byte (&buf, 0x28);
2004         else
2005                 sigbuffer_add_byte (&buf, 0x08);
2006         sigbuffer_add_value (&buf, nparams);
2007         if (mb) {
2008                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2009                 for (i = 0; i < nparams; ++i) {
2010                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2011                         encode_reflection_type (assembly, pt, &buf);
2012                 }
2013         } else if (smb && smb->parameters) {
2014                 /* the property type is the last param */
2015                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2016                 for (i = 0; i < nparams; ++i) {
2017                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2018                         encode_reflection_type (assembly, pt, &buf);
2019                 }
2020         } else {
2021                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2022         }
2023
2024         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2025         sigbuffer_free (&buf);
2026         return idx;
2027 }
2028
2029 static void
2030 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2031 {
2032         MonoDynamicTable *table;
2033         guint32 *values;
2034         guint num_methods = 0;
2035         guint32 semaidx;
2036
2037         /* 
2038          * we need to set things in the following tables:
2039          * PROPERTYMAP (info already filled in _get_type_info ())
2040          * PROPERTY    (rows already preallocated in _get_type_info ())
2041          * METHOD      (method info already done with the generic method code)
2042          * METHODSEMANTICS
2043          * CONSTANT
2044          */
2045         table = &assembly->tables [MONO_TABLE_PROPERTY];
2046         pb->table_idx = table->next_idx ++;
2047         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2048         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2049         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2050         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2051
2052         /* FIXME: we still don't handle 'other' methods */
2053         if (pb->get_method) num_methods ++;
2054         if (pb->set_method) num_methods ++;
2055
2056         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2057         table->rows += num_methods;
2058         alloc_table (table, table->rows);
2059
2060         if (pb->get_method) {
2061                 semaidx = table->next_idx ++;
2062                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2063                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2064                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2065                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2066         }
2067         if (pb->set_method) {
2068                 semaidx = table->next_idx ++;
2069                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2070                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2071                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2072                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2073         }
2074         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2075                 guint32 field_type = 0;
2076                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2077                 table->rows ++;
2078                 alloc_table (table, table->rows);
2079                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2080                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2081                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2082                 values [MONO_CONSTANT_TYPE] = field_type;
2083                 values [MONO_CONSTANT_PADDING] = 0;
2084         }
2085 }
2086
2087 static void
2088 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2089 {
2090         MonoDynamicTable *table;
2091         guint32 *values;
2092         guint num_methods = 0;
2093         guint32 semaidx;
2094
2095         /* 
2096          * we need to set things in the following tables:
2097          * EVENTMAP (info already filled in _get_type_info ())
2098          * EVENT    (rows already preallocated in _get_type_info ())
2099          * METHOD      (method info already done with the generic method code)
2100          * METHODSEMANTICS
2101          */
2102         table = &assembly->tables [MONO_TABLE_EVENT];
2103         eb->table_idx = table->next_idx ++;
2104         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2105         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2106         values [MONO_EVENT_FLAGS] = eb->attrs;
2107         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2108
2109         /*
2110          * FIXME: we still don't handle 'other' methods 
2111          */
2112         if (eb->add_method) num_methods ++;
2113         if (eb->remove_method) num_methods ++;
2114         if (eb->raise_method) num_methods ++;
2115
2116         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2117         table->rows += num_methods;
2118         alloc_table (table, table->rows);
2119
2120         if (eb->add_method) {
2121                 semaidx = table->next_idx ++;
2122                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2123                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2124                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2125                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2126         }
2127         if (eb->remove_method) {
2128                 semaidx = table->next_idx ++;
2129                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2130                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2131                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2132                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2133         }
2134         if (eb->raise_method) {
2135                 semaidx = table->next_idx ++;
2136                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2137                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2138                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2139                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2140         }
2141 }
2142
2143 static void
2144 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2145 {
2146         MonoDynamicTable *table;
2147         guint32 num_constraints, i;
2148         guint32 *values;
2149         guint32 table_idx;
2150
2151         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2152         num_constraints = gparam->iface_constraints ?
2153                 mono_array_length (gparam->iface_constraints) : 0;
2154         table->rows += num_constraints;
2155         if (gparam->base_type)
2156                 table->rows++;
2157         alloc_table (table, table->rows);
2158
2159         if (gparam->base_type) {
2160                 table_idx = table->next_idx ++;
2161                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2162
2163                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2164                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2165                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2166         }
2167
2168         for (i = 0; i < num_constraints; i++) {
2169                 MonoReflectionType *constraint = mono_array_get (
2170                         gparam->iface_constraints, gpointer, i);
2171
2172                 table_idx = table->next_idx ++;
2173                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2174
2175                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2176                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2177                         assembly, mono_reflection_type_get_handle (constraint));
2178         }
2179 }
2180
2181 static void
2182 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2183 {
2184         GenericParamTableEntry *entry;
2185
2186         /*
2187          * The GenericParam table must be sorted according to the `owner' field.
2188          * We need to do this sorting prior to writing the GenericParamConstraint
2189          * table, since we have to use the final GenericParam table indices there
2190          * and they must also be sorted.
2191          */
2192
2193         entry = g_new0 (GenericParamTableEntry, 1);
2194         entry->owner = owner;
2195         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2196         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2197         entry->gparam = gparam;
2198         
2199         g_ptr_array_add (assembly->gen_params, entry);
2200 }
2201
2202 static void
2203 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2204 {
2205         MonoDynamicTable *table;
2206         MonoGenericParam *param;
2207         guint32 *values;
2208         guint32 table_idx;
2209
2210         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2211         table_idx = table->next_idx ++;
2212         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2213
2214         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2215
2216         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2217         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2218         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2219         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2220
2221         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2222
2223         encode_constraints (entry->gparam, table_idx, assembly);
2224 }
2225
2226 static guint32
2227 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2228 {
2229         MonoDynamicTable *table;
2230         guint32 token;
2231         guint32 *values;
2232         guint32 cols [MONO_ASSEMBLY_SIZE];
2233         const char *pubkey;
2234         guint32 publen;
2235
2236         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2237                 return token;
2238
2239         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2240                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2241                 token = table->next_idx ++;
2242                 table->rows ++;
2243                 alloc_table (table, table->rows);
2244                 values = table->values + token * MONO_MODULEREF_SIZE;
2245                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2246
2247                 token <<= MONO_RESOLTION_SCOPE_BITS;
2248                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2249                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2250
2251                 return token;
2252         }
2253         
2254         if (image->assembly->dynamic)
2255                 /* FIXME: */
2256                 memset (cols, 0, sizeof (cols));
2257         else {
2258                 /* image->assembly->image is the manifest module */
2259                 image = image->assembly->image;
2260                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2261         }
2262
2263         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2264         token = table->next_idx ++;
2265         table->rows ++;
2266         alloc_table (table, table->rows);
2267         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2268         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2269         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2270         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2271         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2272         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2273         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2274         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2275         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2276
2277         if (strcmp ("", image->assembly->aname.culture)) {
2278                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2279                                 image->assembly->aname.culture);
2280         }
2281
2282         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2283                 guchar pubtoken [9];
2284                 pubtoken [0] = 8;
2285                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2286                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2287         } else {
2288                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2289         }
2290         token <<= MONO_RESOLTION_SCOPE_BITS;
2291         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2292         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2293         return token;
2294 }
2295
2296 static guint32
2297 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2298 {
2299         MonoDynamicTable *table;
2300         guint32 *values;
2301         guint32 token;
2302         SigBuffer buf;
2303
2304         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2305                 return token;
2306
2307         sigbuffer_init (&buf, 32);
2308         switch (type->type) {
2309         case MONO_TYPE_FNPTR:
2310         case MONO_TYPE_PTR:
2311         case MONO_TYPE_SZARRAY:
2312         case MONO_TYPE_ARRAY:
2313         case MONO_TYPE_VAR:
2314         case MONO_TYPE_MVAR:
2315         case MONO_TYPE_GENERICINST:
2316                 encode_type (assembly, type, &buf);
2317                 break;
2318         case MONO_TYPE_CLASS:
2319         case MONO_TYPE_VALUETYPE: {
2320                 MonoClass *k = mono_class_from_mono_type (type);
2321                 if (!k || !k->generic_container) {
2322                         sigbuffer_free (&buf);
2323                         return 0;
2324                 }
2325                 encode_type (assembly, type, &buf);
2326                 break;
2327         }
2328         default:
2329                 sigbuffer_free (&buf);
2330                 return 0;
2331         }
2332
2333         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2334         if (assembly->save) {
2335                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2336                 alloc_table (table, table->rows + 1);
2337                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2338                 values [MONO_TYPESPEC_SIGNATURE] = token;
2339         }
2340         sigbuffer_free (&buf);
2341
2342         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2343         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2344         table->next_idx ++;
2345         return token;
2346 }
2347
2348 static guint32
2349 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2350 {
2351         MonoDynamicTable *table;
2352         guint32 *values;
2353         guint32 token, scope, enclosing;
2354         MonoClass *klass;
2355
2356         /* if the type requires a typespec, we must try that first*/
2357         if (try_typespec && (token = create_typespec (assembly, type)))
2358                 return token;
2359         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2360         if (token)
2361                 return token;
2362         klass = mono_class_from_mono_type (type);
2363         if (!klass)
2364                 klass = mono_class_from_mono_type (type);
2365
2366         /*
2367          * If it's in the same module and not a generic type parameter:
2368          */
2369         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2370                         (type->type != MONO_TYPE_MVAR)) {
2371                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2372                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2373                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2374                 return token;
2375         }
2376
2377         if (klass->nested_in) {
2378                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2379                 /* get the typeref idx of the enclosing type */
2380                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2381                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2382         } else {
2383                 scope = resolution_scope_from_image (assembly, klass->image);
2384         }
2385         table = &assembly->tables [MONO_TABLE_TYPEREF];
2386         if (assembly->save) {
2387                 alloc_table (table, table->rows + 1);
2388                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2389                 values [MONO_TYPEREF_SCOPE] = scope;
2390                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2391                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2392         }
2393         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2394         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2395         table->next_idx ++;
2396         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2397         return token;
2398 }
2399
2400 /*
2401  * Despite the name, we handle also TypeSpec (with the above helper).
2402  */
2403 static guint32
2404 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2405 {
2406         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2407 }
2408
2409 #ifndef DISABLE_REFLECTION_EMIT
2410 static guint32
2411 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2412 {
2413         MonoDynamicTable *table;
2414         guint32 *values;
2415         guint32 token, pclass;
2416
2417         switch (parent & MONO_TYPEDEFORREF_MASK) {
2418         case MONO_TYPEDEFORREF_TYPEREF:
2419                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2420                 break;
2421         case MONO_TYPEDEFORREF_TYPESPEC:
2422                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2423                 break;
2424         case MONO_TYPEDEFORREF_TYPEDEF:
2425                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2426                 break;
2427         default:
2428                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2429                 return 0;
2430         }
2431         /* extract the index */
2432         parent >>= MONO_TYPEDEFORREF_BITS;
2433
2434         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2435
2436         if (assembly->save) {
2437                 alloc_table (table, table->rows + 1);
2438                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2439                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2440                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2441                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2442         }
2443
2444         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2445         table->next_idx ++;
2446
2447         return token;
2448 }
2449
2450 /*
2451  * Insert a memberef row into the metadata: the token that point to the memberref
2452  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2453  * mono_image_get_fieldref_token()).
2454  * The sig param is an index to an already built signature.
2455  */
2456 static guint32
2457 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2458 {
2459         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2460         return mono_image_add_memberef_row (assembly, parent, name, sig);
2461 }
2462
2463
2464 static guint32
2465 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2466 {
2467         guint32 token;
2468         MonoMethodSignature *sig;
2469         
2470         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2471
2472         if (create_typespec) {
2473                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2474                 if (token)
2475                         return token;
2476         } 
2477
2478         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2479         if (token && !create_typespec)
2480                 return token;
2481
2482         g_assert (!method->is_inflated);
2483         if (!token) {
2484                 /*
2485                  * A methodref signature can't contain an unmanaged calling convention.
2486                  */
2487                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2488                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2489                         sig->call_convention = MONO_CALL_DEFAULT;
2490                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2491                         method->name,  method_encode_signature (assembly, sig));
2492                 g_free (sig);
2493                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2494         }
2495
2496         if (create_typespec) {
2497                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2498                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2499                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2500
2501                 if (assembly->save) {
2502                         guint32 *values;
2503
2504                         alloc_table (table, table->rows + 1);
2505                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2506                         values [MONO_METHODSPEC_METHOD] = token;
2507                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2508                 }
2509
2510                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2511                 table->next_idx ++;
2512                 /*methodspec and memberef tokens are diferent, */
2513                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2514                 return token;
2515         }
2516         return token;
2517 }
2518
2519 static guint32
2520 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2521 {
2522         guint32 token, parent, sig;
2523         ReflectionMethodBuilder rmb;
2524         char *name;
2525         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2526         
2527         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2528         if (token)
2529                 return token;
2530
2531         name = mono_string_to_utf8 (method->name);
2532         reflection_methodbuilder_from_method_builder (&rmb, method);
2533
2534         /*
2535          * A methodref signature can't contain an unmanaged calling convention.
2536          * Since some flags are encoded as part of call_conv, we need to check against it.
2537         */
2538         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2539                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2540
2541         sig = method_builder_encode_signature (assembly, &rmb);
2542
2543         if (tb->generic_params)
2544                 parent = create_generic_typespec (assembly, tb);
2545         else
2546                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2547
2548         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2549
2550         g_free (name);
2551         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2552         return token;
2553 }
2554
2555 static guint32
2556 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2557                                      const gchar *name, guint32 sig)
2558 {
2559         MonoDynamicTable *table;
2560         guint32 token;
2561         guint32 *values;
2562         
2563         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2564
2565         if (assembly->save) {
2566                 alloc_table (table, table->rows + 1);
2567                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2568                 values [MONO_MEMBERREF_CLASS] = original;
2569                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2570                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2571         }
2572
2573         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2574         table->next_idx ++;
2575
2576         return token;
2577 }
2578
2579 static guint32
2580 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2581 {
2582         SigBuffer buf;
2583         int i;
2584         guint32 nparams = mono_array_length (mb->generic_params);
2585         guint32 idx;
2586
2587         if (!assembly->save)
2588                 return 0;
2589
2590         sigbuffer_init (&buf, 32);
2591
2592         sigbuffer_add_value (&buf, 0xa);
2593         sigbuffer_add_value (&buf, nparams);
2594
2595         for (i = 0; i < nparams; i++) {
2596                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2597                 sigbuffer_add_value (&buf, i);
2598         }
2599
2600         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2601         sigbuffer_free (&buf);
2602         return idx;
2603 }
2604
2605 static guint32
2606 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2607 {
2608         MonoDynamicTable *table;
2609         guint32 *values;
2610         guint32 token, mtoken = 0;
2611
2612         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2613         if (token)
2614                 return token;
2615
2616         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2617
2618         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2619         switch (mono_metadata_token_table (mtoken)) {
2620         case MONO_TABLE_MEMBERREF:
2621                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2622                 break;
2623         case MONO_TABLE_METHOD:
2624                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2625                 break;
2626         default:
2627                 g_assert_not_reached ();
2628         }
2629
2630         if (assembly->save) {
2631                 alloc_table (table, table->rows + 1);
2632                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2633                 values [MONO_METHODSPEC_METHOD] = mtoken;
2634                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2635         }
2636
2637         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2638         table->next_idx ++;
2639
2640         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2641         return token;
2642 }
2643
2644 static guint32
2645 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2646 {
2647         guint32 token;
2648
2649         if (mb->generic_params && create_methodspec) 
2650                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2651
2652         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2653         if (token)
2654                 return token;
2655
2656         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2657         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2658         return token;
2659 }
2660
2661 static guint32
2662 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2663 {
2664         guint32 token, parent, sig;
2665         ReflectionMethodBuilder rmb;
2666         char *name;
2667         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2668         
2669         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2670         if (token)
2671                 return token;
2672
2673         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2674
2675         if (tb->generic_params)
2676                 parent = create_generic_typespec (assembly, tb);
2677         else
2678                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2679         
2680         name = mono_string_to_utf8 (rmb.name);
2681         sig = method_builder_encode_signature (assembly, &rmb);
2682
2683         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2684
2685         g_free (name);
2686         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2687         return token;
2688 }
2689 #endif
2690
2691 static gboolean
2692 is_field_on_inst (MonoClassField *field)
2693 {
2694         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2695 }
2696
2697 /*
2698  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2699  */
2700 static MonoType*
2701 get_field_on_inst_generic_type (MonoClassField *field)
2702 {
2703         MonoClass *class, *gtd;
2704         MonoDynamicGenericClass *dgclass;
2705         int field_index;
2706
2707         g_assert (is_field_on_inst (field));
2708
2709         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2710
2711         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2712                 field_index = field - dgclass->fields;
2713                 return dgclass->field_generic_types [field_index];              
2714         }
2715
2716         class = field->parent;
2717         gtd = class->generic_class->container_class;
2718
2719         if (field >= class->fields && field - class->fields < class->field.count) {
2720                 field_index = field - class->fields;
2721                 return gtd->fields [field_index].type;
2722         }
2723
2724         g_assert_not_reached ();
2725         return 0;
2726 }
2727
2728 #ifndef DISABLE_REFLECTION_EMIT
2729 static guint32
2730 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2731 {
2732         MonoType *type;
2733         guint32 token;
2734
2735         g_assert (field);
2736         g_assert (field->parent);
2737
2738         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2739         if (token)
2740                 return token;
2741
2742         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2743                 int index = field - field->parent->fields;
2744                 type = field->parent->generic_class->container_class->fields [index].type;
2745         } else {
2746                 if (is_field_on_inst (field))
2747                         type = get_field_on_inst_generic_type (field);
2748                 else
2749                         type = mono_field_get_type (field);
2750         }
2751         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2752                                                                                         mono_field_get_name (field),
2753                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2754         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2755         return token;
2756 }
2757
2758 static guint32
2759 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2760 {
2761         guint32 token;
2762         MonoClass *klass;
2763         MonoGenericClass *gclass;
2764         MonoDynamicGenericClass *dgclass;
2765         MonoType *type;
2766         char *name;
2767
2768         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2769         if (token)
2770                 return token;
2771         if (is_sre_field_builder (mono_object_class (f->fb))) {
2772                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2773                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2774                 klass = mono_class_from_mono_type (type);
2775                 gclass = type->data.generic_class;
2776                 g_assert (gclass->is_dynamic);
2777                 dgclass = (MonoDynamicGenericClass *) gclass;
2778
2779                 name = mono_string_to_utf8 (fb->name);
2780                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2781                                                                                                 field_encode_signature (assembly, fb));
2782                 g_free (name);          
2783         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2784                 guint32 sig;
2785                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2786
2787                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2788                 klass = mono_class_from_mono_type (type);
2789
2790                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2791                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2792         } else {
2793                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2794                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2795         }
2796
2797         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2798         return token;
2799 }
2800
2801 static guint32
2802 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2803 {
2804         guint32 sig, token;
2805         MonoClass *klass;
2806         MonoGenericClass *gclass;
2807         MonoType *type;
2808
2809         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2810
2811         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2812         if (token)
2813                 return token;
2814
2815         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2816                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2817                 MonoDynamicGenericClass *dgclass;
2818                 ReflectionMethodBuilder rmb;
2819                 char *name;
2820
2821                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2822                 klass = mono_class_from_mono_type (type);
2823
2824                 gclass = type->data.generic_class;
2825                 g_assert (gclass->is_dynamic);
2826                 dgclass = (MonoDynamicGenericClass *) gclass;
2827
2828                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2829
2830                 name = mono_string_to_utf8 (rmb.name);
2831
2832                 sig = method_builder_encode_signature (assembly, &rmb);
2833
2834                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2835                 g_free (name);
2836         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2837                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2838
2839                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2840                 klass = mono_class_from_mono_type (type);
2841
2842                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2843                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2844         } else {
2845                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2846                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2847         }
2848
2849
2850         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2851         return token;
2852 }
2853
2854 static MonoMethod*
2855 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2856 {
2857         MonoClass *klass;
2858         MonoGenericContext tmp_context;
2859         MonoType **type_argv;
2860         MonoGenericInst *ginst;
2861         MonoMethod *method, *inflated;
2862         int count, i;
2863
2864         init_type_builder_generics ((MonoObject*)m->inst);
2865
2866         method = inflate_method (m->inst, (MonoObject*)m->mb);
2867
2868         klass = method->klass;
2869
2870         if (m->method_args == NULL)
2871                 return method;
2872
2873         if (method->is_inflated)
2874                 method = ((MonoMethodInflated *) method)->declaring;
2875
2876         count = mono_array_length (m->method_args);
2877
2878         type_argv = g_new0 (MonoType *, count);
2879         for (i = 0; i < count; i++) {
2880                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2881                 type_argv [i] = mono_reflection_type_get_handle (garg);
2882         }
2883         ginst = mono_metadata_get_generic_inst (count, type_argv);
2884         g_free (type_argv);
2885
2886         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2887         tmp_context.method_inst = ginst;
2888
2889         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2890         return inflated;
2891 }
2892
2893 static guint32
2894 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2895 {
2896         guint32 sig, token = 0;
2897         MonoType *type;
2898         MonoClass *klass;
2899
2900         if (m->method_args) {
2901                 MonoMethod *inflated;
2902
2903                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2904                 if (create_methodspec)
2905                         token = mono_image_get_methodspec_token (assembly, inflated);
2906                 else
2907                         token = mono_image_get_inflated_method_token (assembly, inflated);
2908                 return token;
2909         }
2910
2911         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2912         if (token)
2913                 return token;
2914
2915         if (is_sre_method_builder (mono_object_class (m->mb))) {
2916                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2917                 MonoGenericClass *gclass;
2918                 ReflectionMethodBuilder rmb;
2919                 char *name;
2920
2921                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2922                 klass = mono_class_from_mono_type (type);
2923                 gclass = type->data.generic_class;
2924                 g_assert (gclass->is_dynamic);
2925
2926                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2927
2928                 name = mono_string_to_utf8 (rmb.name);
2929
2930                 sig = method_builder_encode_signature (assembly, &rmb);
2931
2932                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2933                 g_free (name);          
2934         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2935                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2936
2937                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2938                 klass = mono_class_from_mono_type (type);
2939
2940                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2941                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2942         } else {
2943                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2944                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2945         }
2946
2947         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2948         return token;
2949 }
2950
2951 static guint32
2952 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2953 {
2954         SigBuffer buf;
2955         int i;
2956         guint32 nparams = context->method_inst->type_argc;
2957         guint32 idx;
2958
2959         if (!assembly->save)
2960                 return 0;
2961
2962         sigbuffer_init (&buf, 32);
2963         /*
2964          * FIXME: vararg, explicit_this, differenc call_conv values...
2965          */
2966         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2967         sigbuffer_add_value (&buf, nparams);
2968
2969         for (i = 0; i < nparams; i++)
2970                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2971
2972         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2973         sigbuffer_free (&buf);
2974         return idx;
2975 }
2976
2977 static guint32
2978 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2979 {
2980         MonoDynamicTable *table;
2981         guint32 *values;
2982         guint32 token, mtoken = 0, sig;
2983         MonoMethodInflated *imethod;
2984         MonoMethod *declaring;
2985
2986         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2987
2988         g_assert (method->is_inflated);
2989         imethod = (MonoMethodInflated *) method;
2990         declaring = imethod->declaring;
2991
2992         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2993         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2994
2995         if (!mono_method_signature (declaring)->generic_param_count)
2996                 return mtoken;
2997
2998         switch (mono_metadata_token_table (mtoken)) {
2999         case MONO_TABLE_MEMBERREF:
3000                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3001                 break;
3002         case MONO_TABLE_METHOD:
3003                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3004                 break;
3005         default:
3006                 g_assert_not_reached ();
3007         }
3008
3009         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3010
3011         if (assembly->save) {
3012                 alloc_table (table, table->rows + 1);
3013                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3014                 values [MONO_METHODSPEC_METHOD] = mtoken;
3015                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3016         }
3017
3018         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3019         table->next_idx ++;
3020
3021         return token;
3022 }
3023
3024 static guint32
3025 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3026 {
3027         MonoMethodInflated *imethod;
3028         guint32 token;
3029         
3030         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3031         if (token)
3032                 return token;
3033
3034         g_assert (method->is_inflated);
3035         imethod = (MonoMethodInflated *) method;
3036
3037         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3038                 token = method_encode_methodspec (assembly, method);
3039         } else {
3040                 guint32 sig = method_encode_signature (
3041                         assembly, mono_method_signature (imethod->declaring));
3042                 token = mono_image_get_memberref_token (
3043                         assembly, &method->klass->byval_arg, method->name, sig);
3044         }
3045
3046         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3047         return token;
3048 }
3049
3050 static guint32
3051 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3052 {
3053         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3054         guint32 sig, token;
3055
3056         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3057         token = mono_image_get_memberref_token (
3058                 assembly, &m->klass->byval_arg, m->name, sig);
3059
3060         return token;
3061 }
3062
3063 static guint32
3064 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3065 {
3066         MonoDynamicTable *table;
3067         MonoClass *klass;
3068         MonoType *type;
3069         guint32 *values;
3070         guint32 token;
3071         SigBuffer buf;
3072         int count, i;
3073
3074         /*
3075          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3076          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3077          * Because of this, we must not insert it into the `typeref' hash table.
3078          */
3079         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3080         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3081         if (token)
3082                 return token;
3083
3084         sigbuffer_init (&buf, 32);
3085
3086         g_assert (tb->generic_params);
3087         klass = mono_class_from_mono_type (type);
3088
3089         if (tb->generic_container)
3090                 mono_reflection_create_generic_class (tb);
3091
3092         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3093         g_assert (klass->generic_container);
3094         sigbuffer_add_value (&buf, klass->byval_arg.type);
3095         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3096
3097         count = mono_array_length (tb->generic_params);
3098         sigbuffer_add_value (&buf, count);
3099         for (i = 0; i < count; i++) {
3100                 MonoReflectionGenericParam *gparam;
3101
3102                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3103
3104                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3105         }
3106
3107         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3108
3109         if (assembly->save) {
3110                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3111                 alloc_table (table, table->rows + 1);
3112                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3113                 values [MONO_TYPESPEC_SIGNATURE] = token;
3114         }
3115         sigbuffer_free (&buf);
3116
3117         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3118         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3119         table->next_idx ++;
3120         return token;
3121 }
3122
3123 /*
3124  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3125  */
3126 static MonoType*
3127 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3128 {
3129         int i, count, len, pos;
3130         MonoType *t;
3131
3132         count = 0;
3133         if (modreq)
3134                 count += mono_array_length (modreq);
3135         if (modopt)
3136                 count += mono_array_length (modopt);
3137
3138         if (count == 0)
3139                 return mono_metadata_type_dup (NULL, type);
3140
3141         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3142         t = g_malloc (len);
3143         memcpy (t, type, MONO_SIZEOF_TYPE);
3144
3145         t->num_mods = count;
3146         pos = 0;
3147         if (modreq) {
3148                 for (i = 0; i < mono_array_length (modreq); ++i) {
3149                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3150                         t->modifiers [pos].required = 1;
3151                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3152                         pos ++;
3153                 }
3154         }
3155         if (modopt) {
3156                 for (i = 0; i < mono_array_length (modopt); ++i) {
3157                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3158                         t->modifiers [pos].required = 0;
3159                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3160                         pos ++;
3161                 }
3162         }
3163
3164         return t;
3165 }
3166
3167 static void
3168 init_type_builder_generics (MonoObject *type)
3169 {
3170         MonoReflectionTypeBuilder *tb;
3171
3172         if (!is_sre_type_builder(mono_object_class (type)))
3173                 return;
3174         tb = (MonoReflectionTypeBuilder *)type;
3175
3176         if (tb && tb->generic_container)
3177                 mono_reflection_create_generic_class (tb);
3178 }
3179
3180 static guint32
3181 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3182 {
3183         MonoDynamicTable *table;
3184         MonoClass *klass;
3185         MonoType *custom = NULL, *type;
3186         guint32 *values;
3187         guint32 token, pclass, parent, sig;
3188         gchar *name;
3189
3190         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3191         if (token)
3192                 return token;
3193
3194         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3195         name = mono_string_to_utf8 (fb->name);
3196
3197         /*FIXME this is one more layer of ugliness due how types are created.*/
3198         init_type_builder_generics (fb->type);
3199
3200         /* fb->type does not include the custom modifiers */
3201         /* FIXME: We should do this in one place when a fieldbuilder is created */
3202         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3203         if (fb->modreq || fb->modopt)
3204                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3205
3206         sig = fieldref_encode_signature (assembly, NULL, type);
3207         g_free (custom);
3208
3209         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3210         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3211         
3212         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3213         parent >>= MONO_TYPEDEFORREF_BITS;
3214
3215         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3216
3217         if (assembly->save) {
3218                 alloc_table (table, table->rows + 1);
3219                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3220                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3221                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3222                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3223         }
3224
3225         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3226         table->next_idx ++;
3227         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3228         g_free (name);
3229         return token;
3230 }
3231
3232 static guint32
3233 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3234 {
3235         SigBuffer buf;
3236         guint32 nargs;
3237         guint32 size;
3238         guint32 i, idx;
3239
3240         if (!assembly->save)
3241                 return 0;
3242
3243         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3244         g_assert (helper->type == 2);
3245
3246         if (helper->arguments)
3247                 nargs = mono_array_length (helper->arguments);
3248         else
3249                 nargs = 0;
3250
3251         size = 10 + (nargs * 10);
3252         
3253         sigbuffer_init (&buf, 32);
3254
3255         /* Encode calling convention */
3256         /* Change Any to Standard */
3257         if ((helper->call_conv & 0x03) == 0x03)
3258                 helper->call_conv = 0x01;
3259         /* explicit_this implies has_this */
3260         if (helper->call_conv & 0x40)
3261                 helper->call_conv &= 0x20;
3262
3263         if (helper->call_conv == 0) { /* Unmanaged */
3264                 idx = helper->unmanaged_call_conv - 1;
3265         } else {
3266                 /* Managed */
3267                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3268                 if (helper->call_conv & 0x02) /* varargs */
3269                         idx += 0x05;
3270         }
3271
3272         sigbuffer_add_byte (&buf, idx);
3273         sigbuffer_add_value (&buf, nargs);
3274         encode_reflection_type (assembly, helper->return_type, &buf);
3275         for (i = 0; i < nargs; ++i) {
3276                 MonoArray *modreqs = NULL;
3277                 MonoArray *modopts = NULL;
3278                 MonoReflectionType *pt;
3279
3280                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3281                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3282                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3283                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3284
3285                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3286                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3287                 encode_reflection_type (assembly, pt, &buf);
3288         }
3289         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3290         sigbuffer_free (&buf);
3291
3292         return idx;
3293 }
3294
3295 static guint32 
3296 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3297 {
3298         guint32 idx;
3299         MonoDynamicTable *table;
3300         guint32 *values;
3301
3302         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3303         idx = table->next_idx ++;
3304         table->rows ++;
3305         alloc_table (table, table->rows);
3306         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3307
3308         values [MONO_STAND_ALONE_SIGNATURE] =
3309                 mono_reflection_encode_sighelper (assembly, helper);
3310
3311         return idx;
3312 }
3313
3314 static int
3315 reflection_cc_to_file (int call_conv) {
3316         switch (call_conv & 0x3) {
3317         case 0:
3318         case 1: return MONO_CALL_DEFAULT;
3319         case 2: return MONO_CALL_VARARG;
3320         default:
3321                 g_assert_not_reached ();
3322         }
3323         return 0;
3324 }
3325 #endif /* !DISABLE_REFLECTION_EMIT */
3326
3327 typedef struct {
3328         MonoType *parent;
3329         MonoMethodSignature *sig;
3330         char *name;
3331         guint32 token;
3332 } ArrayMethod;
3333
3334 #ifndef DISABLE_REFLECTION_EMIT
3335 static guint32
3336 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3337 {
3338         guint32 nparams, i;
3339         GList *tmp;
3340         char *name;
3341         MonoMethodSignature *sig;
3342         ArrayMethod *am;
3343         MonoType *mtype;
3344
3345         name = mono_string_to_utf8 (m->name);
3346         nparams = mono_array_length (m->parameters);
3347         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3348         sig->hasthis = 1;
3349         sig->sentinelpos = -1;
3350         sig->call_convention = reflection_cc_to_file (m->call_conv);
3351         sig->param_count = nparams;
3352         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3353         mtype = mono_reflection_type_get_handle (m->parent);
3354         for (i = 0; i < nparams; ++i)
3355                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3356
3357         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3358                 am = tmp->data;
3359                 if (strcmp (name, am->name) == 0 && 
3360                                 mono_metadata_type_equal (am->parent, mtype) &&
3361                                 mono_metadata_signature_equal (am->sig, sig)) {
3362                         g_free (name);
3363                         g_free (sig);
3364                         m->table_idx = am->token & 0xffffff;
3365                         return am->token;
3366                 }
3367         }
3368         am = g_new0 (ArrayMethod, 1);
3369         am->name = name;
3370         am->sig = sig;
3371         am->parent = mtype;
3372         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3373                 method_encode_signature (assembly, sig));
3374         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3375         m->table_idx = am->token & 0xffffff;
3376         return am->token;
3377 }
3378
3379 /*
3380  * Insert into the metadata tables all the info about the TypeBuilder tb.
3381  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3382  */
3383 static void
3384 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3385 {
3386         MonoDynamicTable *table;
3387         guint *values;
3388         int i, is_object = 0, is_system = 0;
3389         char *n;
3390
3391         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3392         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3393         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3394         n = mono_string_to_utf8 (tb->name);
3395         if (strcmp (n, "Object") == 0)
3396                 is_object++;
3397         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3398         g_free (n);
3399         n = mono_string_to_utf8 (tb->nspace);
3400         if (strcmp (n, "System") == 0)
3401                 is_system++;
3402         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3403         g_free (n);
3404         if (tb->parent && !(is_system && is_object) && 
3405                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3406                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3407         } else {
3408                 values [MONO_TYPEDEF_EXTENDS] = 0;
3409         }
3410         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3411         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3412
3413         /*
3414          * if we have explicitlayout or sequentiallayouts, output data in the
3415          * ClassLayout table.
3416          */
3417         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3418                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3419                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3420                 table->rows++;
3421                 alloc_table (table, table->rows);
3422                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3423                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3424                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3425                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3426         }
3427
3428         /* handle interfaces */
3429         if (tb->interfaces) {
3430                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3431                 i = table->rows;
3432                 table->rows += mono_array_length (tb->interfaces);
3433                 alloc_table (table, table->rows);
3434                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3435                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3436                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3437                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3438                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3439                         values += MONO_INTERFACEIMPL_SIZE;
3440                 }
3441         }
3442
3443         /* handle fields */
3444         if (tb->fields) {
3445                 table = &assembly->tables [MONO_TABLE_FIELD];
3446                 table->rows += tb->num_fields;
3447                 alloc_table (table, table->rows);
3448                 for (i = 0; i < tb->num_fields; ++i)
3449                         mono_image_get_field_info (
3450                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3451         }
3452
3453         /* handle constructors */
3454         if (tb->ctors) {
3455                 table = &assembly->tables [MONO_TABLE_METHOD];
3456                 table->rows += mono_array_length (tb->ctors);
3457                 alloc_table (table, table->rows);
3458                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3459                         mono_image_get_ctor_info (domain,
3460                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3461         }
3462
3463         /* handle methods */
3464         if (tb->methods) {
3465                 table = &assembly->tables [MONO_TABLE_METHOD];
3466                 table->rows += tb->num_methods;
3467                 alloc_table (table, table->rows);
3468                 for (i = 0; i < tb->num_methods; ++i)
3469                         mono_image_get_method_info (
3470                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3471         }
3472
3473         /* Do the same with properties etc.. */
3474         if (tb->events && mono_array_length (tb->events)) {
3475                 table = &assembly->tables [MONO_TABLE_EVENT];
3476                 table->rows += mono_array_length (tb->events);
3477                 alloc_table (table, table->rows);
3478                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3479                 table->rows ++;
3480                 alloc_table (table, table->rows);
3481                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3482                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3483                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3484                 for (i = 0; i < mono_array_length (tb->events); ++i)
3485                         mono_image_get_event_info (
3486                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3487         }
3488         if (tb->properties && mono_array_length (tb->properties)) {
3489                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3490                 table->rows += mono_array_length (tb->properties);
3491                 alloc_table (table, table->rows);
3492                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3493                 table->rows ++;
3494                 alloc_table (table, table->rows);
3495                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3496                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3497                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3498                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3499                         mono_image_get_property_info (
3500                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3501         }
3502
3503         /* handle generic parameters */
3504         if (tb->generic_params) {
3505                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3506                 table->rows += mono_array_length (tb->generic_params);
3507                 alloc_table (table, table->rows);
3508                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3509                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3510
3511                         mono_image_get_generic_param_info (
3512                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3513                 }
3514         }
3515
3516         mono_image_add_decl_security (assembly, 
3517                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3518
3519         if (tb->subtypes) {
3520                 MonoDynamicTable *ntable;
3521                 
3522                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3523                 ntable->rows += mono_array_length (tb->subtypes);
3524                 alloc_table (ntable, ntable->rows);
3525                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3526
3527                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3528                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3529
3530                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3531                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3532                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3533                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3534                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3535                                 ntable->next_idx, ntable->rows);*/
3536                         values += MONO_NESTED_CLASS_SIZE;
3537                         ntable->next_idx++;
3538                 }
3539         }
3540 }
3541 #endif
3542
3543 static void
3544 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3545 {
3546         int i;
3547
3548         mono_ptr_array_append (*types, type);
3549
3550         if (!type->subtypes)
3551                 return;
3552
3553         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3554                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3555                 collect_types (types, subtype);
3556         }
3557 }
3558
3559 static gint
3560 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3561 {
3562         if ((*type1)->table_idx < (*type2)->table_idx)
3563                 return -1;
3564         else
3565                 if ((*type1)->table_idx > (*type2)->table_idx)
3566                         return 1;
3567         else
3568                 return 0;
3569 }
3570
3571 static void
3572 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3573         int i;
3574
3575         if (!pinfo)
3576                 return;
3577         for (i = 0; i < mono_array_length (pinfo); ++i) {
3578                 MonoReflectionParamBuilder *pb;
3579                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3580                 if (!pb)
3581                         continue;
3582                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3583         }
3584 }
3585
3586 static void
3587 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3588         int i;
3589         
3590         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3591         if (tb->fields) {
3592                 for (i = 0; i < tb->num_fields; ++i) {
3593                         MonoReflectionFieldBuilder* fb;
3594                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3595                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3596                 }
3597         }
3598         if (tb->events) {
3599                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3600                         MonoReflectionEventBuilder* eb;
3601                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3602                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3603                 }
3604         }
3605         if (tb->properties) {
3606                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3607                         MonoReflectionPropertyBuilder* pb;
3608                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3609                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3610                 }
3611         }
3612         if (tb->ctors) {
3613                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3614                         MonoReflectionCtorBuilder* cb;
3615                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3616                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3617                         params_add_cattrs (assembly, cb->pinfo);
3618                 }
3619         }
3620
3621         if (tb->methods) {
3622                 for (i = 0; i < tb->num_methods; ++i) {
3623                         MonoReflectionMethodBuilder* mb;
3624                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3625                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3626                         params_add_cattrs (assembly, mb->pinfo);
3627                 }
3628         }
3629
3630         if (tb->subtypes) {
3631                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3632                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3633         }
3634 }
3635
3636 static void
3637 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3638 {
3639         int i;
3640         
3641         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3642
3643         if (moduleb->global_methods) {
3644                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3645                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3646                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3647                         params_add_cattrs (assembly, mb->pinfo);
3648                 }
3649         }
3650
3651         if (moduleb->global_fields) {
3652                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3653                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3654                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3655                 }
3656         }
3657         
3658         if (moduleb->types) {
3659                 for (i = 0; i < moduleb->num_types; ++i)
3660                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3661         }
3662 }
3663
3664 static void
3665 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3666 {
3667         MonoDynamicTable *table;
3668         guint32 *values;
3669         char blob_size [6];
3670         guchar hash [20];
3671         char *b = blob_size;
3672         char *dir, *path;
3673
3674         table = &assembly->tables [MONO_TABLE_FILE];
3675         table->rows++;
3676         alloc_table (table, table->rows);
3677         values = table->values + table->next_idx * MONO_FILE_SIZE;
3678         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3679         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3680         if (module->image->dynamic) {
3681                 /* This depends on the fact that the main module is emitted last */
3682                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3683                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3684         } else {
3685                 dir = NULL;
3686                 path = g_strdup (module->image->name);
3687         }
3688         mono_sha1_get_digest_from_file (path, hash);
3689         g_free (dir);
3690         g_free (path);
3691         mono_metadata_encode_value (20, b, &b);
3692         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3693         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3694         table->next_idx ++;
3695 }
3696
3697 static void
3698 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3699 {
3700         MonoDynamicTable *table;
3701         int i;
3702
3703         table = &assembly->tables [MONO_TABLE_MODULE];
3704         mb->table_idx = table->next_idx ++;
3705         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3706         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3707         i /= 16;
3708         ++i;
3709         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3710         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3711         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3712         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3713 }
3714
3715 static guint32
3716 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3717         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3718 {
3719         MonoDynamicTable *table;
3720         guint32 *values;
3721         guint32 visib, res;
3722
3723         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3724         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3725                 return 0;
3726
3727         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3728         table->rows++;
3729         alloc_table (table, table->rows);
3730         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3731
3732         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3733         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3734         if (klass->nested_in)
3735                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3736         else
3737                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3738         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3739         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3740
3741         res = table->next_idx;
3742
3743         table->next_idx ++;
3744
3745         /* Emit nested types */
3746         if (klass->ext && klass->ext->nested_classes) {
3747                 GList *tmp;
3748
3749                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3750                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3751         }
3752
3753         return res;
3754 }
3755
3756 static void
3757 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3758         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3759 {
3760         MonoClass *klass;
3761         guint32 idx, i;
3762
3763         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3764
3765         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3766
3767         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3768                                                                                                    parent_index, assembly);
3769
3770         /* 
3771          * Emit nested types
3772          * We need to do this ourselves since klass->nested_classes is not set up.
3773          */
3774         if (tb->subtypes) {
3775                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3776                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3777         }
3778 }
3779
3780 static void
3781 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3782         guint32 module_index, MonoDynamicImage *assembly)
3783 {
3784         MonoImage *image = module->image;
3785         MonoTableInfo  *t;
3786         guint32 i;
3787
3788         t = &image->tables [MONO_TABLE_TYPEDEF];
3789
3790         for (i = 0; i < t->rows; ++i) {
3791                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3792
3793                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3794                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3795         }
3796 }
3797
3798 static void
3799 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3800 {
3801         MonoDynamicTable *table;
3802         guint32 *values;
3803         guint32 scope, scope_idx, impl, current_idx;
3804         gboolean forwarder = TRUE;
3805         gpointer iter = NULL;
3806         MonoClass *nested;
3807
3808         if (klass->nested_in) {
3809                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3810                 forwarder = FALSE;
3811         } else {
3812                 scope = resolution_scope_from_image (assembly, klass->image);
3813                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3814                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3815                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3816         }
3817
3818         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3819
3820         table->rows++;
3821         alloc_table (table, table->rows);
3822         current_idx = table->next_idx;
3823         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3824
3825         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3826         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3827         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3828         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3829         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3830
3831         table->next_idx++;
3832
3833         while ((nested = mono_class_get_nested_types (klass, &iter)))
3834                 add_exported_type (assemblyb, assembly, nested, current_idx);
3835 }
3836
3837 static void
3838 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3839 {
3840         MonoClass *klass;
3841         int i;
3842
3843         if (!assemblyb->type_forwarders)
3844                 return;
3845
3846         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3847                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3848                 MonoType *type;
3849                 if (!t)
3850                         continue;
3851
3852                 type = mono_reflection_type_get_handle (t);
3853                 g_assert (type);
3854
3855                 klass = mono_class_from_mono_type (type);
3856
3857                 add_exported_type (assemblyb, assembly, klass, 0);
3858         }
3859 }
3860
3861 #define align_pointer(base,p)\
3862         do {\
3863                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3864                 if (__diff & 3)\
3865                         (p) += 4 - (__diff & 3);\
3866         } while (0)
3867
3868 static int
3869 compare_constants (const void *a, const void *b)
3870 {
3871         const guint32 *a_values = a;
3872         const guint32 *b_values = b;
3873         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3874 }
3875
3876 static int
3877 compare_semantics (const void *a, const void *b)
3878 {
3879         const guint32 *a_values = a;
3880         const guint32 *b_values = b;
3881         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3882         if (assoc)
3883                 return assoc;
3884         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3885 }
3886
3887 static int
3888 compare_custom_attrs (const void *a, const void *b)
3889 {
3890         const guint32 *a_values = a;
3891         const guint32 *b_values = b;
3892
3893         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3894 }
3895
3896 static int
3897 compare_field_marshal (const void *a, const void *b)
3898 {
3899         const guint32 *a_values = a;
3900         const guint32 *b_values = b;
3901
3902         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3903 }
3904
3905 static int
3906 compare_nested (const void *a, const void *b)
3907 {
3908         const guint32 *a_values = a;
3909         const guint32 *b_values = b;
3910
3911         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3912 }
3913
3914 static int
3915 compare_genericparam (const void *a, const void *b)
3916 {
3917         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3918         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3919
3920         if ((*b_entry)->owner == (*a_entry)->owner)
3921                 return 
3922                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3923                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3924         else
3925                 return (*a_entry)->owner - (*b_entry)->owner;
3926 }
3927
3928 static int
3929 compare_declsecurity_attrs (const void *a, const void *b)
3930 {
3931         const guint32 *a_values = a;
3932         const guint32 *b_values = b;
3933
3934         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3935 }
3936
3937 static int
3938 compare_interface_impl (const void *a, const void *b)
3939 {
3940         const guint32 *a_values = a;
3941         const guint32 *b_values = b;
3942
3943         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3944         if (klass)
3945                 return klass;
3946
3947         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3948 }
3949
3950 static void
3951 pad_heap (MonoDynamicStream *sh)
3952 {
3953         if (sh->index & 3) {
3954                 int sz = 4 - (sh->index & 3);
3955                 memset (sh->data + sh->index, 0, sz);
3956                 sh->index += sz;
3957         }
3958 }
3959
3960 struct StreamDesc {
3961         const char *name;
3962         MonoDynamicStream *stream;
3963 };
3964
3965 /*
3966  * build_compressed_metadata() fills in the blob of data that represents the 
3967  * raw metadata as it will be saved in the PE file. The five streams are output 
3968  * and the metadata tables are comnpressed from the guint32 array representation, 
3969  * to the compressed on-disk format.
3970  */
3971 static void
3972 build_compressed_metadata (MonoDynamicImage *assembly)
3973 {
3974         MonoDynamicTable *table;
3975         int i;
3976         guint64 valid_mask = 0;
3977         guint64 sorted_mask;
3978         guint32 heapt_size = 0;
3979         guint32 meta_size = 256; /* allow for header and other stuff */
3980         guint32 table_offset;
3981         guint32 ntables = 0;
3982         guint64 *int64val;
3983         guint32 *int32val;
3984         guint16 *int16val;
3985         MonoImage *meta;
3986         unsigned char *p;
3987         struct StreamDesc stream_desc [5];
3988
3989         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3990         for (i = 0; i < assembly->gen_params->len; i++){
3991                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3992                 write_generic_param_entry (assembly, entry);
3993         }
3994
3995         stream_desc [0].name  = "#~";
3996         stream_desc [0].stream = &assembly->tstream;
3997         stream_desc [1].name  = "#Strings";
3998         stream_desc [1].stream = &assembly->sheap;
3999         stream_desc [2].name  = "#US";
4000         stream_desc [2].stream = &assembly->us;
4001         stream_desc [3].name  = "#Blob";
4002         stream_desc [3].stream = &assembly->blob;
4003         stream_desc [4].name  = "#GUID";
4004         stream_desc [4].stream = &assembly->guid;
4005         
4006         /* tables that are sorted */
4007         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4008                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4009                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4010                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4011                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4012                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4013                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4014         
4015         /* Compute table sizes */
4016         /* the MonoImage has already been created in mono_image_basic_init() */
4017         meta = &assembly->image;
4018
4019         /* sizes should be multiple of 4 */
4020         pad_heap (&assembly->blob);
4021         pad_heap (&assembly->guid);
4022         pad_heap (&assembly->sheap);
4023         pad_heap (&assembly->us);
4024
4025         /* Setup the info used by compute_sizes () */
4026         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4027         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4028         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4029
4030         meta_size += assembly->blob.index;
4031         meta_size += assembly->guid.index;
4032         meta_size += assembly->sheap.index;
4033         meta_size += assembly->us.index;
4034
4035         for (i=0; i < MONO_TABLE_NUM; ++i)
4036                 meta->tables [i].rows = assembly->tables [i].rows;
4037         
4038         for (i = 0; i < MONO_TABLE_NUM; i++){
4039                 if (meta->tables [i].rows == 0)
4040                         continue;
4041                 valid_mask |= (guint64)1 << i;
4042                 ntables ++;
4043                 meta->tables [i].row_size = mono_metadata_compute_size (
4044                         meta, i, &meta->tables [i].size_bitfield);
4045                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4046         }
4047         heapt_size += 24; /* #~ header size */
4048         heapt_size += ntables * 4;
4049         /* make multiple of 4 */
4050         heapt_size += 3;
4051         heapt_size &= ~3;
4052         meta_size += heapt_size;
4053         meta->raw_metadata = g_malloc0 (meta_size);
4054         p = (unsigned char*)meta->raw_metadata;
4055         /* the metadata signature */
4056         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4057         /* version numbers and 4 bytes reserved */
4058         int16val = (guint16*)p;
4059         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4060         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4061         p += 8;
4062         /* version string */
4063         int32val = (guint32*)p;
4064         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4065         p += 4;
4066         memcpy (p, meta->version, strlen (meta->version));
4067         p += GUINT32_FROM_LE (*int32val);
4068         align_pointer (meta->raw_metadata, p);
4069         int16val = (guint16*)p;
4070         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4071         *int16val = GUINT16_TO_LE (5); /* number of streams */
4072         p += 4;
4073
4074         /*
4075          * write the stream info.
4076          */
4077         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4078         table_offset += 3; table_offset &= ~3;
4079
4080         assembly->tstream.index = heapt_size;
4081         for (i = 0; i < 5; ++i) {
4082                 int32val = (guint32*)p;
4083                 stream_desc [i].stream->offset = table_offset;
4084                 *int32val++ = GUINT32_TO_LE (table_offset);
4085                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4086                 table_offset += GUINT32_FROM_LE (*int32val);
4087                 table_offset += 3; table_offset &= ~3;
4088                 p += 8;
4089                 strcpy ((char*)p, stream_desc [i].name);
4090                 p += strlen (stream_desc [i].name) + 1;
4091                 align_pointer (meta->raw_metadata, p);
4092         }
4093         /* 
4094          * now copy the data, the table stream header and contents goes first.
4095          */
4096         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4097         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4098         int32val = (guint32*)p;
4099         *int32val = GUINT32_TO_LE (0); /* reserved */
4100         p += 4;
4101
4102         *p++ = 2; /* version */
4103         *p++ = 0;
4104
4105         if (meta->idx_string_wide)
4106                 *p |= 0x01;
4107         if (meta->idx_guid_wide)
4108                 *p |= 0x02;
4109         if (meta->idx_blob_wide)
4110                 *p |= 0x04;
4111         ++p;
4112         *p++ = 1; /* reserved */
4113         int64val = (guint64*)p;
4114         *int64val++ = GUINT64_TO_LE (valid_mask);
4115         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4116         p += 16;
4117         int32val = (guint32*)p;
4118         for (i = 0; i < MONO_TABLE_NUM; i++){
4119                 if (meta->tables [i].rows == 0)
4120                         continue;
4121                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4122         }
4123         p = (unsigned char*)int32val;
4124
4125         /* sort the tables that still need sorting */
4126         table = &assembly->tables [MONO_TABLE_CONSTANT];
4127         if (table->rows)
4128                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4129         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4130         if (table->rows)
4131                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4132         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4133         if (table->rows)
4134                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4135         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4136         if (table->rows)
4137                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4138         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4139         if (table->rows)
4140                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4141         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4142         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4143         if (table->rows)
4144                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4145         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4146         if (table->rows)
4147                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4148
4149         /* compress the tables */
4150         for (i = 0; i < MONO_TABLE_NUM; i++){
4151                 int row, col;
4152                 guint32 *values;
4153                 guint32 bitfield = meta->tables [i].size_bitfield;
4154                 if (!meta->tables [i].rows)
4155                         continue;
4156                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4157                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4158                 meta->tables [i].base = (char*)p;
4159                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4160                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4161                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4162                                 switch (mono_metadata_table_size (bitfield, col)) {
4163                                 case 1:
4164                                         *p++ = values [col];
4165                                         break;
4166                                 case 2:
4167                                         *p++ = values [col] & 0xff;
4168                                         *p++ = (values [col] >> 8) & 0xff;
4169                                         break;
4170                                 case 4:
4171                                         *p++ = values [col] & 0xff;
4172                                         *p++ = (values [col] >> 8) & 0xff;
4173                                         *p++ = (values [col] >> 16) & 0xff;
4174                                         *p++ = (values [col] >> 24) & 0xff;
4175                                         break;
4176                                 default:
4177                                         g_assert_not_reached ();
4178                                 }
4179                         }
4180                 }
4181                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4182         }
4183         
4184         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4185         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4186         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4187         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4188         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4189
4190         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4191 }
4192
4193 /*
4194  * Some tables in metadata need to be sorted according to some criteria, but
4195  * when methods and fields are first created with reflection, they may be assigned a token
4196  * that doesn't correspond to the final token they will get assigned after the sorting.
4197  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4198  * with the reflection objects that represent them. Once all the tables are set up, the 
4199  * reflection objects will contains the correct table index. fixup_method() will fixup the
4200  * tokens for the method with ILGenerator @ilgen.
4201  */
4202 static void
4203 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4204 {
4205         guint32 code_idx = GPOINTER_TO_UINT (value);
4206         MonoReflectionILTokenInfo *iltoken;
4207         MonoReflectionFieldBuilder *field;
4208         MonoReflectionCtorBuilder *ctor;
4209         MonoReflectionMethodBuilder *method;
4210         MonoReflectionTypeBuilder *tb;
4211         MonoReflectionArrayMethod *am;
4212         guint32 i, idx = 0;
4213         unsigned char *target;
4214
4215         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4216                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4217                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4218                 switch (target [3]) {
4219                 case MONO_TABLE_FIELD:
4220                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4221                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4222                                 idx = field->table_idx;
4223                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4224                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4225                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4226                         } else {
4227                                 g_assert_not_reached ();
4228                         }
4229                         break;
4230                 case MONO_TABLE_METHOD:
4231                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4232                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4233                                 idx = method->table_idx;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4235                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4236                                 idx = ctor->table_idx;
4237                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4238                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4239                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4240                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4241                         } else {
4242                                 g_assert_not_reached ();
4243                         }
4244                         break;
4245                 case MONO_TABLE_TYPEDEF:
4246                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4247                                 g_assert_not_reached ();
4248                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4249                         idx = tb->table_idx;
4250                         break;
4251                 case MONO_TABLE_MEMBERREF:
4252                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4253                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4254                                 idx = am->table_idx;
4255                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4256                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4257                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4258                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4259                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4260                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4261                                 continue;
4262                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4263                                 continue;
4264                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4265                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4266                                 g_assert (is_field_on_inst (f));
4267                                 continue;
4268                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4269                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4270                                 continue;
4271                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4272                                 continue;
4273                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4274                                 continue;
4275                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4276                                 continue;
4277                         } else {
4278                                 g_assert_not_reached ();
4279                         }
4280                         break;
4281                 case MONO_TABLE_METHODSPEC:
4282                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4283                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4284                                 g_assert (mono_method_signature (m)->generic_param_count);
4285                                 continue;
4286                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4287                                 continue;
4288                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4289                                 continue;
4290                         } else {
4291                                 g_assert_not_reached ();
4292                         }
4293                         break;
4294                 default:
4295                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4296                 }
4297                 target [0] = idx & 0xff;
4298                 target [1] = (idx >> 8) & 0xff;
4299                 target [2] = (idx >> 16) & 0xff;
4300         }
4301 }
4302
4303 /*
4304  * fixup_cattrs:
4305  *
4306  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4307  * value is not known when the table is emitted.
4308  */
4309 static void
4310 fixup_cattrs (MonoDynamicImage *assembly)
4311 {
4312         MonoDynamicTable *table;
4313         guint32 *values;
4314         guint32 type, i, idx, token;
4315         MonoObject *ctor;
4316
4317         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4318
4319         for (i = 0; i < table->rows; ++i) {
4320                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4321
4322                 type = values [MONO_CUSTOM_ATTR_TYPE];
4323                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4324                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4325                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4326                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4327                         g_assert (ctor);
4328
4329                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")|| !strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4330                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4331                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4332                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4333                         }
4334                 }
4335         }
4336 }
4337
4338 static void
4339 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4340 {
4341         MonoDynamicTable *table;
4342         guint32 *values;
4343
4344         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4345         table->rows++;
4346         alloc_table (table, table->rows);
4347         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4348         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4349         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4350         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4351         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4352         table->next_idx++;
4353 }
4354
4355 static void
4356 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4357 {
4358         MonoDynamicTable *table;
4359         guint32 *values;
4360         char blob_size [6];
4361         guchar hash [20];
4362         char *b = blob_size;
4363         char *name, *sname;
4364         guint32 idx, offset;
4365
4366         if (rsrc->filename) {
4367                 name = mono_string_to_utf8 (rsrc->filename);
4368                 sname = g_path_get_basename (name);
4369         
4370                 table = &assembly->tables [MONO_TABLE_FILE];
4371                 table->rows++;
4372                 alloc_table (table, table->rows);
4373                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4374                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4375                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4376                 g_free (sname);
4377
4378                 mono_sha1_get_digest_from_file (name, hash);
4379                 mono_metadata_encode_value (20, b, &b);
4380                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4381                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4382                 g_free (name);
4383                 idx = table->next_idx++;
4384                 rsrc->offset = 0;
4385                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4386         } else {
4387                 char sizebuf [4];
4388                 char *data;
4389                 guint len;
4390                 if (rsrc->data) {
4391                         data = mono_array_addr (rsrc->data, char, 0);
4392                         len = mono_array_length (rsrc->data);
4393                 } else {
4394                         data = NULL;
4395                         len = 0;
4396                 }
4397                 offset = len;
4398                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4399                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4400                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4401                 mono_image_add_stream_data (&assembly->resources, data, len);
4402
4403                 if (!mb->is_main)
4404                         /* 
4405                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4406                          * the main module, but that needs to reference the FILE table
4407                          * which isn't emitted yet.
4408                          */
4409                         return;
4410                 else
4411                         idx = 0;
4412         }
4413
4414         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4415 }
4416
4417 static void
4418 set_version_from_string (MonoString *version, guint32 *values)
4419 {
4420         gchar *ver, *p, *str;
4421         guint32 i;
4422         
4423         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4424         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4425         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4426         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4427         if (!version)
4428                 return;
4429         ver = str = mono_string_to_utf8 (version);
4430         for (i = 0; i < 4; ++i) {
4431                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4432                 switch (*p) {
4433                 case '.':
4434                         p++;
4435                         break;
4436                 case '*':
4437                         /* handle Revision and Build */
4438                         p++;
4439                         break;
4440                 }
4441                 ver = p;
4442         }
4443         g_free (str);
4444 }
4445
4446 static guint32
4447 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4448         gsize len;
4449         guint32 token = 0;
4450         char blob_size [6];
4451         char *b = blob_size;
4452
4453         if (!pkey)
4454                 return token;
4455
4456         len = mono_array_length (pkey);
4457         mono_metadata_encode_value (len, b, &b);
4458         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4459         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4460
4461         assembly->public_key = g_malloc (len);
4462         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4463         assembly->public_key_len = len;
4464
4465         /* Special case: check for ECMA key (16 bytes) */
4466         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4467                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4468                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4469         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4470                 /* minimum key size (in 2.0) is 384 bits */
4471                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4472         } else {
4473                 /* FIXME - verifier */
4474                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4475                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4476         }
4477         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4478
4479         return token;
4480 }
4481
4482 static void
4483 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4484 {
4485         MonoDynamicTable *table;
4486         MonoDynamicImage *assembly;
4487         MonoReflectionAssemblyBuilder *assemblyb;
4488         MonoDomain *domain;
4489         guint32 *values;
4490         int i;
4491         guint32 module_index;
4492
4493         assemblyb = moduleb->assemblyb;
4494         assembly = moduleb->dynamic_image;
4495         domain = mono_object_domain (assemblyb);
4496
4497         /* Emit ASSEMBLY table */
4498         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4499         alloc_table (table, 1);
4500         values = table->values + MONO_ASSEMBLY_SIZE;
4501         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4502         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4503         if (assemblyb->culture) {
4504                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4505         } else {
4506                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4507         }
4508         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4509         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4510         set_version_from_string (assemblyb->version, values);
4511
4512         /* Emit FILE + EXPORTED_TYPE table */
4513         module_index = 0;
4514         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4515                 int j;
4516                 MonoReflectionModuleBuilder *file_module = 
4517                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4518                 if (file_module != moduleb) {
4519                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4520                         module_index ++;
4521                         if (file_module->types) {
4522                                 for (j = 0; j < file_module->num_types; ++j) {
4523                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4524                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4525                                 }
4526                         }
4527                 }
4528         }
4529         if (assemblyb->loaded_modules) {
4530                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4531                         MonoReflectionModule *file_module = 
4532                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4533                         mono_image_fill_file_table (domain, file_module, assembly);
4534                         module_index ++;
4535                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4536                 }
4537         }
4538         if (assemblyb->type_forwarders)
4539                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4540
4541         /* Emit MANIFESTRESOURCE table */
4542         module_index = 0;
4543         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4544                 int j;
4545                 MonoReflectionModuleBuilder *file_module = 
4546                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4547                 /* The table for the main module is emitted later */
4548                 if (file_module != moduleb) {
4549                         module_index ++;
4550                         if (file_module->resources) {
4551                                 int len = mono_array_length (file_module->resources);
4552                                 for (j = 0; j < len; ++j) {
4553                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4554                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4555                                 }
4556                         }
4557                 }
4558         }               
4559 }
4560
4561 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4562
4563 /*
4564  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4565  * for the modulebuilder @moduleb.
4566  * At the end of the process, method and field tokens are fixed up and the 
4567  * on-disk compressed metadata representation is created.
4568  */
4569 void
4570 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4571 {
4572         MonoDynamicTable *table;
4573         MonoDynamicImage *assembly;
4574         MonoReflectionAssemblyBuilder *assemblyb;
4575         MonoDomain *domain;
4576         MonoPtrArray types;
4577         guint32 *values;
4578         int i, j;
4579
4580         assemblyb = moduleb->assemblyb;
4581         assembly = moduleb->dynamic_image;
4582         domain = mono_object_domain (assemblyb);
4583
4584         if (assembly->text_rva)
4585                 return;
4586
4587         assembly->text_rva = START_TEXT_RVA;
4588
4589         if (moduleb->is_main) {
4590                 mono_image_emit_manifest (moduleb);
4591         }
4592
4593         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4594         table->rows = 1; /* .<Module> */
4595         table->next_idx++;
4596         alloc_table (table, table->rows);
4597         /*
4598          * Set the first entry.
4599          */
4600         values = table->values + table->columns;
4601         values [MONO_TYPEDEF_FLAGS] = 0;
4602         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4603         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4604         values [MONO_TYPEDEF_EXTENDS] = 0;
4605         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4606         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4607
4608         /* 
4609          * handle global methods 
4610          * FIXME: test what to do when global methods are defined in multiple modules.
4611          */
4612         if (moduleb->global_methods) {
4613                 table = &assembly->tables [MONO_TABLE_METHOD];
4614                 table->rows += mono_array_length (moduleb->global_methods);
4615                 alloc_table (table, table->rows);
4616                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4617                         mono_image_get_method_info (
4618                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4619         }
4620         if (moduleb->global_fields) {
4621                 table = &assembly->tables [MONO_TABLE_FIELD];
4622                 table->rows += mono_array_length (moduleb->global_fields);
4623                 alloc_table (table, table->rows);
4624                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4625                         mono_image_get_field_info (
4626                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4627         }
4628
4629         table = &assembly->tables [MONO_TABLE_MODULE];
4630         alloc_table (table, 1);
4631         mono_image_fill_module_table (domain, moduleb, assembly);
4632
4633         /* Collect all types into a list sorted by their table_idx */
4634         mono_ptr_array_init (types, moduleb->num_types);
4635
4636         if (moduleb->types)
4637                 for (i = 0; i < moduleb->num_types; ++i) {
4638                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4639                         collect_types (&types, type);
4640                 }
4641
4642         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4643         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4644         table->rows += mono_ptr_array_size (types);
4645         alloc_table (table, table->rows);
4646
4647         /*
4648          * Emit type names + namespaces at one place inside the string heap,
4649          * so load_class_names () needs to touch fewer pages.
4650          */
4651         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4652                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4653                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4654         }
4655         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4656                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4657                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4658         }
4659
4660         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4661                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4662                 mono_image_get_type_info (domain, type, assembly);
4663         }
4664
4665         /* 
4666          * table->rows is already set above and in mono_image_fill_module_table.
4667          */
4668         /* add all the custom attributes at the end, once all the indexes are stable */
4669         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4670
4671         /* CAS assembly permissions */
4672         if (assemblyb->permissions_minimum)
4673                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4674         if (assemblyb->permissions_optional)
4675                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4676         if (assemblyb->permissions_refused)
4677                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4678
4679         module_add_cattrs (assembly, moduleb);
4680
4681         /* fixup tokens */
4682         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4683
4684         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4685          * the final tokens and don't need another fixup pass. */
4686
4687         if (moduleb->global_methods) {
4688                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4689                         MonoReflectionMethodBuilder *mb = mono_array_get (
4690                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4691                         mono_image_add_methodimpl (assembly, mb);
4692                 }
4693         }
4694
4695         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4696                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4697                 if (type->methods) {
4698                         for (j = 0; j < type->num_methods; ++j) {
4699                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4700                                         type->methods, MonoReflectionMethodBuilder*, j);
4701
4702                                 mono_image_add_methodimpl (assembly, mb);
4703                         }
4704                 }
4705         }
4706
4707         mono_ptr_array_destroy (types);
4708
4709         fixup_cattrs (assembly);
4710 }
4711
4712 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4713
4714 void
4715 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4716 {
4717         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4718 }
4719
4720 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4721
4722
4723 typedef struct {
4724         guint32 import_lookup_table;
4725         guint32 timestamp;
4726         guint32 forwarder;
4727         guint32 name_rva;
4728         guint32 import_address_table_rva;
4729 } MonoIDT;
4730
4731 typedef struct {
4732         guint32 name_rva;
4733         guint32 flags;
4734 } MonoILT;
4735
4736 #ifndef DISABLE_REFLECTION_EMIT
4737
4738 /*
4739  * mono_image_insert_string:
4740  * @module: module builder object
4741  * @str: a string
4742  *
4743  * Insert @str into the user string stream of @module.
4744  */
4745 guint32
4746 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4747 {
4748         MonoDynamicImage *assembly;
4749         guint32 idx;
4750         char buf [16];
4751         char *b = buf;
4752         
4753         MONO_ARCH_SAVE_REGS;
4754
4755         if (!module->dynamic_image)
4756                 mono_image_module_basic_init (module);
4757
4758         assembly = module->dynamic_image;
4759         
4760         if (assembly->save) {
4761                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4762                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4763 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4764         {
4765                 char *swapped = g_malloc (2 * mono_string_length (str));
4766                 const char *p = (const char*)mono_string_chars (str);
4767
4768                 swap_with_size (swapped, p, 2, mono_string_length (str));
4769                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4770                 g_free (swapped);
4771         }
4772 #else
4773                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4774 #endif
4775                 mono_image_add_stream_data (&assembly->us, "", 1);
4776         } else {
4777                 idx = assembly->us.index ++;
4778         }
4779
4780         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4781
4782         return MONO_TOKEN_STRING | idx;
4783 }
4784
4785 guint32
4786 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4787 {
4788         MonoClass *klass;
4789         guint32 token = 0;
4790         MonoMethodSignature *sig;
4791
4792         klass = obj->vtable->klass;
4793         if (strcmp (klass->name, "MonoMethod") == 0) {
4794                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4795                 MonoMethodSignature *old;
4796                 guint32 sig_token, parent;
4797                 int nargs, i;
4798
4799                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4800
4801                 nargs = mono_array_length (opt_param_types);
4802                 old = mono_method_signature (method);
4803                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4804
4805                 sig->hasthis = old->hasthis;
4806                 sig->explicit_this = old->explicit_this;
4807                 sig->call_convention = old->call_convention;
4808                 sig->generic_param_count = old->generic_param_count;
4809                 sig->param_count = old->param_count + nargs;
4810                 sig->sentinelpos = old->param_count;
4811                 sig->ret = old->ret;
4812
4813                 for (i = 0; i < old->param_count; i++)
4814                         sig->params [i] = old->params [i];
4815
4816                 for (i = 0; i < nargs; i++) {
4817                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4818                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4819                 }
4820
4821                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4822                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4823                 parent >>= MONO_TYPEDEFORREF_BITS;
4824
4825                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4826                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4827
4828                 sig_token = method_encode_signature (assembly, sig);
4829                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4830         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4831                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4832                 ReflectionMethodBuilder rmb;
4833                 guint32 parent, sig_token;
4834                 int nopt_args, nparams, ngparams, i;
4835                 char *name;
4836
4837                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4838                 rmb.opt_types = opt_param_types;
4839                 nopt_args = mono_array_length (opt_param_types);
4840
4841                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4842                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4843                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4844
4845                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4846                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4847                 sig->call_convention = rmb.call_conv;
4848                 sig->generic_param_count = ngparams;
4849                 sig->param_count = nparams + nopt_args;
4850                 sig->sentinelpos = nparams;
4851                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4852
4853                 for (i = 0; i < nparams; i++) {
4854                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4855                         sig->params [i] = mono_reflection_type_get_handle (rt);
4856                 }
4857
4858                 for (i = 0; i < nopt_args; i++) {
4859                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4860                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4861                 }
4862
4863                 sig_token = method_builder_encode_signature (assembly, &rmb);
4864
4865                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4866                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4867
4868                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4869                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4870
4871                 name = mono_string_to_utf8 (rmb.name);
4872                 token = mono_image_get_varargs_method_token (
4873                         assembly, parent, name, sig_token);
4874                 g_free (name);
4875         } else {
4876                 g_error ("requested method token for %s\n", klass->name);
4877         }
4878
4879         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4880         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4881         return token;
4882 }
4883
4884 /*
4885  * mono_image_create_token:
4886  * @assembly: a dynamic assembly
4887  * @obj:
4888  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4889  *
4890  * Get a token to insert in the IL code stream for the given MemberInfo.
4891  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4892  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4893  * entry.
4894  */
4895 guint32
4896 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4897                                                  gboolean create_open_instance, gboolean register_token)
4898 {
4899         MonoClass *klass;
4900         guint32 token = 0;
4901
4902         klass = obj->vtable->klass;
4903
4904         /* Check for user defined reflection objects */
4905         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4906         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4907                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4908
4909         if (strcmp (klass->name, "MethodBuilder") == 0) {
4910                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4911                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4912
4913                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4914                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4915                 else
4916                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4917                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4918         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4919                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4920                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4921
4922                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4923                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4924                 else
4925                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4926                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4927         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4928                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4929                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4930                 if (tb->generic_params) {
4931                         token = mono_image_get_generic_field_token (assembly, fb);
4932                 } else {
4933                         if (tb->module->dynamic_image == assembly) {
4934                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4935                         } else {
4936                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4937                         }
4938                 }
4939         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4940                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4941                 if (create_open_instance && tb->generic_params) {
4942                         MonoType *type;
4943                         init_type_builder_generics (obj);
4944                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4945                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4946                         token = mono_metadata_token_from_dor (token);
4947                 } else if (tb->module->dynamic_image == assembly) {
4948                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4949                 } else {
4950                         MonoType *type;
4951                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4952                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4953                 }
4954         } else if (strcmp (klass->name, "MonoType") == 0) {
4955                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4956                 MonoClass *mc = mono_class_from_mono_type (type);
4957                 token = mono_metadata_token_from_dor (
4958                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4959         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4960                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4961                 token = mono_metadata_token_from_dor (
4962                         mono_image_typedef_or_ref (assembly, type));
4963         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4964                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4965                 token = mono_metadata_token_from_dor (
4966                         mono_image_typedef_or_ref (assembly, type));
4967         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4968                    strcmp (klass->name, "MonoMethod") == 0 ||
4969                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4970                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4971                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4972                 if (m->method->is_inflated) {
4973                         if (create_open_instance)
4974                                 token = mono_image_get_methodspec_token (assembly, m->method);
4975                         else
4976                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4977                 } else if ((m->method->klass->image == &assembly->image) &&
4978                          !m->method->klass->generic_class) {
4979                         static guint32 method_table_idx = 0xffffff;
4980                         if (m->method->klass->wastypebuilder) {
4981                                 /* we use the same token as the one that was assigned
4982                                  * to the Methodbuilder.
4983                                  * FIXME: do the equivalent for Fields.
4984                                  */
4985                                 token = m->method->token;
4986                         } else {
4987                                 /*
4988                                  * Each token should have a unique index, but the indexes are
4989                                  * assigned by managed code, so we don't know about them. An
4990                                  * easy solution is to count backwards...
4991                                  */
4992                                 method_table_idx --;
4993                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4994                         }
4995                 } else {
4996                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4997                 }
4998                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4999         } else if (strcmp (klass->name, "MonoField") == 0) {
5000                 MonoReflectionField *f = (MonoReflectionField *)obj;
5001                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5002                         static guint32 field_table_idx = 0xffffff;
5003                         field_table_idx --;
5004                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5005                 } else {
5006                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5007                 }
5008                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5009         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5010                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5011                 token = mono_image_get_array_token (assembly, m);
5012         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5013                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5014                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5015         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5016                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5017                 token = mono_metadata_token_from_dor (
5018                         mono_image_typedef_or_ref (assembly, type));
5019         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5020                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5021                 token = mono_image_get_field_on_inst_token (assembly, f);
5022         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5023                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5024                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5025         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5026                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5027                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5028         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5029                 MonoReflectionType *type = (MonoReflectionType *)obj;
5030                 token = mono_metadata_token_from_dor (
5031                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5032         } else {
5033                 g_error ("requested token for %s\n", klass->name);
5034         }
5035
5036         if (register_token)
5037                 mono_image_register_token (assembly, token, obj);
5038
5039         return token;
5040 }
5041
5042 /*
5043  * mono_image_register_token:
5044  *
5045  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5046  * the Module.ResolveXXXToken () methods to work.
5047  */
5048 void
5049 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5050 {
5051         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5052         if (prev) {
5053                 /* There could be multiple MethodInfo objects with the same token */
5054                 //g_assert (prev == obj);
5055         } else {
5056                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5057         }
5058 }
5059
5060 static MonoDynamicImage*
5061 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5062 {
5063         static const guchar entrycode [16] = {0xff, 0x25, 0};
5064         MonoDynamicImage *image;
5065         int i;
5066
5067         const char *version;
5068
5069         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5070                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5071         else
5072                 version = mono_get_runtime_info ()->runtime_version;
5073
5074 #if HAVE_BOEHM_GC
5075         /* The MonoGHashTable's need GC tracking */
5076         image = GC_MALLOC (sizeof (MonoDynamicImage));
5077 #else
5078         image = g_new0 (MonoDynamicImage, 1);
5079 #endif
5080         
5081         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5082         
5083         /*g_print ("created image %p\n", image);*/
5084         /* keep in sync with image.c */
5085         image->image.name = assembly_name;
5086         image->image.assembly_name = image->image.name; /* they may be different */
5087         image->image.module_name = module_name;
5088         image->image.version = g_strdup (version);
5089         image->image.md_version_major = 1;
5090         image->image.md_version_minor = 1;
5091         image->image.dynamic = TRUE;
5092
5093         image->image.references = g_new0 (MonoAssembly*, 1);
5094         image->image.references [0] = NULL;
5095
5096         mono_image_init (&image->image);
5097
5098         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5099         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5100         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5101         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5102         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5103         image->handleref = g_hash_table_new (NULL, NULL);
5104         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5105         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5106         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5107         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5108         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5109         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5110         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5111         image->gen_params = g_ptr_array_new ();
5112
5113         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5114         string_heap_init (&image->sheap);
5115         mono_image_add_stream_data (&image->us, "", 1);
5116         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5117         /* import tables... */
5118         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5119         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5120         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5121         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5122         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5123         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5124         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5125         stream_data_align (&image->code);
5126
5127         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5128
5129         for (i=0; i < MONO_TABLE_NUM; ++i) {
5130                 image->tables [i].next_idx = 1;
5131                 image->tables [i].columns = table_sizes [i];
5132         }
5133
5134         image->image.assembly = (MonoAssembly*)assembly;
5135         image->run = assembly->run;
5136         image->save = assembly->save;
5137         image->pe_kind = 0x1; /* ILOnly */
5138         image->machine = 0x14c; /* I386 */
5139         
5140         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5141
5142         return image;
5143 }
5144 #endif
5145
5146 static void
5147 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5148 {
5149         g_free (key);
5150 }
5151
5152 void
5153 mono_dynamic_image_free (MonoDynamicImage *image)
5154 {
5155         MonoDynamicImage *di = image;
5156         GList *list;
5157         int i;
5158
5159         if (di->methodspec)
5160                 mono_g_hash_table_destroy (di->methodspec);
5161         if (di->typespec)
5162                 g_hash_table_destroy (di->typespec);
5163         if (di->typeref)
5164                 g_hash_table_destroy (di->typeref);
5165         if (di->handleref)
5166                 g_hash_table_destroy (di->handleref);
5167         if (di->handleref_managed)
5168                 mono_g_hash_table_destroy (di->handleref_managed);
5169         if (di->tokens)
5170                 mono_g_hash_table_destroy (di->tokens);
5171         if (di->generic_def_objects)
5172                 mono_g_hash_table_destroy (di->generic_def_objects);
5173         if (di->blob_cache) {
5174                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5175                 g_hash_table_destroy (di->blob_cache);
5176         }
5177         if (di->standalonesig_cache)
5178                 g_hash_table_destroy (di->standalonesig_cache);
5179         for (list = di->array_methods; list; list = list->next) {
5180                 ArrayMethod *am = (ArrayMethod *)list->data;
5181                 g_free (am->sig);
5182                 g_free (am->name);
5183                 g_free (am);
5184         }
5185         g_list_free (di->array_methods);
5186         if (di->gen_params) {
5187                 for (i = 0; i < di->gen_params->len; i++) {
5188                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5189                         mono_gc_deregister_root ((char*) &entry->gparam);
5190                         g_free (entry);
5191                 }
5192                 g_ptr_array_free (di->gen_params, TRUE);
5193         }
5194         if (di->token_fixups)
5195                 mono_g_hash_table_destroy (di->token_fixups);
5196         if (di->method_to_table_idx)
5197                 g_hash_table_destroy (di->method_to_table_idx);
5198         if (di->field_to_table_idx)
5199                 g_hash_table_destroy (di->field_to_table_idx);
5200         if (di->method_aux_hash)
5201                 g_hash_table_destroy (di->method_aux_hash);
5202         if (di->vararg_aux_hash)
5203                 g_hash_table_destroy (di->vararg_aux_hash);
5204         g_free (di->strong_name);
5205         g_free (di->win32_res);
5206         if (di->public_key)
5207                 g_free (di->public_key);
5208
5209         /*g_print ("string heap destroy for image %p\n", di);*/
5210         mono_dynamic_stream_reset (&di->sheap);
5211         mono_dynamic_stream_reset (&di->code);
5212         mono_dynamic_stream_reset (&di->resources);
5213         mono_dynamic_stream_reset (&di->us);
5214         mono_dynamic_stream_reset (&di->blob);
5215         mono_dynamic_stream_reset (&di->tstream);
5216         mono_dynamic_stream_reset (&di->guid);
5217         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5218                 g_free (di->tables [i].values);
5219         }
5220 }       
5221
5222 #ifndef DISABLE_REFLECTION_EMIT
5223
5224 /*
5225  * mono_image_basic_init:
5226  * @assembly: an assembly builder object
5227  *
5228  * Create the MonoImage that represents the assembly builder and setup some
5229  * of the helper hash table and the basic metadata streams.
5230  */
5231 void
5232 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5233 {
5234         MonoDynamicAssembly *assembly;
5235         MonoDynamicImage *image;
5236         MonoDomain *domain = mono_object_domain (assemblyb);
5237         
5238         MONO_ARCH_SAVE_REGS;
5239
5240         if (assemblyb->dynamic_assembly)
5241                 return;
5242
5243 #if HAVE_BOEHM_GC
5244         /* assembly->assembly.image might be GC allocated */
5245         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5246 #else
5247         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5248 #endif
5249
5250         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5251         
5252         assembly->assembly.ref_count = 1;
5253         assembly->assembly.dynamic = TRUE;
5254         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5255         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5256         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5257         if (assemblyb->culture)
5258                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5259         else
5260                 assembly->assembly.aname.culture = g_strdup ("");
5261
5262         if (assemblyb->version) {
5263                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5264                         char **version = g_strsplit (vstr, ".", 4);
5265                         char **parts = version;
5266                         assembly->assembly.aname.major = atoi (*parts++);
5267                         assembly->assembly.aname.minor = atoi (*parts++);
5268                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5269                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5270
5271                         g_strfreev (version);
5272                         g_free (vstr);
5273         } else {
5274                         assembly->assembly.aname.major = 0;
5275                         assembly->assembly.aname.minor = 0;
5276                         assembly->assembly.aname.build = 0;
5277                         assembly->assembly.aname.revision = 0;
5278         }
5279
5280         assembly->run = assemblyb->access != 2;
5281         assembly->save = assemblyb->access != 1;
5282         assembly->domain = domain;
5283
5284         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5285         image->initial_image = TRUE;
5286         assembly->assembly.aname.name = image->image.name;
5287         assembly->assembly.image = &image->image;
5288         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5289                 /* -1 to correct for the trailing NULL byte */
5290                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5291                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5292                 }
5293                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5294         }
5295
5296         mono_domain_assemblies_lock (domain);
5297         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5298         mono_domain_assemblies_unlock (domain);
5299
5300         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5301         
5302         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5303         
5304         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5305 }
5306
5307 #endif /* !DISABLE_REFLECTION_EMIT */
5308
5309 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5310
5311 static int
5312 calc_section_size (MonoDynamicImage *assembly)
5313 {
5314         int nsections = 0;
5315
5316         /* alignment constraints */
5317         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5318         g_assert ((assembly->code.index % 4) == 0);
5319         assembly->meta_size += 3;
5320         assembly->meta_size &= ~3;
5321         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5322         g_assert ((assembly->resources.index % 4) == 0);
5323
5324         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5325         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5326         nsections++;
5327
5328         if (assembly->win32_res) {
5329                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5330
5331                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5332                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5333                 nsections++;
5334         }
5335
5336         assembly->sections [MONO_SECTION_RELOC].size = 12;
5337         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5338         nsections++;
5339
5340         return nsections;
5341 }
5342
5343 typedef struct {
5344         guint32 id;
5345         guint32 offset;
5346         GSList *children;
5347         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5348 } ResTreeNode;
5349
5350 static int
5351 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5352 {
5353         ResTreeNode *t1 = (ResTreeNode*)a;
5354         ResTreeNode *t2 = (ResTreeNode*)b;
5355
5356         return t1->id - t2->id;
5357 }
5358
5359 /*
5360  * resource_tree_create:
5361  *
5362  *  Organize the resources into a resource tree.
5363  */
5364 static ResTreeNode *
5365 resource_tree_create (MonoArray *win32_resources)
5366 {
5367         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5368         GSList *l;
5369         int i;
5370
5371         tree = g_new0 (ResTreeNode, 1);
5372         
5373         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5374                 MonoReflectionWin32Resource *win32_res =
5375                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5376
5377                 /* Create node */
5378
5379                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5380                 lang_node = g_new0 (ResTreeNode, 1);
5381                 lang_node->id = win32_res->lang_id;
5382                 lang_node->win32_res = win32_res;
5383
5384                 /* Create type node if neccesary */
5385                 type_node = NULL;
5386                 for (l = tree->children; l; l = l->next)
5387                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5388                                 type_node = (ResTreeNode*)l->data;
5389                                 break;
5390                         }
5391
5392                 if (!type_node) {
5393                         type_node = g_new0 (ResTreeNode, 1);
5394                         type_node->id = win32_res->res_type;
5395
5396                         /* 
5397                          * The resource types have to be sorted otherwise
5398                          * Windows Explorer can't display the version information.
5399                          */
5400                         tree->children = g_slist_insert_sorted (tree->children, 
5401                                 type_node, resource_tree_compare_by_id);
5402                 }
5403
5404                 /* Create res node if neccesary */
5405                 res_node = NULL;
5406                 for (l = type_node->children; l; l = l->next)
5407                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5408                                 res_node = (ResTreeNode*)l->data;
5409                                 break;
5410                         }
5411
5412                 if (!res_node) {
5413                         res_node = g_new0 (ResTreeNode, 1);
5414                         res_node->id = win32_res->res_id;
5415                         type_node->children = g_slist_append (type_node->children, res_node);
5416                 }
5417
5418                 res_node->children = g_slist_append (res_node->children, lang_node);
5419         }
5420
5421         return tree;
5422 }
5423
5424 /*
5425  * resource_tree_encode:
5426  * 
5427  *   Encode the resource tree into the format used in the PE file.
5428  */
5429 static void
5430 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5431 {
5432         char *entries;
5433         MonoPEResourceDir dir;
5434         MonoPEResourceDirEntry dir_entry;
5435         MonoPEResourceDataEntry data_entry;
5436         GSList *l;
5437         guint32 res_id_entries;
5438
5439         /*
5440          * For the format of the resource directory, see the article
5441          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5442          * Matt Pietrek
5443          */
5444
5445         memset (&dir, 0, sizeof (dir));
5446         memset (&dir_entry, 0, sizeof (dir_entry));
5447         memset (&data_entry, 0, sizeof (data_entry));
5448
5449         g_assert (sizeof (dir) == 16);
5450         g_assert (sizeof (dir_entry) == 8);
5451         g_assert (sizeof (data_entry) == 16);
5452
5453         node->offset = p - begin;
5454
5455         /* IMAGE_RESOURCE_DIRECTORY */
5456         res_id_entries = g_slist_length (node->children);
5457         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5458
5459         memcpy (p, &dir, sizeof (dir));
5460         p += sizeof (dir);
5461
5462         /* Reserve space for entries */
5463         entries = p;
5464         p += sizeof (dir_entry) * res_id_entries;
5465
5466         /* Write children */
5467         for (l = node->children; l; l = l->next) {
5468                 ResTreeNode *child = (ResTreeNode*)l->data;
5469
5470                 if (child->win32_res) {
5471                         guint32 size;
5472
5473                         child->offset = p - begin;
5474
5475                         /* IMAGE_RESOURCE_DATA_ENTRY */
5476                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5477                         size = mono_array_length (child->win32_res->res_data);
5478                         data_entry.rde_size = GUINT32_TO_LE (size);
5479
5480                         memcpy (p, &data_entry, sizeof (data_entry));
5481                         p += sizeof (data_entry);
5482
5483                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5484                         p += size;
5485                 } else {
5486                         resource_tree_encode (child, begin, p, &p);
5487                 }
5488         }
5489
5490         /* IMAGE_RESOURCE_ENTRY */
5491         for (l = node->children; l; l = l->next) {
5492                 ResTreeNode *child = (ResTreeNode*)l->data;
5493
5494                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5495                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5496
5497                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5498                 entries += sizeof (dir_entry);
5499         }
5500
5501         *endbuf = p;
5502 }
5503
5504 static void
5505 resource_tree_free (ResTreeNode * node)
5506 {
5507         GSList * list;
5508         for (list = node->children; list; list = list->next)
5509                 resource_tree_free ((ResTreeNode*)list->data);
5510         g_slist_free(node->children);
5511         g_free (node);
5512 }
5513
5514 static void
5515 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5516 {
5517         char *buf;
5518         char *p;
5519         guint32 size, i;
5520         MonoReflectionWin32Resource *win32_res;
5521         ResTreeNode *tree;
5522
5523         if (!assemblyb->win32_resources)
5524                 return;
5525
5526         /*
5527          * Resources are stored in a three level tree inside the PE file.
5528          * - level one contains a node for each type of resource
5529          * - level two contains a node for each resource
5530          * - level three contains a node for each instance of a resource for a
5531          *   specific language.
5532          */
5533
5534         tree = resource_tree_create (assemblyb->win32_resources);
5535
5536         /* Estimate the size of the encoded tree */
5537         size = 0;
5538         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5539                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5540                 size += mono_array_length (win32_res->res_data);
5541         }
5542         /* Directory structure */
5543         size += mono_array_length (assemblyb->win32_resources) * 256;
5544         p = buf = g_malloc (size);
5545
5546         resource_tree_encode (tree, p, p, &p);
5547
5548         g_assert (p - buf <= size);
5549
5550         assembly->win32_res = g_malloc (p - buf);
5551         assembly->win32_res_size = p - buf;
5552         memcpy (assembly->win32_res, buf, p - buf);
5553
5554         g_free (buf);
5555         resource_tree_free (tree);
5556 }
5557
5558 static void
5559 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5560 {
5561         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5562         int i;
5563
5564         p += sizeof (MonoPEResourceDir);
5565         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5566                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5567                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5568                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5569                         fixup_resource_directory (res_section, child, rva);
5570                 } else {
5571                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5572                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5573                 }
5574
5575                 p += sizeof (MonoPEResourceDirEntry);
5576         }
5577 }
5578
5579 static void
5580 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5581 {
5582         guint32 dummy;
5583         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5584                 g_error ("WriteFile returned %d\n", GetLastError ());
5585 }
5586
5587 /*
5588  * mono_image_create_pefile:
5589  * @mb: a module builder object
5590  * 
5591  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5592  * assembly->pefile where it can be easily retrieved later in chunks.
5593  */
5594 void
5595 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5596 {
5597         MonoMSDOSHeader *msdos;
5598         MonoDotNetHeader *header;
5599         MonoSectionTable *section;
5600         MonoCLIHeader *cli_header;
5601         guint32 size, image_size, virtual_base, text_offset;
5602         guint32 header_start, section_start, file_offset, virtual_offset;
5603         MonoDynamicImage *assembly;
5604         MonoReflectionAssemblyBuilder *assemblyb;
5605         MonoDynamicStream pefile_stream = {0};
5606         MonoDynamicStream *pefile = &pefile_stream;
5607         int i, nsections;
5608         guint32 *rva, value;
5609         guchar *p;
5610         static const unsigned char msheader[] = {
5611                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5612                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5613                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5614                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5615                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5616                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5617                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5618                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5619         };
5620
5621         assemblyb = mb->assemblyb;
5622
5623         mono_image_basic_init (assemblyb);
5624         assembly = mb->dynamic_image;
5625
5626         assembly->pe_kind = assemblyb->pe_kind;
5627         assembly->machine = assemblyb->machine;
5628         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5629         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5630         
5631         mono_image_build_metadata (mb);
5632
5633         if (mb->is_main && assemblyb->resources) {
5634                 int len = mono_array_length (assemblyb->resources);
5635                 for (i = 0; i < len; ++i)
5636                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5637         }
5638
5639         if (mb->resources) {
5640                 int len = mono_array_length (mb->resources);
5641                 for (i = 0; i < len; ++i)
5642                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5643         }
5644
5645         build_compressed_metadata (assembly);
5646
5647         if (mb->is_main)
5648                 assembly_add_win32_resources (assembly, assemblyb);
5649
5650         nsections = calc_section_size (assembly);
5651         
5652         /* The DOS header and stub */
5653         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5654         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5655
5656         /* the dotnet header */
5657         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5658
5659         /* the section tables */
5660         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5661
5662         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5663         virtual_offset = VIRT_ALIGN;
5664         image_size = 0;
5665
5666         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5667                 if (!assembly->sections [i].size)
5668                         continue;
5669                 /* align offsets */
5670                 file_offset += FILE_ALIGN - 1;
5671                 file_offset &= ~(FILE_ALIGN - 1);
5672                 virtual_offset += VIRT_ALIGN - 1;
5673                 virtual_offset &= ~(VIRT_ALIGN - 1);
5674
5675                 assembly->sections [i].offset = file_offset;
5676                 assembly->sections [i].rva = virtual_offset;
5677
5678                 file_offset += assembly->sections [i].size;
5679                 virtual_offset += assembly->sections [i].size;
5680                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5681         }
5682
5683         file_offset += FILE_ALIGN - 1;
5684         file_offset &= ~(FILE_ALIGN - 1);
5685
5686         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5687
5688         /* back-patch info */
5689         msdos = (MonoMSDOSHeader*)pefile->data;
5690         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5691
5692         header = (MonoDotNetHeader*)(pefile->data + header_start);
5693         header->pesig [0] = 'P';
5694         header->pesig [1] = 'E';
5695         
5696         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5697         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5698         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5699         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5700         if (assemblyb->pekind == 1) {
5701                 /* it's a dll */
5702                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5703         } else {
5704                 /* it's an exe */
5705                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5706         }
5707
5708         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5709
5710         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5711         header->pe.pe_major = 6;
5712         header->pe.pe_minor = 0;
5713         size = assembly->sections [MONO_SECTION_TEXT].size;
5714         size += FILE_ALIGN - 1;
5715         size &= ~(FILE_ALIGN - 1);
5716         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5717         size = assembly->sections [MONO_SECTION_RSRC].size;
5718         size += FILE_ALIGN - 1;
5719         size &= ~(FILE_ALIGN - 1);
5720         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5721         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5722         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5723         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5724         /* pe_rva_entry_point always at the beginning of the text section */
5725         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5726
5727         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5728         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5729         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5730         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5731         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5732         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5733         size = section_start;
5734         size += FILE_ALIGN - 1;
5735         size &= ~(FILE_ALIGN - 1);
5736         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5737         size = image_size;
5738         size += VIRT_ALIGN - 1;
5739         size &= ~(VIRT_ALIGN - 1);
5740         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5741
5742         /*
5743         // Translate the PEFileKind value to the value expected by the Windows loader
5744         */
5745         {
5746                 short kind;
5747
5748                 /*
5749                 // PEFileKinds.Dll == 1
5750                 // PEFileKinds.ConsoleApplication == 2
5751                 // PEFileKinds.WindowApplication == 3
5752                 //
5753                 // need to get:
5754                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5755                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5756                 */
5757                 if (assemblyb->pekind == 3)
5758                         kind = 2;
5759                 else
5760                         kind = 3;
5761                 
5762                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5763         }    
5764         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5765         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5766         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5767         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5768         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5769         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5770
5771         /* fill data directory entries */
5772
5773         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5774         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5775
5776         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5777         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5778
5779         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5780         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5781         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5782         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5783         /* patch entrypoint name */
5784         if (assemblyb->pekind == 1)
5785                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5786         else
5787                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5788         /* patch imported function RVA name */
5789         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5790         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5791
5792         /* the import table */
5793         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5794         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5795         /* patch imported dll RVA name and other entries in the dir */
5796         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5797         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5798         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5799         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5800         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5801         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5802
5803         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5804         value = (assembly->text_rva + assembly->imp_names_offset);
5805         *p++ = (value) & 0xff;
5806         *p++ = (value >> 8) & (0xff);
5807         *p++ = (value >> 16) & (0xff);
5808         *p++ = (value >> 24) & (0xff);
5809
5810         /* the CLI header info */
5811         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5812         cli_header->ch_size = GUINT32_FROM_LE (72);
5813         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5814         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5815         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5816         if (assemblyb->entry_point) {
5817                 guint32 table_idx = 0;
5818                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5819                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5820                         table_idx = methodb->table_idx;
5821                 } else {
5822                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5823                 }
5824                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5825         } else {
5826                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5827         }
5828         /* The embedded managed resources */
5829         text_offset = assembly->text_rva + assembly->code.index;
5830         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5831         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5832         text_offset += assembly->resources.index;
5833         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5834         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5835         text_offset += assembly->meta_size;
5836         if (assembly->strong_name_size) {
5837                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5838                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5839                 text_offset += assembly->strong_name_size;
5840         }
5841
5842         /* write the section tables and section content */
5843         section = (MonoSectionTable*)(pefile->data + section_start);
5844         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5845                 static const char section_names [][7] = {
5846                         ".text", ".rsrc", ".reloc"
5847                 };
5848                 if (!assembly->sections [i].size)
5849                         continue;
5850                 strcpy (section->st_name, section_names [i]);
5851                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5852                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5853                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5854                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5855                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5856                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5857                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5858                 section ++;
5859         }
5860         
5861         checked_write_file (file, pefile->data, pefile->index);
5862         
5863         mono_dynamic_stream_reset (pefile);
5864         
5865         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5866                 if (!assembly->sections [i].size)
5867                         continue;
5868                 
5869                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5870                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5871                 
5872                 switch (i) {
5873                 case MONO_SECTION_TEXT:
5874                         /* patch entry point */
5875                         p = (guchar*)(assembly->code.data + 2);
5876                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5877                         *p++ = (value) & 0xff;
5878                         *p++ = (value >> 8) & 0xff;
5879                         *p++ = (value >> 16) & 0xff;
5880                         *p++ = (value >> 24) & 0xff;
5881                 
5882                         checked_write_file (file, assembly->code.data, assembly->code.index);
5883                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5884                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5885                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5886                                 
5887
5888                         g_free (assembly->image.raw_metadata);
5889                         break;
5890                 case MONO_SECTION_RELOC: {
5891                         struct {
5892                                 guint32 page_rva;
5893                                 guint32 block_size;
5894                                 guint16 type_and_offset;
5895                                 guint16 term;
5896                         } reloc;
5897                         
5898                         g_assert (sizeof (reloc) == 12);
5899                         
5900                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5901                         reloc.block_size = GUINT32_FROM_LE (12);
5902                         
5903                         /* 
5904                          * the entrypoint is always at the start of the text section 
5905                          * 3 is IMAGE_REL_BASED_HIGHLOW
5906                          * 2 is patch_size_rva - text_rva
5907                          */
5908                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5909                         reloc.term = 0;
5910                         
5911                         checked_write_file (file, &reloc, sizeof (reloc));
5912                         
5913                         break;
5914                 }
5915                 case MONO_SECTION_RSRC:
5916                         if (assembly->win32_res) {
5917
5918                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5919                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5920                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5921                         }
5922                         break;
5923                 default:
5924                         g_assert_not_reached ();
5925                 }
5926         }
5927         
5928         /* check that the file is properly padded */
5929         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5930                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5931         if (! SetEndOfFile (file))
5932                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5933         
5934         mono_dynamic_stream_reset (&assembly->code);
5935         mono_dynamic_stream_reset (&assembly->us);
5936         mono_dynamic_stream_reset (&assembly->blob);
5937         mono_dynamic_stream_reset (&assembly->guid);
5938         mono_dynamic_stream_reset (&assembly->sheap);
5939
5940         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5941         g_hash_table_destroy (assembly->blob_cache);
5942         assembly->blob_cache = NULL;
5943 }
5944
5945 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5946
5947 void
5948 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5949 {
5950         g_assert_not_reached ();
5951 }
5952
5953 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5954
5955 #ifndef DISABLE_REFLECTION_EMIT
5956
5957 MonoReflectionModule *
5958 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5959 {
5960         char *name;
5961         MonoImage *image;
5962         MonoImageOpenStatus status;
5963         MonoDynamicAssembly *assembly;
5964         guint32 module_count;
5965         MonoImage **new_modules;
5966         gboolean *new_modules_loaded;
5967         
5968         name = mono_string_to_utf8 (fileName);
5969
5970         image = mono_image_open (name, &status);
5971         if (!image) {
5972                 MonoException *exc;
5973                 if (status == MONO_IMAGE_ERROR_ERRNO)
5974                         exc = mono_get_exception_file_not_found (fileName);
5975                 else
5976                         exc = mono_get_exception_bad_image_format (name);
5977                 g_free (name);
5978                 mono_raise_exception (exc);
5979         }
5980
5981         g_free (name);
5982
5983         assembly = ab->dynamic_assembly;
5984         image->assembly = (MonoAssembly*)assembly;
5985
5986         module_count = image->assembly->image->module_count;
5987         new_modules = g_new0 (MonoImage *, module_count + 1);
5988         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5989
5990         if (image->assembly->image->modules)
5991                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5992         if (image->assembly->image->modules_loaded)
5993                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5994         new_modules [module_count] = image;
5995         new_modules_loaded [module_count] = TRUE;
5996         mono_image_addref (image);
5997
5998         g_free (image->assembly->image->modules);
5999         image->assembly->image->modules = new_modules;
6000         image->assembly->image->modules_loaded = new_modules_loaded;
6001         image->assembly->image->module_count ++;
6002
6003         mono_assembly_load_references (image, &status);
6004         if (status) {
6005                 mono_image_close (image);
6006                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6007         }
6008
6009         return mono_module_get_object (mono_domain_get (), image);
6010 }
6011
6012 #endif /* DISABLE_REFLECTION_EMIT */
6013
6014 /*
6015  * We need to return always the same object for MethodInfo, FieldInfo etc..
6016  * but we need to consider the reflected type.
6017  * type uses a different hash, since it uses custom hash/equal functions.
6018  */
6019
6020 typedef struct {
6021         gpointer item;
6022         MonoClass *refclass;
6023 } ReflectedEntry;
6024
6025 static gboolean
6026 reflected_equal (gconstpointer a, gconstpointer b) {
6027         const ReflectedEntry *ea = a;
6028         const ReflectedEntry *eb = b;
6029
6030         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6031 }
6032
6033 static guint
6034 reflected_hash (gconstpointer a) {
6035         const ReflectedEntry *ea = a;
6036         return mono_aligned_addr_hash (ea->item);
6037 }
6038
6039 #define CHECK_OBJECT(t,p,k)     \
6040         do {    \
6041                 t _obj; \
6042                 ReflectedEntry e;       \
6043                 e.item = (p);   \
6044                 e.refclass = (k);       \
6045                 mono_domain_lock (domain);      \
6046                 if (!domain->refobject_hash)    \
6047                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6048                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6049                         mono_domain_unlock (domain);    \
6050                         return _obj;    \
6051                 }       \
6052         mono_domain_unlock (domain); \
6053         } while (0)
6054
6055 #ifdef HAVE_BOEHM_GC
6056 /* ReflectedEntry doesn't need to be GC tracked */
6057 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6058 #define FREE_REFENTRY(entry) g_free ((entry))
6059 #define REFENTRY_REQUIRES_CLEANUP
6060 #else
6061 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6062 /* FIXME: */
6063 #define FREE_REFENTRY(entry)
6064 #endif
6065
6066 #define CACHE_OBJECT(t,p,o,k)   \
6067         do {    \
6068                 t _obj; \
6069         ReflectedEntry pe; \
6070         pe.item = (p); \
6071         pe.refclass = (k); \
6072         mono_domain_lock (domain); \
6073                 if (!domain->refobject_hash)    \
6074                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6075         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6076         if (!_obj) { \
6077                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6078                     e->item = (p);      \
6079                     e->refclass = (k);  \
6080                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6081             _obj = o; \
6082         } \
6083                 mono_domain_unlock (domain);    \
6084         return _obj; \
6085         } while (0)
6086
6087 static void
6088 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6089 {
6090         mono_domain_lock (domain);
6091         if (domain->refobject_hash) {
6092         ReflectedEntry pe;
6093                 gpointer orig_pe, orig_value;
6094
6095                 pe.item = o;
6096                 pe.refclass = klass;
6097                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6098                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6099                         FREE_REFENTRY (orig_pe);
6100                 }
6101         }
6102         mono_domain_unlock (domain);
6103 }
6104
6105 #ifdef REFENTRY_REQUIRES_CLEANUP
6106 static void
6107 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6108 {
6109         FREE_REFENTRY (key);
6110 }
6111 #endif
6112
6113 void
6114 mono_reflection_cleanup_domain (MonoDomain *domain)
6115 {
6116         if (domain->refobject_hash) {
6117 /*let's avoid scanning the whole hashtable if not needed*/
6118 #ifdef REFENTRY_REQUIRES_CLEANUP
6119                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6120 #endif
6121                 mono_g_hash_table_destroy (domain->refobject_hash);
6122                 domain->refobject_hash = NULL;
6123         }
6124 }
6125
6126 #ifndef DISABLE_REFLECTION_EMIT
6127 static gpointer
6128 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6129 {
6130         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6131 }
6132
6133 static gpointer
6134 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6135 {
6136         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6137 }
6138
6139 void
6140 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6141 {
6142         MonoDynamicImage *image = moduleb->dynamic_image;
6143         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6144         if (!image) {
6145                 MonoError error;
6146                 int module_count;
6147                 MonoImage **new_modules;
6148                 MonoImage *ass;
6149                 char *name, *fqname;
6150                 /*
6151                  * FIXME: we already created an image in mono_image_basic_init (), but
6152                  * we don't know which module it belongs to, since that is only 
6153                  * determined at assembly save time.
6154                  */
6155                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6156                 name = mono_string_to_utf8 (ab->name);
6157                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6158                 if (!mono_error_ok (&error)) {
6159                         g_free (name);
6160                         mono_error_raise_exception (&error);
6161                 }
6162                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6163
6164                 moduleb->module.image = &image->image;
6165                 moduleb->dynamic_image = image;
6166                 register_module (mono_object_domain (moduleb), moduleb, image);
6167
6168                 /* register the module with the assembly */
6169                 ass = ab->dynamic_assembly->assembly.image;
6170                 module_count = ass->module_count;
6171                 new_modules = g_new0 (MonoImage *, module_count + 1);
6172
6173                 if (ass->modules)
6174                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6175                 new_modules [module_count] = &image->image;
6176                 mono_image_addref (&image->image);
6177
6178                 g_free (ass->modules);
6179                 ass->modules = new_modules;
6180                 ass->module_count ++;
6181         }
6182 }
6183
6184 void
6185 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6186 {
6187         MonoDynamicImage *image = moduleb->dynamic_image;
6188
6189         g_assert (type->type);
6190         image->wrappers_type = mono_class_from_mono_type (type->type);
6191 }
6192
6193 #endif
6194
6195 /*
6196  * mono_assembly_get_object:
6197  * @domain: an app domain
6198  * @assembly: an assembly
6199  *
6200  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6201  */
6202 MonoReflectionAssembly*
6203 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6204 {
6205         static MonoClass *assembly_type;
6206         MonoReflectionAssembly *res;
6207         
6208         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6209         if (!assembly_type) {
6210                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6211                 if (class == NULL)
6212                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6213                 g_assert (class);
6214                 assembly_type = class;
6215         }
6216         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6217         res->assembly = assembly;
6218
6219         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6220 }
6221
6222
6223
6224 MonoReflectionModule*   
6225 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6226 {
6227         static MonoClass *module_type;
6228         MonoReflectionModule *res;
6229         char* basename;
6230         
6231         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6232         if (!module_type) {
6233                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6234                 if (class == NULL)
6235                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6236                 g_assert (class);
6237                 module_type = class;
6238         }
6239         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6240
6241         res->image = image;
6242         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6243
6244         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6245         basename = g_path_get_basename (image->name);
6246         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6247         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6248         
6249         g_free (basename);
6250
6251         if (image->assembly->image == image) {
6252                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6253         } else {
6254                 int i;
6255                 res->token = 0;
6256                 if (image->assembly->image->modules) {
6257                         for (i = 0; i < image->assembly->image->module_count; i++) {
6258                                 if (image->assembly->image->modules [i] == image)
6259                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6260                         }
6261                         g_assert (res->token);
6262                 }
6263         }
6264
6265         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6266 }
6267
6268 MonoReflectionModule*   
6269 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6270 {
6271         static MonoClass *module_type;
6272         MonoReflectionModule *res;
6273         MonoTableInfo *table;
6274         guint32 cols [MONO_FILE_SIZE];
6275         const char *name;
6276         guint32 i, name_idx;
6277         const char *val;
6278         
6279         if (!module_type) {
6280                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6281                 if (class == NULL)
6282                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6283                 g_assert (class);
6284                 module_type = class;
6285         }
6286         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6287
6288         table = &image->tables [MONO_TABLE_FILE];
6289         g_assert (table_index < table->rows);
6290         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6291
6292         res->image = NULL;
6293         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6294         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6295
6296         /* Check whenever the row has a corresponding row in the moduleref table */
6297         table = &image->tables [MONO_TABLE_MODULEREF];
6298         for (i = 0; i < table->rows; ++i) {
6299                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6300                 val = mono_metadata_string_heap (image, name_idx);
6301                 if (strcmp (val, name) == 0)
6302                         res->image = image->modules [i];
6303         }
6304
6305         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6306         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6307         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6308         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6309         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6310
6311         return res;
6312 }
6313
6314 static gboolean
6315 verify_safe_for_managed_space (MonoType *type)
6316 {
6317         switch (type->type) {
6318 #ifdef DEBUG_HARDER
6319         case MONO_TYPE_ARRAY:
6320                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6321         case MONO_TYPE_PTR:
6322                 return verify_safe_for_managed_space (type->data.type);
6323         case MONO_TYPE_SZARRAY:
6324                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6325         case MONO_TYPE_GENERICINST: {
6326                 MonoGenericInst *inst = type->data.generic_class->inst;
6327                 int i;
6328                 if (!inst->is_open)
6329                         break;
6330                 for (i = 0; i < inst->type_argc; ++i)
6331                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6332                                 return FALSE;
6333                 break;
6334         }
6335 #endif
6336         case MONO_TYPE_VAR:
6337         case MONO_TYPE_MVAR:
6338                 return TRUE;
6339         }
6340         return TRUE;
6341 }
6342
6343 static MonoType*
6344 mono_type_normalize (MonoType *type)
6345 {
6346         int i;
6347         MonoGenericClass *gclass;
6348         MonoGenericInst *ginst;
6349         MonoClass *gtd;
6350         MonoGenericContainer *gcontainer;
6351         MonoType **argv = NULL;
6352         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6353
6354         if (type->type != MONO_TYPE_GENERICINST)
6355                 return type;
6356
6357         gclass = type->data.generic_class;
6358         ginst = gclass->context.class_inst;
6359         if (!ginst->is_open)
6360                 return type;
6361
6362         gtd = gclass->container_class;
6363         gcontainer = gtd->generic_container;
6364         argv = g_newa (MonoType*, ginst->type_argc);
6365
6366         for (i = 0; i < ginst->type_argc; ++i) {
6367                 MonoType *t = ginst->type_argv [i], *norm;
6368                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6369                         is_denorm_gtd = FALSE;
6370                 norm = mono_type_normalize (t);
6371                 argv [i] = norm;
6372                 if (norm != t)
6373                         requires_rebind = TRUE;
6374         }
6375
6376         if (is_denorm_gtd)
6377                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6378
6379         if (requires_rebind) {
6380                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6381                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6382         }
6383
6384         return type;
6385 }
6386 /*
6387  * mono_type_get_object:
6388  * @domain: an app domain
6389  * @type: a type
6390  *
6391  * Return an System.MonoType object representing the type @type.
6392  */
6393 MonoReflectionType*
6394 mono_type_get_object (MonoDomain *domain, MonoType *type)
6395 {
6396         MonoType *norm_type;
6397         MonoReflectionType *res;
6398         MonoClass *klass = mono_class_from_mono_type (type);
6399
6400         /*we must avoid using @type as it might have come
6401          * from a mono_metadata_type_dup and the caller
6402          * expects that is can be freed.
6403          * Using the right type from 
6404          */
6405         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6406
6407         /* void is very common */
6408         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6409                 return (MonoReflectionType*)domain->typeof_void;
6410
6411         /*
6412          * If the vtable of the given class was already created, we can use
6413          * the MonoType from there and avoid all locking and hash table lookups.
6414          * 
6415          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6416          * that the resulting object is different.   
6417          */
6418         if (type == &klass->byval_arg && !klass->image->dynamic) {
6419                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6420                 if (vtable && vtable->type)
6421                         return vtable->type;
6422         }
6423
6424         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6425         mono_domain_lock (domain);
6426         if (!domain->type_hash)
6427                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6428                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6429         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6430                 mono_domain_unlock (domain);
6431                 mono_loader_unlock ();
6432                 return res;
6433         }
6434
6435         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6436          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6437          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6438          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6439          * artifact of how generics are encoded and should be transparent to managed code so we
6440          * need to weed out this diference when retrieving managed System.Type objects.
6441          */
6442         norm_type = mono_type_normalize (type);
6443         if (norm_type != type) {
6444                 res = mono_type_get_object (domain, norm_type);
6445                 mono_g_hash_table_insert (domain->type_hash, type, res);
6446                 mono_domain_unlock (domain);
6447                 mono_loader_unlock ();
6448                 return res;
6449         }
6450
6451         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6452         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6453                 g_assert (0);
6454
6455         if (!verify_safe_for_managed_space (type)) {
6456                 mono_domain_unlock (domain);
6457                 mono_loader_unlock ();
6458                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6459         }
6460
6461         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6462                 gboolean is_type_done = TRUE;
6463                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6464                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6465                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6466                 */
6467                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6468                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6469
6470                         if (gparam->owner && gparam->owner->is_method) {
6471                                 MonoMethod *method = gparam->owner->owner.method;
6472                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6473                                         is_type_done = FALSE;
6474                         } else if (gparam->owner && !gparam->owner->is_method) {
6475                                 MonoClass *klass = gparam->owner->owner.klass;
6476                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6477                                         is_type_done = FALSE;
6478                         }
6479                 } 
6480
6481                 /* g_assert_not_reached (); */
6482                 /* should this be considered an error condition? */
6483                 if (is_type_done && !type->byref) {
6484                         mono_domain_unlock (domain);
6485                         mono_loader_unlock ();
6486                         return mono_class_get_ref_info (klass);
6487                 }
6488         }
6489         /* This is stored in vtables/JITted code so it has to be pinned */
6490         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6491         res->type = type;
6492         mono_g_hash_table_insert (domain->type_hash, type, res);
6493
6494         if (type->type == MONO_TYPE_VOID)
6495                 domain->typeof_void = (MonoObject*)res;
6496
6497         mono_domain_unlock (domain);
6498         mono_loader_unlock ();
6499         return res;
6500 }
6501
6502 /*
6503  * mono_method_get_object:
6504  * @domain: an app domain
6505  * @method: a method
6506  * @refclass: the reflected type (can be NULL)
6507  *
6508  * Return an System.Reflection.MonoMethod object representing the method @method.
6509  */
6510 MonoReflectionMethod*
6511 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6512 {
6513         /*
6514          * We use the same C representation for methods and constructors, but the type 
6515          * name in C# is different.
6516          */
6517         static MonoClass *System_Reflection_MonoMethod = NULL;
6518         static MonoClass *System_Reflection_MonoCMethod = NULL;
6519         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6520         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6521         MonoClass *klass;
6522         MonoReflectionMethod *ret;
6523
6524         if (method->is_inflated) {
6525                 MonoReflectionGenericMethod *gret;
6526
6527                 refclass = method->klass;
6528                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6529                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6530                         if (!System_Reflection_MonoGenericCMethod)
6531                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6532                         klass = System_Reflection_MonoGenericCMethod;
6533                 } else {
6534                         if (!System_Reflection_MonoGenericMethod)
6535                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6536                         klass = System_Reflection_MonoGenericMethod;
6537                 }
6538                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6539                 gret->method.method = method;
6540                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6541                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6542                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6543         }
6544
6545         if (!refclass)
6546                 refclass = method->klass;
6547
6548         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6549         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6550                 if (!System_Reflection_MonoCMethod)
6551                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6552                 klass = System_Reflection_MonoCMethod;
6553         }
6554         else {
6555                 if (!System_Reflection_MonoMethod)
6556                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6557                 klass = System_Reflection_MonoMethod;
6558         }
6559         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6560         ret->method = method;
6561         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6562         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6563 }
6564
6565 /*
6566  * mono_method_clear_object:
6567  *
6568  *   Clear the cached reflection objects for the dynamic method METHOD.
6569  */
6570 void
6571 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6572 {
6573         MonoClass *klass;
6574         g_assert (method->dynamic);
6575
6576         klass = method->klass;
6577         while (klass) {
6578                 clear_cached_object (domain, method, klass);
6579                 klass = klass->parent;
6580         }
6581         /* Added by mono_param_get_objects () */
6582         clear_cached_object (domain, &(method->signature), NULL);
6583         klass = method->klass;
6584         while (klass) {
6585                 clear_cached_object (domain, &(method->signature), klass);
6586                 klass = klass->parent;
6587         }
6588 }
6589
6590 /*
6591  * mono_field_get_object:
6592  * @domain: an app domain
6593  * @klass: a type
6594  * @field: a field
6595  *
6596  * Return an System.Reflection.MonoField object representing the field @field
6597  * in class @klass.
6598  */
6599 MonoReflectionField*
6600 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6601 {
6602         MonoReflectionField *res;
6603         static MonoClass *monofield_klass;
6604
6605         CHECK_OBJECT (MonoReflectionField *, field, klass);
6606         if (!monofield_klass)
6607                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6608         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6609         res->klass = klass;
6610         res->field = field;
6611         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6612
6613         if (is_field_on_inst (field)) {
6614                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6615                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6616         } else {
6617                 if (field->type)
6618                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6619                 res->attrs = mono_field_get_flags (field);
6620         }
6621         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6622 }
6623
6624 /*
6625  * mono_property_get_object:
6626  * @domain: an app domain
6627  * @klass: a type
6628  * @property: a property
6629  *
6630  * Return an System.Reflection.MonoProperty object representing the property @property
6631  * in class @klass.
6632  */
6633 MonoReflectionProperty*
6634 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6635 {
6636         MonoReflectionProperty *res;
6637         static MonoClass *monoproperty_klass;
6638
6639         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6640         if (!monoproperty_klass)
6641                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6642         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6643         res->klass = klass;
6644         res->property = property;
6645         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6646 }
6647
6648 /*
6649  * mono_event_get_object:
6650  * @domain: an app domain
6651  * @klass: a type
6652  * @event: a event
6653  *
6654  * Return an System.Reflection.MonoEvent object representing the event @event
6655  * in class @klass.
6656  */
6657 MonoReflectionEvent*
6658 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6659 {
6660         MonoReflectionEvent *res;
6661         MonoReflectionMonoEvent *mono_event;
6662         static MonoClass *monoevent_klass;
6663
6664         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6665         if (!monoevent_klass)
6666                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6667         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6668         mono_event->klass = klass;
6669         mono_event->event = event;
6670         res = (MonoReflectionEvent*)mono_event;
6671         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6672 }
6673
6674 /**
6675  * mono_get_reflection_missing_object:
6676  * @domain: Domain where the object lives
6677  *
6678  * Returns the System.Reflection.Missing.Value singleton object
6679  * (of type System.Reflection.Missing).
6680  *
6681  * Used as the value for ParameterInfo.DefaultValue when Optional
6682  * is present
6683  */
6684 static MonoObject *
6685 mono_get_reflection_missing_object (MonoDomain *domain)
6686 {
6687         MonoObject *obj;
6688         static MonoClassField *missing_value_field = NULL;
6689         
6690         if (!missing_value_field) {
6691                 MonoClass *missing_klass;
6692                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6693                 mono_class_init (missing_klass);
6694                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6695                 g_assert (missing_value_field);
6696         }
6697         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6698         g_assert (obj);
6699         return obj;
6700 }
6701
6702 static MonoObject*
6703 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6704 {
6705         if (!*dbnull)
6706                 *dbnull = mono_get_dbnull_object (domain);
6707         return *dbnull;
6708 }
6709
6710 static MonoObject*
6711 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6712 {
6713         if (!*reflection_missing)
6714                 *reflection_missing = mono_get_reflection_missing_object (domain);
6715         return *reflection_missing;
6716 }
6717
6718 /*
6719  * mono_param_get_objects:
6720  * @domain: an app domain
6721  * @method: a method
6722  *
6723  * Return an System.Reflection.ParameterInfo array object representing the parameters
6724  * in the method @method.
6725  */
6726 MonoArray*
6727 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6728 {
6729         static MonoClass *System_Reflection_ParameterInfo;
6730         static MonoClass *System_Reflection_ParameterInfo_array;
6731         MonoError error;
6732         MonoArray *res = NULL;
6733         MonoReflectionMethod *member = NULL;
6734         MonoReflectionParameter *param = NULL;
6735         char **names, **blobs = NULL;
6736         guint32 *types = NULL;
6737         MonoType *type = NULL;
6738         MonoObject *dbnull = NULL;
6739         MonoObject *missing = NULL;
6740         MonoMarshalSpec **mspecs;
6741         MonoMethodSignature *sig;
6742         MonoVTable *pinfo_vtable;
6743         int i;
6744
6745         if (!System_Reflection_ParameterInfo_array) {
6746                 MonoClass *klass;
6747
6748                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6749                 mono_memory_barrier ();
6750                 System_Reflection_ParameterInfo = klass; 
6751         
6752                 klass = mono_array_class_get (klass, 1);
6753                 mono_memory_barrier ();
6754                 System_Reflection_ParameterInfo_array = klass;
6755         }
6756
6757         sig = mono_method_signature_checked (method, &error);
6758         if (!mono_error_ok (&error))
6759                 mono_error_raise_exception (&error);
6760
6761         if (!sig->param_count)
6762                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6763
6764         /* Note: the cache is based on the address of the signature into the method
6765          * since we already cache MethodInfos with the method as keys.
6766          */
6767         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6768
6769         member = mono_method_get_object (domain, method, refclass);
6770         names = g_new (char *, sig->param_count);
6771         mono_method_get_param_names (method, (const char **) names);
6772
6773         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6774         mono_method_get_marshal_info (method, mspecs);
6775
6776         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6777         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6778         for (i = 0; i < sig->param_count; ++i) {
6779                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6780                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6781                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6782                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6783                 param->PositionImpl = i;
6784                 param->AttrsImpl = sig->params [i]->attrs;
6785
6786                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6787                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6788                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6789                         else
6790                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6791                 } else {
6792
6793                         if (!blobs) {
6794                                 blobs = g_new0 (char *, sig->param_count);
6795                                 types = g_new0 (guint32, sig->param_count);
6796                                 get_default_param_value_blobs (method, blobs, types); 
6797                         }
6798
6799                         /* Build MonoType for the type from the Constant Table */
6800                         if (!type)
6801                                 type = g_new0 (MonoType, 1);
6802                         type->type = types [i];
6803                         type->data.klass = NULL;
6804                         if (types [i] == MONO_TYPE_CLASS)
6805                                 type->data.klass = mono_defaults.object_class;
6806                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6807                                 /* For enums, types [i] contains the base type */
6808
6809                                         type->type = MONO_TYPE_VALUETYPE;
6810                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6811                         } else
6812                                 type->data.klass = mono_class_from_mono_type (type);
6813
6814                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6815
6816                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6817                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6818                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6819                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6820                                 else
6821                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6822                         }
6823                         
6824                 }
6825
6826                 if (mspecs [i + 1])
6827                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6828                 
6829                 mono_array_setref (res, i, param);
6830         }
6831         g_free (names);
6832         g_free (blobs);
6833         g_free (types);
6834         g_free (type);
6835
6836         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6837                 if (mspecs [i])
6838                         mono_metadata_free_marshal_spec (mspecs [i]);
6839         g_free (mspecs);
6840         
6841         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6842 }
6843
6844 MonoArray*
6845 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6846 {
6847         return mono_param_get_objects_internal (domain, method, NULL);
6848 }
6849
6850 /*
6851  * mono_method_body_get_object:
6852  * @domain: an app domain
6853  * @method: a method
6854  *
6855  * Return an System.Reflection.MethodBody object representing the method @method.
6856  */
6857 MonoReflectionMethodBody*
6858 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6859 {
6860         static MonoClass *System_Reflection_MethodBody = NULL;
6861         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6862         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6863         MonoReflectionMethodBody *ret;
6864         MonoMethodHeader *header;
6865         MonoImage *image;
6866         guint32 method_rva, local_var_sig_token;
6867     char *ptr;
6868         unsigned char format, flags;
6869         int i;
6870
6871         /* for compatibility with .net */
6872     if (method->dynamic)
6873         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6874
6875         if (!System_Reflection_MethodBody)
6876                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6877         if (!System_Reflection_LocalVariableInfo)
6878                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6879         if (!System_Reflection_ExceptionHandlingClause)
6880                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6881
6882         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6883
6884         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6885                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6886             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6887             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6888                 return NULL;
6889
6890         image = method->klass->image;
6891         header = mono_method_get_header (method);
6892
6893         if (!image->dynamic) {
6894                 /* Obtain local vars signature token */
6895                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6896                 ptr = mono_image_rva_map (image, method_rva);
6897                 flags = *(const unsigned char *) ptr;
6898                 format = flags & METHOD_HEADER_FORMAT_MASK;
6899                 switch (format){
6900                 case METHOD_HEADER_TINY_FORMAT:
6901                         local_var_sig_token = 0;
6902                         break;
6903                 case METHOD_HEADER_FAT_FORMAT:
6904                         ptr += 2;
6905                         ptr += 2;
6906                         ptr += 4;
6907                         local_var_sig_token = read32 (ptr);
6908                         break;
6909                 default:
6910                         g_assert_not_reached ();
6911                 }
6912         } else
6913                 local_var_sig_token = 0; //FIXME
6914
6915         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6916
6917         ret->init_locals = header->init_locals;
6918         ret->max_stack = header->max_stack;
6919         ret->local_var_sig_token = local_var_sig_token;
6920         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6921         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6922
6923         /* Locals */
6924         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6925         for (i = 0; i < header->num_locals; ++i) {
6926                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6927                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6928                 info->is_pinned = header->locals [i]->pinned;
6929                 info->local_index = i;
6930                 mono_array_setref (ret->locals, i, info);
6931         }
6932
6933         /* Exceptions */
6934         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6935         for (i = 0; i < header->num_clauses; ++i) {
6936                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6937                 MonoExceptionClause *clause = &header->clauses [i];
6938
6939                 info->flags = clause->flags;
6940                 info->try_offset = clause->try_offset;
6941                 info->try_length = clause->try_len;
6942                 info->handler_offset = clause->handler_offset;
6943                 info->handler_length = clause->handler_len;
6944                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6945                         info->filter_offset = clause->data.filter_offset;
6946                 else if (clause->data.catch_class)
6947                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6948
6949                 mono_array_setref (ret->clauses, i, info);
6950         }
6951
6952         mono_metadata_free_mh (header);
6953         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6954         return ret;
6955 }
6956
6957 /**
6958  * mono_get_dbnull_object:
6959  * @domain: Domain where the object lives
6960  *
6961  * Returns the System.DBNull.Value singleton object
6962  *
6963  * Used as the value for ParameterInfo.DefaultValue 
6964  */
6965 MonoObject *
6966 mono_get_dbnull_object (MonoDomain *domain)
6967 {
6968         MonoObject *obj;
6969         static MonoClassField *dbnull_value_field = NULL;
6970         
6971         if (!dbnull_value_field) {
6972                 MonoClass *dbnull_klass;
6973                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6974                 mono_class_init (dbnull_klass);
6975                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6976                 g_assert (dbnull_value_field);
6977         }
6978         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6979         g_assert (obj);
6980         return obj;
6981 }
6982
6983 static void
6984 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6985 {
6986         guint32 param_index, i, lastp, crow = 0;
6987         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6988         gint32 idx;
6989
6990         MonoClass *klass = method->klass;
6991         MonoImage *image = klass->image;
6992         MonoMethodSignature *methodsig = mono_method_signature (method);
6993
6994         MonoTableInfo *constt;
6995         MonoTableInfo *methodt;
6996         MonoTableInfo *paramt;
6997
6998         if (!methodsig->param_count)
6999                 return;
7000
7001         mono_class_init (klass);
7002
7003         if (klass->image->dynamic) {
7004                 MonoReflectionMethodAux *aux;
7005                 if (method->is_inflated)
7006                         method = ((MonoMethodInflated*)method)->declaring;
7007                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7008                 if (aux && aux->param_defaults) {
7009                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7010                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7011                 }
7012                 return;
7013         }
7014
7015         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7016         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7017         constt = &image->tables [MONO_TABLE_CONSTANT];
7018
7019         idx = mono_method_get_index (method) - 1;
7020         g_assert (idx != -1);
7021
7022         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7023         if (idx + 1 < methodt->rows)
7024                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7025         else
7026                 lastp = paramt->rows + 1;
7027
7028         for (i = param_index; i < lastp; ++i) {
7029                 guint32 paramseq;
7030
7031                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7032                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7033
7034                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7035                         continue;
7036
7037                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7038                 if (!crow) {
7039                         continue;
7040                 }
7041         
7042                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7043                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7044                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7045         }
7046
7047         return;
7048 }
7049
7050 MonoObject *
7051 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7052 {
7053         void *retval;
7054         MonoClass *klass;
7055         MonoObject *object;
7056         MonoType *basetype = type;
7057
7058         if (!blob)
7059                 return NULL;
7060         
7061         klass = mono_class_from_mono_type (type);
7062         if (klass->valuetype) {
7063                 object = mono_object_new (domain, klass);
7064                 retval = ((gchar *) object + sizeof (MonoObject));
7065                 if (klass->enumtype)
7066                         basetype = mono_class_enum_basetype (klass);
7067         } else {
7068                 retval = &object;
7069         }
7070                         
7071         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7072                 return object;
7073         else
7074                 return NULL;
7075 }
7076
7077 static int
7078 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7079         int found_sep;
7080         char *s;
7081         gboolean quoted = FALSE;
7082
7083         memset (assembly, 0, sizeof (MonoAssemblyName));
7084         assembly->culture = "";
7085         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7086
7087         if (*p == '"') {
7088                 quoted = TRUE;
7089                 p++;
7090         }
7091         assembly->name = p;
7092         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7093                 p++;
7094         if (quoted) {
7095                 if (*p != '"')
7096                         return 1;
7097                 *p = 0;
7098                 p++;
7099         }
7100         if (*p != ',')
7101                 return 1;
7102         *p = 0;
7103         /* Remove trailing whitespace */
7104         s = p - 1;
7105         while (*s && g_ascii_isspace (*s))
7106                 *s-- = 0;
7107         p ++;
7108         while (g_ascii_isspace (*p))
7109                 p++;
7110         while (*p) {
7111                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7112                         p += 8;
7113                         assembly->major = strtoul (p, &s, 10);
7114                         if (s == p || *s != '.')
7115                                 return 1;
7116                         p = ++s;
7117                         assembly->minor = strtoul (p, &s, 10);
7118                         if (s == p || *s != '.')
7119                                 return 1;
7120                         p = ++s;
7121                         assembly->build = strtoul (p, &s, 10);
7122                         if (s == p || *s != '.')
7123                                 return 1;
7124                         p = ++s;
7125                         assembly->revision = strtoul (p, &s, 10);
7126                         if (s == p)
7127                                 return 1;
7128                         p = s;
7129                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7130                         p += 8;
7131                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7132                                 assembly->culture = "";
7133                                 p += 7;
7134                         } else {
7135                                 assembly->culture = p;
7136                                 while (*p && *p != ',') {
7137                                         p++;
7138                                 }
7139                         }
7140                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7141                         p += 15;
7142                         if (strncmp (p, "null", 4) == 0) {
7143                                 p += 4;
7144                         } else {
7145                                 int len;
7146                                 gchar *start = p;
7147                                 while (*p && *p != ',') {
7148                                         p++;
7149                                 }
7150                                 len = (p - start + 1);
7151                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7152                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7153                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7154                         }
7155                 } else {
7156                         while (*p && *p != ',')
7157                                 p++;
7158                 }
7159                 found_sep = 0;
7160                 while (g_ascii_isspace (*p) || *p == ',') {
7161                         *p++ = 0;
7162                         found_sep = 1;
7163                         continue;
7164                 }
7165                 /* failed */
7166                 if (!found_sep)
7167                         return 1;
7168         }
7169
7170         return 0;
7171 }
7172
7173 /*
7174  * mono_reflection_parse_type:
7175  * @name: type name
7176  *
7177  * Parse a type name as accepted by the GetType () method and output the info
7178  * extracted in the info structure.
7179  * the name param will be mangled, so, make a copy before passing it to this function.
7180  * The fields in info will be valid until the memory pointed to by name is valid.
7181  *
7182  * See also mono_type_get_name () below.
7183  *
7184  * Returns: 0 on parse error.
7185  */
7186 static int
7187 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7188                              MonoTypeNameParse *info)
7189 {
7190         char *start, *p, *w, *temp, *last_point, *startn;
7191         int in_modifiers = 0;
7192         int isbyref = 0, rank, arity = 0, i;
7193
7194         start = p = w = name;
7195
7196         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7197         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7198         info->name = info->name_space = NULL;
7199         info->nested = NULL;
7200         info->modifiers = NULL;
7201         info->type_arguments = NULL;
7202
7203         /* last_point separates the namespace from the name */
7204         last_point = NULL;
7205         /* Skips spaces */
7206         while (*p == ' ') p++, start++, w++, name++;
7207
7208         while (*p) {
7209                 switch (*p) {
7210                 case '+':
7211                         *p = 0; /* NULL terminate the name */
7212                         startn = p + 1;
7213                         info->nested = g_list_append (info->nested, startn);
7214                         /* we have parsed the nesting namespace + name */
7215                         if (info->name)
7216                                 break;
7217                         if (last_point) {
7218                                 info->name_space = start;
7219                                 *last_point = 0;
7220                                 info->name = last_point + 1;
7221                         } else {
7222                                 info->name_space = (char *)"";
7223                                 info->name = start;
7224                         }
7225                         break;
7226                 case '.':
7227                         last_point = p;
7228                         break;
7229                 case '\\':
7230                         ++p;
7231                         break;
7232                 case '&':
7233                 case '*':
7234                 case '[':
7235                 case ',':
7236                 case ']':
7237                         in_modifiers = 1;
7238                         break;
7239                 case '`':
7240                         ++p;
7241                         i = strtol (p, &temp, 10);
7242                         arity += i;
7243                         if (p == temp)
7244                                 return 0;
7245                         p = temp-1;
7246                         break;
7247                 default:
7248                         break;
7249                 }
7250                 if (in_modifiers)
7251                         break;
7252                 // *w++ = *p++;
7253                 p++;
7254         }
7255         
7256         if (!info->name) {
7257                 if (last_point) {
7258                         info->name_space = start;
7259                         *last_point = 0;
7260                         info->name = last_point + 1;
7261                 } else {
7262                         info->name_space = (char *)"";
7263                         info->name = start;
7264                 }
7265         }
7266         while (*p) {
7267                 switch (*p) {
7268                 case '&':
7269                         if (isbyref) /* only one level allowed by the spec */
7270                                 return 0;
7271                         isbyref = 1;
7272                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7273                         *p++ = 0;
7274                         break;
7275                 case '*':
7276                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7277                         *p++ = 0;
7278                         break;
7279                 case '[':
7280                         if (arity != 0) {
7281                                 *p++ = 0;
7282                                 info->type_arguments = g_ptr_array_new ();
7283                                 for (i = 0; i < arity; i++) {
7284                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7285                                         gboolean fqname = FALSE;
7286
7287                                         g_ptr_array_add (info->type_arguments, subinfo);
7288
7289                                         if (*p == '[') {
7290                                                 p++;
7291                                                 fqname = TRUE;
7292                                         }
7293
7294                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7295                                                 return 0;
7296
7297                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7298                                         if (fqname && (*p != ']')) {
7299                                                 char *aname;
7300
7301                                                 if (*p != ',')
7302                                                         return 0;
7303                                                 *p++ = 0;
7304
7305                                                 aname = p;
7306                                                 while (*p && (*p != ']'))
7307                                                         p++;
7308
7309                                                 if (*p != ']')
7310                                                         return 0;
7311
7312                                                 *p++ = 0;
7313                                                 while (*aname) {
7314                                                         if (g_ascii_isspace (*aname)) {
7315                                                                 ++aname;
7316                                                                 continue;
7317                                                         }
7318                                                         break;
7319                                                 }
7320                                                 if (!*aname ||
7321                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7322                                                         return 0;
7323                                         } else if (fqname && (*p == ']')) {
7324                                                 *p++ = 0;
7325                                         }
7326
7327                                         if (i + 1 < arity) {
7328                                                 if (*p != ',')
7329                                                         return 0;
7330                                         } else {
7331                                                 if (*p != ']')
7332                                                         return 0;
7333                                         }
7334                                         *p++ = 0;
7335                                 }
7336
7337                                 arity = 0;
7338                                 break;
7339                         }
7340                         rank = 1;
7341                         *p++ = 0;
7342                         while (*p) {
7343                                 if (*p == ']')
7344                                         break;
7345                                 if (*p == ',')
7346                                         rank++;
7347                                 else if (*p == '*') /* '*' means unknown lower bound */
7348                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7349                                 else
7350                                         return 0;
7351                                 ++p;
7352                         }
7353                         if (*p++ != ']')
7354                                 return 0;
7355                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7356                         break;
7357                 case ']':
7358                         if (is_recursed)
7359                                 goto end;
7360                         return 0;
7361                 case ',':
7362                         if (is_recursed)
7363                                 goto end;
7364                         *p++ = 0;
7365                         while (*p) {
7366                                 if (g_ascii_isspace (*p)) {
7367                                         ++p;
7368                                         continue;
7369                                 }
7370                                 break;
7371                         }
7372                         if (!*p)
7373                                 return 0; /* missing assembly name */
7374                         if (!assembly_name_to_aname (&info->assembly, p))
7375                                 return 0;
7376                         break;
7377                 default:
7378                         return 0;
7379                 }
7380                 if (info->assembly.name)
7381                         break;
7382         }
7383         // *w = 0; /* terminate class name */
7384  end:
7385         if (!info->name || !*info->name)
7386                 return 0;
7387         if (endptr)
7388                 *endptr = p;
7389         /* add other consistency checks */
7390         return 1;
7391 }
7392
7393 int
7394 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7395 {
7396         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7397 }
7398
7399 static MonoType*
7400 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7401 {
7402         gboolean type_resolve = FALSE;
7403         MonoType *type;
7404         MonoImage *rootimage = image;
7405
7406         if (info->assembly.name) {
7407                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7408                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7409                         /* 
7410                          * This could happen in the AOT compiler case when the search hook is not
7411                          * installed.
7412                          */
7413                         assembly = image->assembly;
7414                 if (!assembly) {
7415                         /* then we must load the assembly ourselve - see #60439 */
7416                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7417                         if (!assembly)
7418                                 return NULL;
7419                 }
7420                 image = assembly->image;
7421         } else if (!image) {
7422                 image = mono_defaults.corlib;
7423         }
7424
7425         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7426         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7427                 image = mono_defaults.corlib;
7428                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7429         }
7430
7431         return type;
7432 }
7433
7434 static MonoType*
7435 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7436 {
7437         MonoClass *klass;
7438         GList *mod;
7439         int modval;
7440         gboolean bounded = FALSE;
7441         
7442         if (!image)
7443                 image = mono_defaults.corlib;
7444
7445         if (ignorecase)
7446                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7447         else
7448                 klass = mono_class_from_name (image, info->name_space, info->name);
7449         if (!klass)
7450                 return NULL;
7451         for (mod = info->nested; mod; mod = mod->next) {
7452                 gpointer iter = NULL;
7453                 MonoClass *parent;
7454
7455                 parent = klass;
7456                 mono_class_init (parent);
7457
7458                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7459                         if (ignorecase) {
7460                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7461                                         break;
7462                         } else {
7463                                 if (strcmp (klass->name, mod->data) == 0)
7464                                         break;
7465                         }
7466                 }
7467                 if (!klass)
7468                         break;
7469         }
7470         if (!klass)
7471                 return NULL;
7472
7473         if (info->type_arguments) {
7474                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7475                 MonoReflectionType *the_type;
7476                 MonoType *instance;
7477                 int i;
7478
7479                 for (i = 0; i < info->type_arguments->len; i++) {
7480                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7481
7482                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7483                         if (!type_args [i]) {
7484                                 g_free (type_args);
7485                                 return NULL;
7486                         }
7487                 }
7488
7489                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7490
7491                 instance = mono_reflection_bind_generic_parameters (
7492                         the_type, info->type_arguments->len, type_args);
7493
7494                 g_free (type_args);
7495                 if (!instance)
7496                         return NULL;
7497
7498                 klass = mono_class_from_mono_type (instance);
7499         }
7500
7501         for (mod = info->modifiers; mod; mod = mod->next) {
7502                 modval = GPOINTER_TO_UINT (mod->data);
7503                 if (!modval) { /* byref: must be last modifier */
7504                         return &klass->this_arg;
7505                 } else if (modval == -1) {
7506                         klass = mono_ptr_class_get (&klass->byval_arg);
7507                 } else if (modval == -2) {
7508                         bounded = TRUE;
7509                 } else { /* array rank */
7510                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7511                 }
7512         }
7513
7514         return &klass->byval_arg;
7515 }
7516
7517 /*
7518  * mono_reflection_get_type:
7519  * @image: a metadata context
7520  * @info: type description structure
7521  * @ignorecase: flag for case-insensitive string compares
7522  * @type_resolve: whenever type resolve was already tried
7523  *
7524  * Build a MonoType from the type description in @info.
7525  * 
7526  */
7527
7528 MonoType*
7529 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7530         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7531 }
7532
7533 static MonoType*
7534 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7535 {
7536         MonoReflectionAssemblyBuilder *abuilder;
7537         MonoType *type;
7538         int i;
7539
7540         g_assert (assembly->dynamic);
7541         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7542
7543         /* Enumerate all modules */
7544
7545         type = NULL;
7546         if (abuilder->modules) {
7547                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7548                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7549                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7550                         if (type)
7551                                 break;
7552                 }
7553         }
7554
7555         if (!type && abuilder->loaded_modules) {
7556                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7557                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7558                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7559                         if (type)
7560                                 break;
7561                 }
7562         }
7563
7564         return type;
7565 }
7566         
7567 MonoType*
7568 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7569 {
7570         MonoType *type;
7571         MonoReflectionAssembly *assembly;
7572         GString *fullName;
7573         GList *mod;
7574
7575         if (image && image->dynamic)
7576                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7577         else
7578                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7579         if (type)
7580                 return type;
7581         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7582                 return NULL;
7583
7584         if (type_resolve) {
7585                 if (*type_resolve) 
7586                         return NULL;
7587                 else
7588                         *type_resolve = TRUE;
7589         }
7590         
7591         /* Reconstruct the type name */
7592         fullName = g_string_new ("");
7593         if (info->name_space && (info->name_space [0] != '\0'))
7594                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7595         else
7596                 g_string_printf (fullName, "%s", info->name);
7597         for (mod = info->nested; mod; mod = mod->next)
7598                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7599
7600         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7601         if (assembly) {
7602                 if (assembly->assembly->dynamic)
7603                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7604                 else
7605                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7606                                                                                                           info, ignorecase);
7607         }
7608         g_string_free (fullName, TRUE);
7609         return type;
7610 }
7611
7612 void
7613 mono_reflection_free_type_info (MonoTypeNameParse *info)
7614 {
7615         g_list_free (info->modifiers);
7616         g_list_free (info->nested);
7617
7618         if (info->type_arguments) {
7619                 int i;
7620
7621                 for (i = 0; i < info->type_arguments->len; i++) {
7622                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7623
7624                         mono_reflection_free_type_info (subinfo);
7625                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7626                         g_free (subinfo);
7627                 }
7628
7629                 g_ptr_array_free (info->type_arguments, TRUE);
7630         }
7631 }
7632
7633 /*
7634  * mono_reflection_type_from_name:
7635  * @name: type name.
7636  * @image: a metadata context (can be NULL).
7637  *
7638  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7639  * it defaults to get the type from @image or, if @image is NULL or loading
7640  * from it fails, uses corlib.
7641  * 
7642  */
7643 MonoType*
7644 mono_reflection_type_from_name (char *name, MonoImage *image)
7645 {
7646         MonoType *type = NULL;
7647         MonoTypeNameParse info;
7648         char *tmp;
7649
7650         /* Make a copy since parse_type modifies its argument */
7651         tmp = g_strdup (name);
7652         
7653         /*g_print ("requested type %s\n", str);*/
7654         if (mono_reflection_parse_type (tmp, &info)) {
7655                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7656         }
7657
7658         g_free (tmp);
7659         mono_reflection_free_type_info (&info);
7660         return type;
7661 }
7662
7663 /*
7664  * mono_reflection_get_token:
7665  *
7666  *   Return the metadata token of OBJ which should be an object
7667  * representing a metadata element.
7668  */
7669 guint32
7670 mono_reflection_get_token (MonoObject *obj)
7671 {
7672         MonoClass *klass;
7673         guint32 token = 0;
7674
7675         klass = obj->vtable->klass;
7676
7677         if (strcmp (klass->name, "MethodBuilder") == 0) {
7678                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7679
7680                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7681         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7682                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7683
7684                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7685         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7686                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7687
7688                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7689         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7690                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7691                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7692         } else if (strcmp (klass->name, "MonoType") == 0) {
7693                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7694                 MonoClass *mc = mono_class_from_mono_type (type);
7695                 if (!mono_class_init (mc))
7696                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7697
7698                 token = mc->type_token;
7699         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7700                    strcmp (klass->name, "MonoMethod") == 0 ||
7701                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7702                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7703                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7704                 if (m->method->is_inflated) {
7705                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7706                         return inflated->declaring->token;
7707                 } else {
7708                         token = m->method->token;
7709                 }
7710         } else if (strcmp (klass->name, "MonoField") == 0) {
7711                 MonoReflectionField *f = (MonoReflectionField*)obj;
7712
7713                 if (is_field_on_inst (f->field)) {
7714                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7715                         int field_index = f->field - dgclass->fields;
7716                         MonoObject *obj;
7717
7718                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7719                         obj = dgclass->field_objects [field_index];
7720                         return mono_reflection_get_token (obj);
7721                 }
7722                 token = mono_class_get_field_token (f->field);
7723         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7724                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7725
7726                 token = mono_class_get_property_token (p->property);
7727         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7728                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7729
7730                 token = mono_class_get_event_token (p->event);
7731         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7732                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7733                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7734                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7735
7736                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7737         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7738                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7739
7740                 token = m->token;
7741         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7742                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7743         } else {
7744                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7745                 MonoException *ex = mono_get_exception_not_implemented (msg);
7746                 g_free (msg);
7747                 mono_raise_exception (ex);
7748         }
7749
7750         return token;
7751 }
7752
7753 static void*
7754 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7755 {
7756         int slen, type = t->type;
7757         MonoClass *tklass = t->data.klass;
7758
7759 handle_enum:
7760         switch (type) {
7761         case MONO_TYPE_U1:
7762         case MONO_TYPE_I1:
7763         case MONO_TYPE_BOOLEAN: {
7764                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7765                 *bval = *p;
7766                 *end = p + 1;
7767                 return bval;
7768         }
7769         case MONO_TYPE_CHAR:
7770         case MONO_TYPE_U2:
7771         case MONO_TYPE_I2: {
7772                 guint16 *val = g_malloc (sizeof (guint16));
7773                 *val = read16 (p);
7774                 *end = p + 2;
7775                 return val;
7776         }
7777 #if SIZEOF_VOID_P == 4
7778         case MONO_TYPE_U:
7779         case MONO_TYPE_I:
7780 #endif
7781         case MONO_TYPE_R4:
7782         case MONO_TYPE_U4:
7783         case MONO_TYPE_I4: {
7784                 guint32 *val = g_malloc (sizeof (guint32));
7785                 *val = read32 (p);
7786                 *end = p + 4;
7787                 return val;
7788         }
7789 #if SIZEOF_VOID_P == 8
7790         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7791         case MONO_TYPE_I:
7792 #endif
7793         case MONO_TYPE_U8:
7794         case MONO_TYPE_I8: {
7795                 guint64 *val = g_malloc (sizeof (guint64));
7796                 *val = read64 (p);
7797                 *end = p + 8;
7798                 return val;
7799         }
7800         case MONO_TYPE_R8: {
7801                 double *val = g_malloc (sizeof (double));
7802                 readr8 (p, val);
7803                 *end = p + 8;
7804                 return val;
7805         }
7806         case MONO_TYPE_VALUETYPE:
7807                 if (t->data.klass->enumtype) {
7808                         type = mono_class_enum_basetype (t->data.klass)->type;
7809                         goto handle_enum;
7810                 } else {
7811                         MonoClass *k =  t->data.klass;
7812                         
7813                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7814                                 guint64 *val = g_malloc (sizeof (guint64));
7815                                 *val = read64 (p);
7816                                 *end = p + 8;
7817                                 return val;
7818                         }
7819                 }
7820                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7821                 break;
7822                 
7823         case MONO_TYPE_STRING:
7824                 if (*p == (char)0xFF) {
7825                         *end = p + 1;
7826                         return NULL;
7827                 }
7828                 slen = mono_metadata_decode_value (p, &p);
7829                 *end = p + slen;
7830                 return mono_string_new_len (mono_domain_get (), p, slen);
7831         case MONO_TYPE_CLASS: {
7832                 char *n;
7833                 MonoType *t;
7834                 if (*p == (char)0xFF) {
7835                         *end = p + 1;
7836                         return NULL;
7837                 }
7838 handle_type:
7839                 slen = mono_metadata_decode_value (p, &p);
7840                 n = g_memdup (p, slen + 1);
7841                 n [slen] = 0;
7842                 t = mono_reflection_type_from_name (n, image);
7843                 if (!t)
7844                         g_warning ("Cannot load type '%s'", n);
7845                 g_free (n);
7846                 *end = p + slen;
7847                 if (t)
7848                         return mono_type_get_object (mono_domain_get (), t);
7849                 else
7850                         return NULL;
7851         }
7852         case MONO_TYPE_OBJECT: {
7853                 char subt = *p++;
7854                 MonoObject *obj;
7855                 MonoClass *subc = NULL;
7856                 void *val;
7857
7858                 if (subt == 0x50) {
7859                         goto handle_type;
7860                 } else if (subt == 0x0E) {
7861                         type = MONO_TYPE_STRING;
7862                         goto handle_enum;
7863                 } else if (subt == 0x1D) {
7864                         MonoType simple_type = {{0}};
7865                         int etype = *p;
7866                         p ++;
7867
7868                         type = MONO_TYPE_SZARRAY;
7869                         if (etype == 0x50) {
7870                                 tklass = mono_defaults.systemtype_class;
7871                         } else {
7872                                 if (etype == 0x51)
7873                                         /* See Partition II, Appendix B3 */
7874                                         etype = MONO_TYPE_OBJECT;
7875                                 simple_type.type = etype;
7876                                 tklass = mono_class_from_mono_type (&simple_type);
7877                         }
7878                         goto handle_enum;
7879                 } else if (subt == 0x55) {
7880                         char *n;
7881                         MonoType *t;
7882                         slen = mono_metadata_decode_value (p, &p);
7883                         n = g_memdup (p, slen + 1);
7884                         n [slen] = 0;
7885                         t = mono_reflection_type_from_name (n, image);
7886                         if (!t)
7887                                 g_error ("Cannot load type '%s'", n);
7888                         g_free (n);
7889                         p += slen;
7890                         subc = mono_class_from_mono_type (t);
7891                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7892                         MonoType simple_type = {{0}};
7893                         simple_type.type = subt;
7894                         subc = mono_class_from_mono_type (&simple_type);
7895                 } else {
7896                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7897                 }
7898                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7899                 obj = mono_object_new (mono_domain_get (), subc);
7900                 g_assert (!subc->has_references);
7901                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7902                 g_free (val);
7903                 return obj;
7904         }
7905         case MONO_TYPE_SZARRAY: {
7906                 MonoArray *arr;
7907                 guint32 i, alen, basetype;
7908                 alen = read32 (p);
7909                 p += 4;
7910                 if (alen == 0xffffffff) {
7911                         *end = p;
7912                         return NULL;
7913                 }
7914                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7915                 basetype = tklass->byval_arg.type;
7916                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7917                         basetype = mono_class_enum_basetype (tklass)->type;
7918                 switch (basetype)
7919                 {
7920                         case MONO_TYPE_U1:
7921                         case MONO_TYPE_I1:
7922                         case MONO_TYPE_BOOLEAN:
7923                                 for (i = 0; i < alen; i++) {
7924                                         MonoBoolean val = *p++;
7925                                         mono_array_set (arr, MonoBoolean, i, val);
7926                                 }
7927                                 break;
7928                         case MONO_TYPE_CHAR:
7929                         case MONO_TYPE_U2:
7930                         case MONO_TYPE_I2:
7931                                 for (i = 0; i < alen; i++) {
7932                                         guint16 val = read16 (p);
7933                                         mono_array_set (arr, guint16, i, val);
7934                                         p += 2;
7935                                 }
7936                                 break;
7937                         case MONO_TYPE_R4:
7938                         case MONO_TYPE_U4:
7939                         case MONO_TYPE_I4:
7940                                 for (i = 0; i < alen; i++) {
7941                                         guint32 val = read32 (p);
7942                                         mono_array_set (arr, guint32, i, val);
7943                                         p += 4;
7944                                 }
7945                                 break;
7946                         case MONO_TYPE_R8:
7947                                 for (i = 0; i < alen; i++) {
7948                                         double val;
7949                                         readr8 (p, &val);
7950                                         mono_array_set (arr, double, i, val);
7951                                         p += 8;
7952                                 }
7953                                 break;
7954                         case MONO_TYPE_U8:
7955                         case MONO_TYPE_I8:
7956                                 for (i = 0; i < alen; i++) {
7957                                         guint64 val = read64 (p);
7958                                         mono_array_set (arr, guint64, i, val);
7959                                         p += 8;
7960                                 }
7961                                 break;
7962                         case MONO_TYPE_CLASS:
7963                         case MONO_TYPE_OBJECT:
7964                         case MONO_TYPE_STRING:
7965                                 for (i = 0; i < alen; i++) {
7966                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7967                                         mono_array_setref (arr, i, item);
7968                                 }
7969                                 break;
7970                         default:
7971                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7972                 }
7973                 *end=p;
7974                 return arr;
7975         }
7976         default:
7977                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7978         }
7979         return NULL;
7980 }
7981
7982 static MonoObject*
7983 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7984 {
7985         static MonoClass *klass;
7986         static MonoMethod *ctor;
7987         MonoObject *retval;
7988         void *params [2], *unboxed;
7989
7990         if (!klass)
7991                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7992         if (!ctor)
7993                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7994         
7995         params [0] = mono_type_get_object (mono_domain_get (), t);
7996         params [1] = val;
7997         retval = mono_object_new (mono_domain_get (), klass);
7998         unboxed = mono_object_unbox (retval);
7999         mono_runtime_invoke (ctor, unboxed, params, NULL);
8000
8001         return retval;
8002 }
8003
8004 static MonoObject*
8005 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8006 {
8007         static MonoClass *klass;
8008         static MonoMethod *ctor;
8009         MonoObject *retval;
8010         void *unboxed, *params [2];
8011
8012         if (!klass)
8013                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8014         if (!ctor)
8015                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8016
8017         params [0] = minfo;
8018         params [1] = typedarg;
8019         retval = mono_object_new (mono_domain_get (), klass);
8020         unboxed = mono_object_unbox (retval);
8021         mono_runtime_invoke (ctor, unboxed, params, NULL);
8022
8023         return retval;
8024 }
8025
8026 static gboolean
8027 type_is_reference (MonoType *type)
8028 {
8029         switch (type->type) {
8030         case MONO_TYPE_BOOLEAN:
8031         case MONO_TYPE_CHAR:
8032         case MONO_TYPE_U:
8033         case MONO_TYPE_I:
8034         case MONO_TYPE_U1:
8035         case MONO_TYPE_I1:
8036         case MONO_TYPE_U2:
8037         case MONO_TYPE_I2:
8038         case MONO_TYPE_U4:
8039         case MONO_TYPE_I4:
8040         case MONO_TYPE_U8:
8041         case MONO_TYPE_I8:
8042         case MONO_TYPE_R8:
8043         case MONO_TYPE_R4:
8044         case MONO_TYPE_VALUETYPE:
8045                 return FALSE;
8046         default:
8047                 return TRUE;
8048         }
8049 }
8050
8051 static void
8052 free_param_data (MonoMethodSignature *sig, void **params) {
8053         int i;
8054         for (i = 0; i < sig->param_count; ++i) {
8055                 if (!type_is_reference (sig->params [i]))
8056                         g_free (params [i]);
8057         }
8058 }
8059
8060 /*
8061  * Find the field index in the metadata FieldDef table.
8062  */
8063 static guint32
8064 find_field_index (MonoClass *klass, MonoClassField *field) {
8065         int i;
8066
8067         for (i = 0; i < klass->field.count; ++i) {
8068                 if (field == &klass->fields [i])
8069                         return klass->field.first + 1 + i;
8070         }
8071         return 0;
8072 }
8073
8074 /*
8075  * Find the property index in the metadata Property table.
8076  */
8077 static guint32
8078 find_property_index (MonoClass *klass, MonoProperty *property) {
8079         int i;
8080
8081         for (i = 0; i < klass->ext->property.count; ++i) {
8082                 if (property == &klass->ext->properties [i])
8083                         return klass->ext->property.first + 1 + i;
8084         }
8085         return 0;
8086 }
8087
8088 /*
8089  * Find the event index in the metadata Event table.
8090  */
8091 static guint32
8092 find_event_index (MonoClass *klass, MonoEvent *event) {
8093         int i;
8094
8095         for (i = 0; i < klass->ext->event.count; ++i) {
8096                 if (event == &klass->ext->events [i])
8097                         return klass->ext->event.first + 1 + i;
8098         }
8099         return 0;
8100 }
8101
8102 static MonoObject*
8103 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8104 {
8105         const char *p = (const char*)data;
8106         const char *named;
8107         guint32 i, j, num_named;
8108         MonoObject *attr;
8109         void *params_buf [32];
8110         void **params;
8111         MonoMethodSignature *sig;
8112
8113         mono_error_init (error);
8114
8115         mono_class_init (method->klass);
8116
8117         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8118                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8119                 return NULL;
8120         }
8121
8122         if (len == 0) {
8123                 attr = mono_object_new (mono_domain_get (), method->klass);
8124                 mono_runtime_invoke (method, attr, NULL, NULL);
8125                 return attr;
8126         }
8127
8128         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8129                 return NULL;
8130
8131         /*g_print ("got attr %s\n", method->klass->name);*/
8132
8133         sig = mono_method_signature (method);
8134         if (sig->param_count < 32)
8135                 params = params_buf;
8136         else
8137                 /* Allocate using GC so it gets GC tracking */
8138                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8139
8140         /* skip prolog */
8141         p += 2;
8142         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8143                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8144         }
8145
8146         named = p;
8147         attr = mono_object_new (mono_domain_get (), method->klass);
8148         mono_runtime_invoke (method, attr, params, NULL);
8149         free_param_data (method->signature, params);
8150         num_named = read16 (named);
8151         named += 2;
8152         for (j = 0; j < num_named; j++) {
8153                 gint name_len;
8154                 char *name, named_type, data_type;
8155                 named_type = *named++;
8156                 data_type = *named++; /* type of data */
8157                 if (data_type == MONO_TYPE_SZARRAY)
8158                         data_type = *named++;
8159                 if (data_type == MONO_TYPE_ENUM) {
8160                         gint type_len;
8161                         char *type_name;
8162                         type_len = mono_metadata_decode_blob_size (named, &named);
8163                         type_name = g_malloc (type_len + 1);
8164                         memcpy (type_name, named, type_len);
8165                         type_name [type_len] = 0;
8166                         named += type_len;
8167                         /* FIXME: lookup the type and check type consistency */
8168                         g_free (type_name);
8169                 }
8170                 name_len = mono_metadata_decode_blob_size (named, &named);
8171                 name = g_malloc (name_len + 1);
8172                 memcpy (name, named, name_len);
8173                 name [name_len] = 0;
8174                 named += name_len;
8175                 if (named_type == 0x53) {
8176                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8177                         void *val = load_cattr_value (image, field->type, named, &named);
8178                         mono_field_set_value (attr, field, val);
8179                         if (!type_is_reference (field->type))
8180                                 g_free (val);
8181                 } else if (named_type == 0x54) {
8182                         MonoProperty *prop;
8183                         void *pparams [1];
8184                         MonoType *prop_type;
8185
8186                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8187                         /* can we have more that 1 arg in a custom attr named property? */
8188                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8189                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8190                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8191                         mono_property_set_value (prop, attr, pparams, NULL);
8192                         if (!type_is_reference (prop_type))
8193                                 g_free (pparams [0]);
8194                 }
8195                 g_free (name);
8196         }
8197
8198         if (params != params_buf)
8199                 mono_gc_free_fixed (params);
8200
8201         return attr;
8202 }
8203         
8204 /*
8205  * mono_reflection_create_custom_attr_data_args:
8206  *
8207  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8208  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8209  * NAMED_ARG_INFO will contain information about the named arguments.
8210  */
8211 void
8212 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)
8213 {
8214         MonoArray *typedargs, *namedargs;
8215         MonoClass *attrklass;
8216         MonoDomain *domain;
8217         const char *p = (const char*)data;
8218         const char *named;
8219         guint32 i, j, num_named;
8220         CattrNamedArg *arginfo = NULL;
8221
8222         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8223                 return;
8224
8225         mono_class_init (method->klass);
8226
8227         *typed_args = NULL;
8228         *named_args = NULL;
8229         *named_arg_info = NULL;
8230         
8231         domain = mono_domain_get ();
8232
8233         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8234                 return;
8235
8236         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8237         
8238         /* skip prolog */
8239         p += 2;
8240         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8241                 MonoObject *obj;
8242                 void *val;
8243
8244                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8245                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8246                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8247                 mono_array_setref (typedargs, i, obj);
8248
8249                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8250                         g_free (val);
8251         }
8252
8253         named = p;
8254         num_named = read16 (named);
8255         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8256         named += 2;
8257         attrklass = method->klass;
8258
8259         arginfo = g_new0 (CattrNamedArg, num_named);
8260         *named_arg_info = arginfo;
8261
8262         for (j = 0; j < num_named; j++) {
8263                 gint name_len;
8264                 char *name, named_type, data_type;
8265                 named_type = *named++;
8266                 data_type = *named++; /* type of data */
8267                 if (data_type == MONO_TYPE_SZARRAY)
8268                         data_type = *named++;
8269                 if (data_type == MONO_TYPE_ENUM) {
8270                         gint type_len;
8271                         char *type_name;
8272                         type_len = mono_metadata_decode_blob_size (named, &named);
8273                         type_name = g_malloc (type_len + 1);
8274                         memcpy (type_name, named, type_len);
8275                         type_name [type_len] = 0;
8276                         named += type_len;
8277                         /* FIXME: lookup the type and check type consistency */
8278                         g_free (type_name);
8279                 }
8280                 name_len = mono_metadata_decode_blob_size (named, &named);
8281                 name = g_malloc (name_len + 1);
8282                 memcpy (name, named, name_len);
8283                 name [name_len] = 0;
8284                 named += name_len;
8285                 if (named_type == 0x53) {
8286                         MonoObject *obj;
8287                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8288                         void *val;
8289
8290                         arginfo [j].type = field->type;
8291                         arginfo [j].field = field;
8292
8293                         val = load_cattr_value (image, field->type, named, &named);
8294                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8295                         mono_array_setref (namedargs, j, obj);
8296                         if (!type_is_reference (field->type))
8297                                 g_free (val);
8298                 } else if (named_type == 0x54) {
8299                         MonoObject *obj;
8300                         MonoType *prop_type;
8301                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8302                         void *val;
8303
8304                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8305                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8306
8307                         arginfo [j].type = prop_type;
8308                         arginfo [j].prop = prop;
8309
8310                         val = load_cattr_value (image, prop_type, named, &named);
8311                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8312                         mono_array_setref (namedargs, j, obj);
8313                         if (!type_is_reference (prop_type))
8314                                 g_free (val);
8315                 }
8316                 g_free (name);
8317         }
8318
8319         *typed_args = typedargs;
8320         *named_args = namedargs;
8321 }
8322
8323 void
8324 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8325 {
8326         MonoDomain *domain;
8327         MonoArray *typedargs, *namedargs;
8328         MonoImage *image;
8329         MonoMethod *method;
8330         CattrNamedArg *arginfo;
8331         int i;
8332
8333         *ctor_args = NULL;
8334         *named_args = NULL;
8335
8336         if (len == 0)
8337                 return;
8338
8339         image = assembly->assembly->image;
8340         method = ref_method->method;
8341         domain = mono_object_domain (ref_method);
8342
8343         if (!mono_class_init (method->klass))
8344                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8345
8346         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8347         if (mono_loader_get_last_error ())
8348                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8349
8350         if (!typedargs || !namedargs)
8351                 return;
8352
8353         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8354                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8355                 MonoObject *typedarg;
8356
8357                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8358                 mono_array_setref (typedargs, i, typedarg);
8359         }
8360
8361         for (i = 0; i < mono_array_length (namedargs); ++i) {
8362                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8363                 MonoObject *typedarg, *namedarg, *minfo;
8364
8365                 if (arginfo [i].prop)
8366                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8367                 else
8368                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8369
8370                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8371                 namedarg = create_cattr_named_arg (minfo, typedarg);
8372
8373                 mono_array_setref (namedargs, i, namedarg);
8374         }
8375
8376         *ctor_args = typedargs;
8377         *named_args = namedargs;
8378 }
8379
8380 static MonoObject*
8381 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8382 {
8383         static MonoMethod *ctor;
8384         MonoDomain *domain;
8385         MonoObject *attr;
8386         void *params [4];
8387
8388         g_assert (image->assembly);
8389
8390         if (!ctor)
8391                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8392
8393         domain = mono_domain_get ();
8394         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8395         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8396         params [1] = mono_assembly_get_object (domain, image->assembly);
8397         params [2] = (gpointer)&cattr->data;
8398         params [3] = &cattr->data_size;
8399         mono_runtime_invoke (ctor, attr, params, NULL);
8400         return attr;
8401 }
8402
8403 static MonoArray*
8404 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8405 {
8406         MonoArray *result;
8407         MonoObject *attr;
8408         int i, n;
8409
8410         mono_error_init (error);
8411
8412         n = 0;
8413         for (i = 0; i < cinfo->num_attrs; ++i) {
8414                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8415                         n ++;
8416         }
8417
8418         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8419         n = 0;
8420         for (i = 0; i < cinfo->num_attrs; ++i) {
8421                 if (!cinfo->attrs [i].ctor)
8422                         /* The cattr type is not finished yet */
8423                         /* We should include the type name but cinfo doesn't contain it */
8424                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8425                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8426                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8427                         if (!mono_error_ok (error))
8428                                 return result;
8429                         mono_array_setref (result, n, attr);
8430                         n ++;
8431                 }
8432         }
8433         return result;
8434 }
8435
8436 MonoArray*
8437 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8438 {
8439         MonoError error;
8440
8441         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8442 }
8443
8444 static MonoArray*
8445 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8446 {
8447         MonoArray *result;
8448         MonoObject *attr;
8449         int i;
8450         
8451         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8452         for (i = 0; i < cinfo->num_attrs; ++i) {
8453                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8454                 mono_array_setref (result, i, attr);
8455         }
8456         return result;
8457 }
8458
8459 /**
8460  * mono_custom_attrs_from_index:
8461  *
8462  * Returns: NULL if no attributes are found or if a loading error occurs.
8463  */
8464 MonoCustomAttrInfo*
8465 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8466 {
8467         guint32 mtoken, i, len;
8468         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8469         MonoTableInfo *ca;
8470         MonoCustomAttrInfo *ainfo;
8471         GList *tmp, *list = NULL;
8472         const char *data;
8473
8474         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8475
8476         i = mono_metadata_custom_attrs_from_index (image, idx);
8477         if (!i)
8478                 return NULL;
8479         i --;
8480         while (i < ca->rows) {
8481                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8482                         break;
8483                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8484                 ++i;
8485         }
8486         len = g_list_length (list);
8487         if (!len)
8488                 return NULL;
8489         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8490         ainfo->num_attrs = len;
8491         ainfo->image = image;
8492         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8493                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8494                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8495                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8496                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8497                         mtoken |= MONO_TOKEN_METHOD_DEF;
8498                         break;
8499                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8500                         mtoken |= MONO_TOKEN_MEMBER_REF;
8501                         break;
8502                 default:
8503                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8504                         break;
8505                 }
8506                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8507                 if (!ainfo->attrs [i].ctor) {
8508                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8509                         g_list_free (list);
8510                         g_free (ainfo);
8511                         return NULL;
8512                 }
8513
8514                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8515                         /*FIXME raising an exception here doesn't make any sense*/
8516                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8517                         g_list_free (list);
8518                         g_free (ainfo);
8519                         return NULL;
8520                 }
8521                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8522                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8523                 ainfo->attrs [i].data = (guchar*)data;
8524         }
8525         g_list_free (list);
8526
8527         return ainfo;
8528 }
8529
8530 MonoCustomAttrInfo*
8531 mono_custom_attrs_from_method (MonoMethod *method)
8532 {
8533         guint32 idx;
8534
8535         /*
8536          * An instantiated method has the same cattrs as the generic method definition.
8537          *
8538          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8539          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8540          */
8541         if (method->is_inflated)
8542                 method = ((MonoMethodInflated *) method)->declaring;
8543         
8544         if (method->dynamic || method->klass->image->dynamic)
8545                 return lookup_custom_attr (method->klass->image, method);
8546
8547         if (!method->token)
8548                 /* Synthetic methods */
8549                 return NULL;
8550
8551         idx = mono_method_get_index (method);
8552         idx <<= MONO_CUSTOM_ATTR_BITS;
8553         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8554         return mono_custom_attrs_from_index (method->klass->image, idx);
8555 }
8556
8557 MonoCustomAttrInfo*
8558 mono_custom_attrs_from_class (MonoClass *klass)
8559 {
8560         guint32 idx;
8561
8562         if (klass->generic_class)
8563                 klass = klass->generic_class->container_class;
8564
8565         if (klass->image->dynamic)
8566                 return lookup_custom_attr (klass->image, klass);
8567
8568         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8569                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8570                 idx <<= MONO_CUSTOM_ATTR_BITS;
8571                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8572         } else {
8573                 idx = mono_metadata_token_index (klass->type_token);
8574                 idx <<= MONO_CUSTOM_ATTR_BITS;
8575                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8576         }
8577         return mono_custom_attrs_from_index (klass->image, idx);
8578 }
8579
8580 MonoCustomAttrInfo*
8581 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8582 {
8583         guint32 idx;
8584         
8585         if (assembly->image->dynamic)
8586                 return lookup_custom_attr (assembly->image, assembly);
8587         idx = 1; /* there is only one assembly */
8588         idx <<= MONO_CUSTOM_ATTR_BITS;
8589         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8590         return mono_custom_attrs_from_index (assembly->image, idx);
8591 }
8592
8593 static MonoCustomAttrInfo*
8594 mono_custom_attrs_from_module (MonoImage *image)
8595 {
8596         guint32 idx;
8597         
8598         if (image->dynamic)
8599                 return lookup_custom_attr (image, image);
8600         idx = 1; /* there is only one module */
8601         idx <<= MONO_CUSTOM_ATTR_BITS;
8602         idx |= MONO_CUSTOM_ATTR_MODULE;
8603         return mono_custom_attrs_from_index (image, idx);
8604 }
8605
8606 MonoCustomAttrInfo*
8607 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8608 {
8609         guint32 idx;
8610         
8611         if (klass->image->dynamic) {
8612                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8613                 return lookup_custom_attr (klass->image, property);
8614         }
8615         idx = find_property_index (klass, property);
8616         idx <<= MONO_CUSTOM_ATTR_BITS;
8617         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8618         return mono_custom_attrs_from_index (klass->image, idx);
8619 }
8620
8621 MonoCustomAttrInfo*
8622 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8623 {
8624         guint32 idx;
8625         
8626         if (klass->image->dynamic) {
8627                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8628                 return lookup_custom_attr (klass->image, event);
8629         }
8630         idx = find_event_index (klass, event);
8631         idx <<= MONO_CUSTOM_ATTR_BITS;
8632         idx |= MONO_CUSTOM_ATTR_EVENT;
8633         return mono_custom_attrs_from_index (klass->image, idx);
8634 }
8635
8636 MonoCustomAttrInfo*
8637 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8638 {
8639         guint32 idx;
8640         if (klass->image->dynamic) {
8641                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8642                 return lookup_custom_attr (klass->image, field);
8643         }
8644         idx = find_field_index (klass, field);
8645         idx <<= MONO_CUSTOM_ATTR_BITS;
8646         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8647         return mono_custom_attrs_from_index (klass->image, idx);
8648 }
8649
8650 MonoCustomAttrInfo*
8651 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8652 {
8653         MonoTableInfo *ca;
8654         guint32 i, idx, method_index;
8655         guint32 param_list, param_last, param_pos, found;
8656         MonoImage *image;
8657         MonoReflectionMethodAux *aux;
8658
8659         /*
8660          * An instantiated method has the same cattrs as the generic method definition.
8661          *
8662          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8663          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8664          */
8665         if (method->is_inflated)
8666                 method = ((MonoMethodInflated *) method)->declaring;
8667
8668         if (method->klass->image->dynamic) {
8669                 MonoCustomAttrInfo *res, *ainfo;
8670                 int size;
8671
8672                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8673                 if (!aux || !aux->param_cattr)
8674                         return NULL;
8675
8676                 /* Need to copy since it will be freed later */
8677                 ainfo = aux->param_cattr [param];
8678                 if (!ainfo)
8679                         return NULL;
8680                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8681                 res = g_malloc0 (size);
8682                 memcpy (res, ainfo, size);
8683                 return res;
8684         }
8685
8686         image = method->klass->image;
8687         method_index = mono_method_get_index (method);
8688         if (!method_index)
8689                 return NULL;
8690         ca = &image->tables [MONO_TABLE_METHOD];
8691
8692         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8693         if (method_index == ca->rows) {
8694                 ca = &image->tables [MONO_TABLE_PARAM];
8695                 param_last = ca->rows + 1;
8696         } else {
8697                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8698                 ca = &image->tables [MONO_TABLE_PARAM];
8699         }
8700         found = FALSE;
8701         for (i = param_list; i < param_last; ++i) {
8702                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8703                 if (param_pos == param) {
8704                         found = TRUE;
8705                         break;
8706                 }
8707         }
8708         if (!found)
8709                 return NULL;
8710         idx = i;
8711         idx <<= MONO_CUSTOM_ATTR_BITS;
8712         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8713         return mono_custom_attrs_from_index (image, idx);
8714 }
8715
8716 gboolean
8717 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8718 {
8719         int i;
8720         MonoClass *klass;
8721         for (i = 0; i < ainfo->num_attrs; ++i) {
8722                 klass = ainfo->attrs [i].ctor->klass;
8723                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8724                         return TRUE;
8725         }
8726         return FALSE;
8727 }
8728
8729 MonoObject*
8730 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8731 {
8732         int i, attr_index;
8733         MonoClass *klass;
8734         MonoArray *attrs;
8735
8736         attr_index = -1;
8737         for (i = 0; i < ainfo->num_attrs; ++i) {
8738                 klass = ainfo->attrs [i].ctor->klass;
8739                 if (mono_class_has_parent (klass, attr_klass)) {
8740                         attr_index = i;
8741                         break;
8742                 }
8743         }
8744         if (attr_index == -1)
8745                 return NULL;
8746
8747         attrs = mono_custom_attrs_construct (ainfo);
8748         if (attrs)
8749                 return mono_array_get (attrs, MonoObject*, attr_index);
8750         else
8751                 return NULL;
8752 }
8753
8754 /*
8755  * mono_reflection_get_custom_attrs_info:
8756  * @obj: a reflection object handle
8757  *
8758  * Return the custom attribute info for attributes defined for the
8759  * reflection handle @obj. The objects.
8760  *
8761  * FIXME this function leaks like a sieve for SRE objects.
8762  */
8763 MonoCustomAttrInfo*
8764 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8765 {
8766         MonoClass *klass;
8767         MonoCustomAttrInfo *cinfo = NULL;
8768         
8769         klass = obj->vtable->klass;
8770         if (klass == mono_defaults.monotype_class) {
8771                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8772                 klass = mono_class_from_mono_type (type);
8773                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8774                 cinfo = mono_custom_attrs_from_class (klass);
8775         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8776                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8777                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8778         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8779                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8780                 cinfo = mono_custom_attrs_from_module (module->image);
8781         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8782                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8783                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8784         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8785                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8786                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8787         } else if (strcmp ("MonoField", klass->name) == 0) {
8788                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8789                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8790         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8791                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8792                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8793         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8794                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8795                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8796         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8797                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8798                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8799                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8800                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8801                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8802                 } else if (is_sr_mono_property (member_class)) {
8803                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8804                         MonoMethod *method;
8805                         if (!(method = prop->property->get))
8806                                 method = prop->property->set;
8807                         g_assert (method);
8808
8809                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8810                 } 
8811 #ifndef DISABLE_REFLECTION_EMIT
8812                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8813                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8814                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8815                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8816                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8817                         MonoMethod *method = NULL;
8818                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8819                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8820                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8821                                 method = ((MonoReflectionMethod *)c->cb)->method;
8822                         else
8823                                 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));
8824
8825                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8826                 } 
8827 #endif
8828                 else {
8829                         char *type_name = mono_type_get_full_name (member_class);
8830                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8831                         MonoException *ex = mono_get_exception_not_supported  (msg);
8832                         g_free (type_name);
8833                         g_free (msg);
8834                         mono_raise_exception (ex);
8835                 }
8836         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8837                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8838                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8839         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8840                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8841                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8842         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8843                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8844                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8845         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8846                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8847                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8848         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8849                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8850                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8851         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8852                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8853                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8854         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8855                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8856                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8857         } else { /* handle other types here... */
8858                 g_error ("get custom attrs not yet supported for %s", klass->name);
8859         }
8860
8861         return cinfo;
8862 }
8863
8864 /*
8865  * mono_reflection_get_custom_attrs_by_type:
8866  * @obj: a reflection object handle
8867  *
8868  * Return an array with all the custom attributes defined of the
8869  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8870  * of that type are returned. The objects are fully build. Return NULL if a loading error
8871  * occurs.
8872  */
8873 MonoArray*
8874 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8875 {
8876         MonoArray *result;
8877         MonoCustomAttrInfo *cinfo;
8878
8879         mono_error_init (error);
8880
8881         cinfo = mono_reflection_get_custom_attrs_info (obj);
8882         if (cinfo) {
8883                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8884                 if (!cinfo->cached)
8885                         mono_custom_attrs_free (cinfo);
8886         } else {
8887                 if (mono_loader_get_last_error ())
8888                         return NULL;
8889                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8890         }
8891
8892         return result;
8893 }
8894
8895 /*
8896  * mono_reflection_get_custom_attrs:
8897  * @obj: a reflection object handle
8898  *
8899  * Return an array with all the custom attributes defined of the
8900  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8901  * occurs.
8902  */
8903 MonoArray*
8904 mono_reflection_get_custom_attrs (MonoObject *obj)
8905 {
8906         MonoError error;
8907
8908         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8909 }
8910
8911 /*
8912  * mono_reflection_get_custom_attrs_data:
8913  * @obj: a reflection obj handle
8914  *
8915  * Returns an array of System.Reflection.CustomAttributeData,
8916  * which include information about attributes reflected on
8917  * types loaded using the Reflection Only methods
8918  */
8919 MonoArray*
8920 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8921 {
8922         MonoArray *result;
8923         MonoCustomAttrInfo *cinfo;
8924
8925         cinfo = mono_reflection_get_custom_attrs_info (obj);
8926         if (cinfo) {
8927                 result = mono_custom_attrs_data_construct (cinfo);
8928                 if (!cinfo->cached)
8929                         mono_custom_attrs_free (cinfo);
8930         } else
8931                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8932
8933         return result;
8934 }
8935
8936 static MonoReflectionType*
8937 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8938 {
8939         static MonoMethod *method_get_underlying_system_type = NULL;
8940         MonoMethod *usertype_method;
8941
8942         if (!method_get_underlying_system_type)
8943                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8944         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8945         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8946 }
8947
8948
8949 static gboolean
8950 is_corlib_type (MonoClass *class)
8951 {
8952         return class->image == mono_defaults.corlib;
8953 }
8954
8955 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8956         static MonoClass *cached_class; \
8957         if (cached_class) \
8958                 return cached_class == _class; \
8959         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8960                 cached_class = _class; \
8961                 return TRUE; \
8962         } \
8963         return FALSE; \
8964 } while (0) \
8965
8966
8967 #ifndef DISABLE_REFLECTION_EMIT
8968 static gboolean
8969 is_sre_array (MonoClass *class)
8970 {
8971         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8972 }
8973
8974 static gboolean
8975 is_sre_byref (MonoClass *class)
8976 {
8977         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8978 }
8979
8980 static gboolean
8981 is_sre_pointer (MonoClass *class)
8982 {
8983         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8984 }
8985
8986 static gboolean
8987 is_sre_generic_instance (MonoClass *class)
8988 {
8989         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8990 }
8991
8992 static gboolean
8993 is_sre_type_builder (MonoClass *class)
8994 {
8995         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8996 }
8997
8998 static gboolean
8999 is_sre_method_builder (MonoClass *class)
9000 {
9001         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9002 }
9003
9004 static gboolean
9005 is_sre_ctor_builder (MonoClass *class)
9006 {
9007         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9008 }
9009
9010 static gboolean
9011 is_sre_field_builder (MonoClass *class)
9012 {
9013         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9014 }
9015
9016 static gboolean
9017 is_sre_method_on_tb_inst (MonoClass *class)
9018 {
9019         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9020 }
9021
9022 static gboolean
9023 is_sre_ctor_on_tb_inst (MonoClass *class)
9024 {
9025         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9026 }
9027
9028 MonoType*
9029 mono_reflection_type_get_handle (MonoReflectionType* ref)
9030 {
9031         MonoClass *class;
9032         if (!ref)
9033                 return NULL;
9034         if (ref->type)
9035                 return ref->type;
9036
9037         if (is_usertype (ref)) {
9038                 ref = mono_reflection_type_get_underlying_system_type (ref);
9039                 if (ref == NULL || is_usertype (ref))
9040                         return NULL;
9041                 if (ref->type)
9042                         return ref->type;
9043         }
9044
9045         class = mono_object_class (ref);
9046
9047         if (is_sre_array (class)) {
9048                 MonoType *res;
9049                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9050                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9051                 g_assert (base);
9052                 if (sre_array->rank == 0) //single dimentional array
9053                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9054                 else
9055                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9056                 sre_array->type.type = res;
9057                 return res;
9058         } else if (is_sre_byref (class)) {
9059                 MonoType *res;
9060                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9061                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9062                 g_assert (base);
9063                 res = &mono_class_from_mono_type (base)->this_arg;
9064                 sre_byref->type.type = res;
9065                 return res;
9066         } else if (is_sre_pointer (class)) {
9067                 MonoType *res;
9068                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9069                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9070                 g_assert (base);
9071                 res = &mono_ptr_class_get (base)->byval_arg;
9072                 sre_pointer->type.type = res;
9073                 return res;
9074         } else if (is_sre_generic_instance (class)) {
9075                 MonoType *res, **types;
9076                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9077                 int i, count;
9078
9079                 count = mono_array_length (gclass->type_arguments);
9080                 types = g_new0 (MonoType*, count);
9081                 for (i = 0; i < count; ++i) {
9082                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9083                         types [i] = mono_reflection_type_get_handle (t);
9084                         if (!types[i]) {
9085                                 g_free (types);
9086                                 return NULL;
9087                         }
9088                 }
9089
9090                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9091                 g_free (types);
9092                 g_assert (res);
9093                 gclass->type.type = res;
9094                 return res;
9095         }
9096
9097         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9098         return NULL;
9099 }
9100
9101
9102
9103 void
9104 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9105 {
9106         mono_reflection_type_get_handle (type);
9107 }
9108
9109 void
9110 mono_reflection_register_with_runtime (MonoReflectionType *type)
9111 {
9112         MonoType *res = mono_reflection_type_get_handle (type);
9113         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9114         MonoClass *class;
9115
9116         if (!res)
9117                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9118
9119         class = mono_class_from_mono_type (res);
9120
9121         mono_loader_lock (); /*same locking as mono_type_get_object*/
9122         mono_domain_lock (domain);
9123
9124         if (!class->image->dynamic) {
9125                 mono_class_setup_supertypes (class);
9126         } else {
9127                 if (!domain->type_hash)
9128                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9129                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9130                 mono_g_hash_table_insert (domain->type_hash, res, type);
9131         }
9132         mono_domain_unlock (domain);
9133         mono_loader_unlock ();
9134 }
9135
9136 /**
9137  * LOCKING: Assumes the loader lock is held.
9138  */
9139 static MonoMethodSignature*
9140 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9141         MonoMethodSignature *sig;
9142         int count, i;
9143
9144         count = parameters? mono_array_length (parameters): 0;
9145
9146         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9147         sig->param_count = count;
9148         sig->sentinelpos = -1; /* FIXME */
9149         for (i = 0; i < count; ++i)
9150                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9151         return sig;
9152 }
9153
9154 /**
9155  * LOCKING: Assumes the loader lock is held.
9156  */
9157 static MonoMethodSignature*
9158 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9159         MonoMethodSignature *sig;
9160
9161         sig = parameters_to_signature (image, ctor->parameters);
9162         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9163         sig->ret = &mono_defaults.void_class->byval_arg;
9164         return sig;
9165 }
9166
9167 /**
9168  * LOCKING: Assumes the loader lock is held.
9169  */
9170 static MonoMethodSignature*
9171 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9172         MonoMethodSignature *sig;
9173
9174         sig = parameters_to_signature (image, method->parameters);
9175         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9176         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9177         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9178         return sig;
9179 }
9180
9181 static MonoMethodSignature*
9182 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9183         MonoMethodSignature *sig;
9184
9185         sig = parameters_to_signature (NULL, method->parameters);
9186         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9187         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9188         sig->generic_param_count = 0;
9189         return sig;
9190 }
9191
9192 static void
9193 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9194 {
9195         MonoClass *klass = mono_object_class (prop);
9196         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9197                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9198                 *name = mono_string_to_utf8 (pb->name);
9199                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9200         } else {
9201                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9202                 *name = g_strdup (p->property->name);
9203                 if (p->property->get)
9204                         *type = mono_method_signature (p->property->get)->ret;
9205                 else
9206                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9207         }
9208 }
9209
9210 static void
9211 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9212 {
9213         MonoClass *klass = mono_object_class (field);
9214         if (strcmp (klass->name, "FieldBuilder") == 0) {
9215                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9216                 *name = mono_string_to_utf8 (fb->name);
9217                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9218         } else {
9219                 MonoReflectionField *f = (MonoReflectionField *)field;
9220                 *name = g_strdup (mono_field_get_name (f->field));
9221                 *type = f->field->type;
9222         }
9223 }
9224
9225 #else /* DISABLE_REFLECTION_EMIT */
9226
9227 void
9228 mono_reflection_register_with_runtime (MonoReflectionType *type)
9229 {
9230         /* This is empty */
9231 }
9232
9233 static gboolean
9234 is_sre_type_builder (MonoClass *class)
9235 {
9236         return FALSE;
9237 }
9238
9239 static gboolean
9240 is_sre_generic_instance (MonoClass *class)
9241 {
9242         return FALSE;
9243 }
9244
9245 static void
9246 init_type_builder_generics (MonoObject *type)
9247 {
9248 }
9249
9250 #endif /* !DISABLE_REFLECTION_EMIT */
9251
9252
9253 static gboolean
9254 is_sr_mono_field (MonoClass *class)
9255 {
9256         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9257 }
9258
9259 static gboolean
9260 is_sr_mono_property (MonoClass *class)
9261 {
9262         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9263 }
9264
9265 static gboolean
9266 is_sr_mono_method (MonoClass *class)
9267 {
9268         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9269 }
9270
9271 static gboolean
9272 is_sr_mono_cmethod (MonoClass *class)
9273 {
9274         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9275 }
9276
9277 static gboolean
9278 is_sr_mono_generic_method (MonoClass *class)
9279 {
9280         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9281 }
9282
9283 static gboolean
9284 is_sr_mono_generic_cmethod (MonoClass *class)
9285 {
9286         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9287 }
9288
9289 gboolean
9290 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9291 {
9292         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9293 }
9294
9295 static gboolean
9296 is_usertype (MonoReflectionType *ref)
9297 {
9298         MonoClass *class = mono_object_class (ref);
9299         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9300 }
9301
9302 static MonoReflectionType*
9303 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9304 {
9305         if (!type || type->type)
9306                 return type;
9307
9308         if (is_usertype (type)) {
9309                 type = mono_reflection_type_get_underlying_system_type (type);
9310                 if (is_usertype (type))
9311                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9312         }
9313
9314         return type;
9315 }
9316 /*
9317  * Encode a value in a custom attribute stream of bytes.
9318  * The value to encode is either supplied as an object in argument val
9319  * (valuetypes are boxed), or as a pointer to the data in the
9320  * argument argval.
9321  * @type represents the type of the value
9322  * @buffer is the start of the buffer
9323  * @p the current position in the buffer
9324  * @buflen contains the size of the buffer and is used to return the new buffer size
9325  * if this needs to be realloced.
9326  * @retbuffer and @retp return the start and the position of the buffer
9327  */
9328 static void
9329 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9330 {
9331         MonoTypeEnum simple_type;
9332         
9333         if ((p-buffer) + 10 >= *buflen) {
9334                 char *newbuf;
9335                 *buflen *= 2;
9336                 newbuf = g_realloc (buffer, *buflen);
9337                 p = newbuf + (p-buffer);
9338                 buffer = newbuf;
9339         }
9340         if (!argval)
9341                 argval = ((char*)arg + sizeof (MonoObject));
9342         simple_type = type->type;
9343 handle_enum:
9344         switch (simple_type) {
9345         case MONO_TYPE_BOOLEAN:
9346         case MONO_TYPE_U1:
9347         case MONO_TYPE_I1:
9348                 *p++ = *argval;
9349                 break;
9350         case MONO_TYPE_CHAR:
9351         case MONO_TYPE_U2:
9352         case MONO_TYPE_I2:
9353                 swap_with_size (p, argval, 2, 1);
9354                 p += 2;
9355                 break;
9356         case MONO_TYPE_U4:
9357         case MONO_TYPE_I4:
9358         case MONO_TYPE_R4:
9359                 swap_with_size (p, argval, 4, 1);
9360                 p += 4;
9361                 break;
9362         case MONO_TYPE_R8:
9363 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9364                 p [0] = argval [4];
9365                 p [1] = argval [5];
9366                 p [2] = argval [6];
9367                 p [3] = argval [7];
9368                 p [4] = argval [0];
9369                 p [5] = argval [1];
9370                 p [6] = argval [2];
9371                 p [7] = argval [3];
9372 #else
9373                 swap_with_size (p, argval, 8, 1);
9374 #endif
9375                 p += 8;
9376                 break;
9377         case MONO_TYPE_U8:
9378         case MONO_TYPE_I8:
9379                 swap_with_size (p, argval, 8, 1);
9380                 p += 8;
9381                 break;
9382         case MONO_TYPE_VALUETYPE:
9383                 if (type->data.klass->enumtype) {
9384                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9385                         goto handle_enum;
9386                 } else {
9387                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9388                 }
9389                 break;
9390         case MONO_TYPE_STRING: {
9391                 char *str;
9392                 guint32 slen;
9393                 if (!arg) {
9394                         *p++ = 0xFF;
9395                         break;
9396                 }
9397                 str = mono_string_to_utf8 ((MonoString*)arg);
9398                 slen = strlen (str);
9399                 if ((p-buffer) + 10 + slen >= *buflen) {
9400                         char *newbuf;
9401                         *buflen *= 2;
9402                         *buflen += slen;
9403                         newbuf = g_realloc (buffer, *buflen);
9404                         p = newbuf + (p-buffer);
9405                         buffer = newbuf;
9406                 }
9407                 mono_metadata_encode_value (slen, p, &p);
9408                 memcpy (p, str, slen);
9409                 p += slen;
9410                 g_free (str);
9411                 break;
9412         }
9413         case MONO_TYPE_CLASS: {
9414                 char *str;
9415                 guint32 slen;
9416                 if (!arg) {
9417                         *p++ = 0xFF;
9418                         break;
9419                 }
9420 handle_type:
9421                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9422                 slen = strlen (str);
9423                 if ((p-buffer) + 10 + slen >= *buflen) {
9424                         char *newbuf;
9425                         *buflen *= 2;
9426                         *buflen += slen;
9427                         newbuf = g_realloc (buffer, *buflen);
9428                         p = newbuf + (p-buffer);
9429                         buffer = newbuf;
9430                 }
9431                 mono_metadata_encode_value (slen, p, &p);
9432                 memcpy (p, str, slen);
9433                 p += slen;
9434                 g_free (str);
9435                 break;
9436         }
9437         case MONO_TYPE_SZARRAY: {
9438                 int len, i;
9439                 MonoClass *eclass, *arg_eclass;
9440
9441                 if (!arg) {
9442                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9443                         break;
9444                 }
9445                 len = mono_array_length ((MonoArray*)arg);
9446                 *p++ = len & 0xff;
9447                 *p++ = (len >> 8) & 0xff;
9448                 *p++ = (len >> 16) & 0xff;
9449                 *p++ = (len >> 24) & 0xff;
9450                 *retp = p;
9451                 *retbuffer = buffer;
9452                 eclass = type->data.klass;
9453                 arg_eclass = mono_object_class (arg)->element_class;
9454
9455                 if (!eclass) {
9456                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9457                         eclass = mono_defaults.object_class;
9458                 }
9459                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9460                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9461                         int elsize = mono_class_array_element_size (arg_eclass);
9462                         for (i = 0; i < len; ++i) {
9463                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9464                                 elptr += elsize;
9465                         }
9466                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9467                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9468                         int elsize = mono_class_array_element_size (eclass);
9469                         for (i = 0; i < len; ++i) {
9470                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9471                                 elptr += elsize;
9472                         }
9473                 } else {
9474                         for (i = 0; i < len; ++i) {
9475                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9476                         }
9477                 }
9478                 break;
9479         }
9480         case MONO_TYPE_OBJECT: {
9481                 MonoClass *klass;
9482                 char *str;
9483                 guint32 slen;
9484
9485                 /*
9486                  * The parameter type is 'object' but the type of the actual
9487                  * argument is not. So we have to add type information to the blob
9488                  * too. This is completely undocumented in the spec.
9489                  */
9490
9491                 if (arg == NULL) {
9492                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9493                         *p++ = 0xFF;
9494                         break;
9495                 }
9496                 
9497                 klass = mono_object_class (arg);
9498
9499                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9500                         *p++ = 0x50;
9501                         goto handle_type;
9502                 } else if (klass->enumtype) {
9503                         *p++ = 0x55;
9504                 } else if (klass == mono_defaults.string_class) {
9505                         simple_type = MONO_TYPE_STRING;
9506                         *p++ = 0x0E;
9507                         goto handle_enum;
9508                 } else if (klass->rank == 1) {
9509                         *p++ = 0x1D;
9510                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9511                                 /* See Partition II, Appendix B3 */
9512                                 *p++ = 0x51;
9513                         else
9514                                 *p++ = klass->element_class->byval_arg.type;
9515                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9516                         break;
9517                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9518                         *p++ = simple_type = klass->byval_arg.type;
9519                         goto handle_enum;
9520                 } else {
9521                         g_error ("unhandled type in custom attr");
9522                 }
9523                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9524                 slen = strlen (str);
9525                 if ((p-buffer) + 10 + slen >= *buflen) {
9526                         char *newbuf;
9527                         *buflen *= 2;
9528                         *buflen += slen;
9529                         newbuf = g_realloc (buffer, *buflen);
9530                         p = newbuf + (p-buffer);
9531                         buffer = newbuf;
9532                 }
9533                 mono_metadata_encode_value (slen, p, &p);
9534                 memcpy (p, str, slen);
9535                 p += slen;
9536                 g_free (str);
9537                 simple_type = mono_class_enum_basetype (klass)->type;
9538                 goto handle_enum;
9539         }
9540         default:
9541                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9542         }
9543         *retp = p;
9544         *retbuffer = buffer;
9545 }
9546
9547 static void
9548 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9549 {
9550         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9551                 char *str = type_get_qualified_name (type, NULL);
9552                 int slen = strlen (str);
9553
9554                 *p++ = 0x55;
9555                 /*
9556                  * This seems to be optional...
9557                  * *p++ = 0x80;
9558                  */
9559                 mono_metadata_encode_value (slen, p, &p);
9560                 memcpy (p, str, slen);
9561                 p += slen;
9562                 g_free (str);
9563         } else if (type->type == MONO_TYPE_OBJECT) {
9564                 *p++ = 0x51;
9565         } else if (type->type == MONO_TYPE_CLASS) {
9566                 /* it should be a type: encode_cattr_value () has the check */
9567                 *p++ = 0x50;
9568         } else {
9569                 mono_metadata_encode_value (type->type, p, &p);
9570                 if (type->type == MONO_TYPE_SZARRAY)
9571                         /* See the examples in Partition VI, Annex B */
9572                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9573         }
9574
9575         *retp = p;
9576 }
9577
9578 #ifndef DISABLE_REFLECTION_EMIT
9579 static void
9580 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9581 {
9582         int len;
9583         /* Preallocate a large enough buffer */
9584         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9585                 char *str = type_get_qualified_name (type, NULL);
9586                 len = strlen (str);
9587                 g_free (str);
9588         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9589                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9590                 len = strlen (str);
9591                 g_free (str);
9592         } else {
9593                 len = 0;
9594         }
9595         len += strlen (name);
9596
9597         if ((p-buffer) + 20 + len >= *buflen) {
9598                 char *newbuf;
9599                 *buflen *= 2;
9600                 *buflen += len;
9601                 newbuf = g_realloc (buffer, *buflen);
9602                 p = newbuf + (p-buffer);
9603                 buffer = newbuf;
9604         }
9605
9606         encode_field_or_prop_type (type, p, &p);
9607
9608         len = strlen (name);
9609         mono_metadata_encode_value (len, p, &p);
9610         memcpy (p, name, len);
9611         p += len;
9612         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9613         *retp = p;
9614         *retbuffer = buffer;
9615 }
9616
9617 /*
9618  * mono_reflection_get_custom_attrs_blob:
9619  * @ctor: custom attribute constructor
9620  * @ctorArgs: arguments o the constructor
9621  * @properties:
9622  * @propValues:
9623  * @fields:
9624  * @fieldValues:
9625  * 
9626  * Creates the blob of data that needs to be saved in the metadata and that represents
9627  * the custom attributed described by @ctor, @ctorArgs etc.
9628  * Returns: a Byte array representing the blob of data.
9629  */
9630 MonoArray*
9631 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9632 {
9633         MonoArray *result;
9634         MonoMethodSignature *sig;
9635         MonoObject *arg;
9636         char *buffer, *p;
9637         guint32 buflen, i;
9638
9639         MONO_ARCH_SAVE_REGS;
9640
9641         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9642                 /* sig is freed later so allocate it in the heap */
9643                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9644         } else {
9645                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9646         }
9647
9648         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9649         buflen = 256;
9650         p = buffer = g_malloc (buflen);
9651         /* write the prolog */
9652         *p++ = 1;
9653         *p++ = 0;
9654         for (i = 0; i < sig->param_count; ++i) {
9655                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9656                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9657         }
9658         i = 0;
9659         if (properties)
9660                 i += mono_array_length (properties);
9661         if (fields)
9662                 i += mono_array_length (fields);
9663         *p++ = i & 0xff;
9664         *p++ = (i >> 8) & 0xff;
9665         if (properties) {
9666                 MonoObject *prop;
9667                 for (i = 0; i < mono_array_length (properties); ++i) {
9668                         MonoType *ptype;
9669                         char *pname;
9670
9671                         prop = mono_array_get (properties, gpointer, i);
9672                         get_prop_name_and_type (prop, &pname, &ptype);
9673                         *p++ = 0x54; /* PROPERTY signature */
9674                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9675                         g_free (pname);
9676                 }
9677         }
9678
9679         if (fields) {
9680                 MonoObject *field;
9681                 for (i = 0; i < mono_array_length (fields); ++i) {
9682                         MonoType *ftype;
9683                         char *fname;
9684
9685                         field = mono_array_get (fields, gpointer, i);
9686                         get_field_name_and_type (field, &fname, &ftype);
9687                         *p++ = 0x53; /* FIELD signature */
9688                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9689                         g_free (fname);
9690                 }
9691         }
9692
9693         g_assert (p - buffer <= buflen);
9694         buflen = p - buffer;
9695         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9696         p = mono_array_addr (result, char, 0);
9697         memcpy (p, buffer, buflen);
9698         g_free (buffer);
9699         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9700                 g_free (sig);
9701         return result;
9702 }
9703
9704 /*
9705  * mono_reflection_setup_internal_class:
9706  * @tb: a TypeBuilder object
9707  *
9708  * Creates a MonoClass that represents the TypeBuilder.
9709  * This is a trick that lets us simplify a lot of reflection code
9710  * (and will allow us to support Build and Run assemblies easier).
9711  */
9712 void
9713 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9714 {
9715         MonoError error;
9716         MonoClass *klass, *parent;
9717
9718         MONO_ARCH_SAVE_REGS;
9719
9720         RESOLVE_TYPE (tb->parent);
9721
9722         mono_loader_lock ();
9723
9724         if (tb->parent) {
9725                 /* check so we can compile corlib correctly */
9726                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9727                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9728                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9729                 } else {
9730                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9731                 }
9732         } else {
9733                 parent = NULL;
9734         }
9735         
9736         /* the type has already being created: it means we just have to change the parent */
9737         if (tb->type.type) {
9738                 klass = mono_class_from_mono_type (tb->type.type);
9739                 klass->parent = NULL;
9740                 /* fool mono_class_setup_parent */
9741                 klass->supertypes = NULL;
9742                 mono_class_setup_parent (klass, parent);
9743                 mono_class_setup_mono_type (klass);
9744                 mono_loader_unlock ();
9745                 return;
9746         }
9747
9748         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9749
9750         klass->image = &tb->module->dynamic_image->image;
9751
9752         klass->inited = 1; /* we lie to the runtime */
9753         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9754         if (!mono_error_ok (&error))
9755                 goto failure;
9756         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9757         if (!mono_error_ok (&error))
9758                 goto failure;
9759         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9760         klass->flags = tb->attrs;
9761         
9762         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9763
9764         klass->element_class = klass;
9765
9766         if (mono_class_get_ref_info (klass) == NULL) {
9767
9768                 mono_class_set_ref_info (klass, tb);
9769
9770                 /* Put into cache so mono_class_get () will find it.
9771                 Skip nested types as those should not be available on the global scope. */
9772                 if (!tb->nesting_type) {
9773                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9774                 } else {
9775                         klass->image->reflection_info_unregister_classes =
9776                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9777                 }
9778         } else {
9779                 g_assert (mono_class_get_ref_info (klass) == tb);
9780         }
9781
9782         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9783                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9784
9785         if (parent != NULL) {
9786                 mono_class_setup_parent (klass, parent);
9787         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9788                 const char *old_n = klass->name;
9789                 /* trick to get relative numbering right when compiling corlib */
9790                 klass->name = "BuildingObject";
9791                 mono_class_setup_parent (klass, mono_defaults.object_class);
9792                 klass->name = old_n;
9793         }
9794
9795         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9796                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9797                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9798                 klass->instance_size = sizeof (MonoObject);
9799                 klass->size_inited = 1;
9800                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9801         }
9802
9803         mono_class_setup_mono_type (klass);
9804
9805         mono_class_setup_supertypes (klass);
9806
9807         /*
9808          * FIXME: handle interfaces.
9809          */
9810
9811         tb->type.type = &klass->byval_arg;
9812
9813         if (tb->nesting_type) {
9814                 g_assert (tb->nesting_type->type);
9815                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9816         }
9817
9818         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9819
9820         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9821         
9822         mono_loader_unlock ();
9823         return;
9824
9825 failure:
9826         mono_loader_unlock ();
9827         mono_error_raise_exception (&error);
9828 }
9829
9830 /*
9831  * mono_reflection_setup_generic_class:
9832  * @tb: a TypeBuilder object
9833  *
9834  * Setup the generic class before adding the first generic parameter.
9835  */
9836 void
9837 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9838 {
9839 }
9840
9841 /*
9842  * mono_reflection_create_generic_class:
9843  * @tb: a TypeBuilder object
9844  *
9845  * Creates the generic class after all generic parameters have been added.
9846  */
9847 void
9848 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9849 {
9850         MonoClass *klass;
9851         int count, i;
9852
9853         MONO_ARCH_SAVE_REGS;
9854
9855         klass = mono_class_from_mono_type (tb->type.type);
9856
9857         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9858
9859         if (klass->generic_container || (count == 0))
9860                 return;
9861
9862         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9863
9864         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9865
9866         klass->generic_container->owner.klass = klass;
9867         klass->generic_container->type_argc = count;
9868         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9869
9870         klass->is_generic = 1;
9871
9872         for (i = 0; i < count; i++) {
9873                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9874                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9875                 klass->generic_container->type_params [i] = *param;
9876                 /*Make sure we are a diferent type instance */
9877                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9878                 klass->generic_container->type_params [i].info.pklass = NULL;
9879                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9880
9881                 g_assert (klass->generic_container->type_params [i].param.owner);
9882         }
9883
9884         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9885 }
9886
9887 /*
9888  * mono_reflection_create_internal_class:
9889  * @tb: a TypeBuilder object
9890  *
9891  * Actually create the MonoClass that is associated with the TypeBuilder.
9892  */
9893 void
9894 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9895 {
9896         MonoClass *klass;
9897
9898         MONO_ARCH_SAVE_REGS;
9899
9900         klass = mono_class_from_mono_type (tb->type.type);
9901
9902         mono_loader_lock ();
9903         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9904                 MonoReflectionFieldBuilder *fb;
9905                 MonoClass *ec;
9906                 MonoType *enum_basetype;
9907
9908                 g_assert (tb->fields != NULL);
9909                 g_assert (mono_array_length (tb->fields) >= 1);
9910
9911                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9912
9913                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9914                         mono_loader_unlock ();
9915                         return;
9916                 }
9917
9918                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9919                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9920                 if (!klass->element_class)
9921                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9922
9923                 /*
9924                  * get the element_class from the current corlib.
9925                  */
9926                 ec = default_class_from_mono_type (enum_basetype);
9927                 klass->instance_size = ec->instance_size;
9928                 klass->size_inited = 1;
9929                 /* 
9930                  * this is almost safe to do with enums and it's needed to be able
9931                  * to create objects of the enum type (for use in SetConstant).
9932                  */
9933                 /* FIXME: Does this mean enums can't have method overrides ? */
9934                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9935         }
9936         mono_loader_unlock ();
9937 }
9938
9939 static MonoMarshalSpec*
9940 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9941                                                                 MonoReflectionMarshal *minfo)
9942 {
9943         MonoMarshalSpec *res;
9944
9945         res = image_g_new0 (image, MonoMarshalSpec, 1);
9946         res->native = minfo->type;
9947
9948         switch (minfo->type) {
9949         case MONO_NATIVE_LPARRAY:
9950                 res->data.array_data.elem_type = minfo->eltype;
9951                 if (minfo->has_size) {
9952                         res->data.array_data.param_num = minfo->param_num;
9953                         res->data.array_data.num_elem = minfo->count;
9954                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9955                 }
9956                 else {
9957                         res->data.array_data.param_num = -1;
9958                         res->data.array_data.num_elem = -1;
9959                         res->data.array_data.elem_mult = -1;
9960                 }
9961                 break;
9962
9963         case MONO_NATIVE_BYVALTSTR:
9964         case MONO_NATIVE_BYVALARRAY:
9965                 res->data.array_data.num_elem = minfo->count;
9966                 break;
9967
9968         case MONO_NATIVE_CUSTOM:
9969                 if (minfo->marshaltyperef)
9970                         res->data.custom_data.custom_name =
9971                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9972                 if (minfo->mcookie)
9973                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9974                 break;
9975
9976         default:
9977                 break;
9978         }
9979
9980         return res;
9981 }
9982 #endif /* !DISABLE_REFLECTION_EMIT */
9983
9984 MonoReflectionMarshal*
9985 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9986                                                                                    MonoMarshalSpec *spec)
9987 {
9988         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9989         MonoReflectionMarshal *minfo;
9990         MonoType *mtype;
9991
9992         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9993                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9994                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9995                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9996         }
9997
9998         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9999         minfo->type = spec->native;
10000
10001         switch (minfo->type) {
10002         case MONO_NATIVE_LPARRAY:
10003                 minfo->eltype = spec->data.array_data.elem_type;
10004                 minfo->count = spec->data.array_data.num_elem;
10005                 minfo->param_num = spec->data.array_data.param_num;
10006                 break;
10007
10008         case MONO_NATIVE_BYVALTSTR:
10009         case MONO_NATIVE_BYVALARRAY:
10010                 minfo->count = spec->data.array_data.num_elem;
10011                 break;
10012
10013         case MONO_NATIVE_CUSTOM:
10014                 if (spec->data.custom_data.custom_name) {
10015                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10016                         if (mtype)
10017                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10018
10019                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10020                 }
10021                 if (spec->data.custom_data.cookie)
10022                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10023                 break;
10024
10025         default:
10026                 break;
10027         }
10028
10029         return minfo;
10030 }
10031
10032 #ifndef DISABLE_REFLECTION_EMIT
10033 static MonoMethod*
10034 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10035                                          ReflectionMethodBuilder *rmb,
10036                                          MonoMethodSignature *sig)
10037 {
10038         MonoError error;
10039         MonoMethod *m;
10040         MonoMethodWrapper *wrapperm;
10041         MonoMarshalSpec **specs;
10042         MonoReflectionMethodAux *method_aux;
10043         MonoImage *image;
10044         gboolean dynamic;
10045         int i;
10046
10047         mono_error_init (&error);
10048         /*
10049          * Methods created using a MethodBuilder should have their memory allocated
10050          * inside the image mempool, while dynamic methods should have their memory
10051          * malloc'd.
10052          */
10053         dynamic = rmb->refs != NULL;
10054         image = dynamic ? NULL : klass->image;
10055
10056         if (!dynamic)
10057                 g_assert (!klass->generic_class);
10058
10059         mono_loader_lock ();
10060
10061         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10062                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10063                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10064         else
10065                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10066
10067         wrapperm = (MonoMethodWrapper*)m;
10068
10069         m->dynamic = dynamic;
10070         m->slot = -1;
10071         m->flags = rmb->attrs;
10072         m->iflags = rmb->iattrs;
10073         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10074         m->klass = klass;
10075         m->signature = sig;
10076         m->sre_method = TRUE;
10077         m->skip_visibility = rmb->skip_visibility;
10078         if (rmb->table_idx)
10079                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10080
10081         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10082                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10083                         m->string_ctor = 1;
10084
10085                 m->signature->pinvoke = 1;
10086         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10087                 m->signature->pinvoke = 1;
10088
10089                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10090
10091                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10092                 g_assert (mono_error_ok (&error));
10093                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10094                 g_assert (mono_error_ok (&error));
10095                 
10096                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10097
10098                 if (klass->image->dynamic)
10099                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10100
10101                 mono_loader_unlock ();
10102
10103                 return m;
10104         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10105                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10106                 MonoMethodHeader *header;
10107                 guint32 code_size;
10108                 gint32 max_stack, i;
10109                 gint32 num_locals = 0;
10110                 gint32 num_clauses = 0;
10111                 guint8 *code;
10112
10113                 if (rmb->ilgen) {
10114                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10115                         code_size = rmb->ilgen->code_len;
10116                         max_stack = rmb->ilgen->max_stack;
10117                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10118                         if (rmb->ilgen->ex_handlers)
10119                                 num_clauses = method_count_clauses (rmb->ilgen);
10120                 } else {
10121                         if (rmb->code) {
10122                                 code = mono_array_addr (rmb->code, guint8, 0);
10123                                 code_size = mono_array_length (rmb->code);
10124                                 /* we probably need to run a verifier on the code... */
10125                                 max_stack = 8; 
10126                         }
10127                         else {
10128                                 code = NULL;
10129                                 code_size = 0;
10130                                 max_stack = 8;
10131                         }
10132                 }
10133
10134                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10135                 header->code_size = code_size;
10136                 header->code = image_g_malloc (image, code_size);
10137                 memcpy ((char*)header->code, code, code_size);
10138                 header->max_stack = max_stack;
10139                 header->init_locals = rmb->init_locals;
10140                 header->num_locals = num_locals;
10141
10142                 for (i = 0; i < num_locals; ++i) {
10143                         MonoReflectionLocalBuilder *lb = 
10144                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10145
10146                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10147                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10148                 }
10149
10150                 header->num_clauses = num_clauses;
10151                 if (num_clauses) {
10152                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10153                                  rmb->ilgen, num_clauses);
10154                 }
10155
10156                 wrapperm->header = header;
10157         }
10158
10159         if (rmb->generic_params) {
10160                 int count = mono_array_length (rmb->generic_params);
10161                 MonoGenericContainer *container = rmb->generic_container;
10162
10163                 g_assert (container);
10164
10165                 container->type_argc = count;
10166                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10167                 container->owner.method = m;
10168
10169                 m->is_generic = TRUE;
10170                 mono_method_set_generic_container (m, container);
10171
10172                 for (i = 0; i < count; i++) {
10173                         MonoReflectionGenericParam *gp =
10174                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10175                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10176                         container->type_params [i] = *param;
10177                 }
10178
10179                 /*
10180                  * The method signature might have pointers to generic parameters that belong to other methods.
10181                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10182                  * generic parameters.
10183                  */
10184                 for (i = 0; i < m->signature->param_count; ++i) {
10185                         MonoType *t = m->signature->params [i];
10186                         if (t->type == MONO_TYPE_MVAR) {
10187                                 MonoGenericParam *gparam =  t->data.generic_param;
10188                                 if (gparam->num < count) {
10189                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10190                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10191                                 }
10192
10193                         }
10194                 }
10195
10196                 if (klass->generic_container) {
10197                         container->parent = klass->generic_container;
10198                         container->context.class_inst = klass->generic_container->context.class_inst;
10199                 }
10200                 container->context.method_inst = mono_get_shared_generic_inst (container);
10201         }
10202
10203         if (rmb->refs) {
10204                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10205                 int i;
10206                 void **data;
10207
10208                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10209
10210                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10211                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10212                 for (i = 0; i < rmb->nrefs; ++i)
10213                         data [i + 1] = rmb->refs [i];
10214         }
10215
10216         method_aux = NULL;
10217
10218         /* Parameter info */
10219         if (rmb->pinfo) {
10220                 if (!method_aux)
10221                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10222                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10223                 for (i = 0; i <= m->signature->param_count; ++i) {
10224                         MonoReflectionParamBuilder *pb;
10225                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10226                                 if ((i > 0) && (pb->attrs)) {
10227                                         /* Make a copy since it might point to a shared type structure */
10228                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10229                                         m->signature->params [i - 1]->attrs = pb->attrs;
10230                                 }
10231
10232                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10233                                         MonoDynamicImage *assembly;
10234                                         guint32 idx, def_type, len;
10235                                         char *p;
10236                                         const char *p2;
10237
10238                                         if (!method_aux->param_defaults) {
10239                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10240                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10241                                         }
10242                                         assembly = (MonoDynamicImage*)klass->image;
10243                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10244                                         /* Copy the data from the blob since it might get realloc-ed */
10245                                         p = assembly->blob.data + idx;
10246                                         len = mono_metadata_decode_blob_size (p, &p2);
10247                                         len += p2 - p;
10248                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10249                                         method_aux->param_default_types [i] = def_type;
10250                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10251                                 }
10252
10253                                 if (pb->name) {
10254                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10255                                         g_assert (mono_error_ok (&error));
10256                                 }
10257                                 if (pb->cattrs) {
10258                                         if (!method_aux->param_cattr)
10259                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10260                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10261                                 }
10262                         }
10263                 }
10264         }
10265
10266         /* Parameter marshalling */
10267         specs = NULL;
10268         if (rmb->pinfo)         
10269                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10270                         MonoReflectionParamBuilder *pb;
10271                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10272                                 if (pb->marshal_info) {
10273                                         if (specs == NULL)
10274                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10275                                         specs [pb->position] = 
10276                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10277                                 }
10278                         }
10279                 }
10280         if (specs != NULL) {
10281                 if (!method_aux)
10282                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10283                 method_aux->param_marshall = specs;
10284         }
10285
10286         if (klass->image->dynamic && method_aux)
10287                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10288
10289         mono_loader_unlock ();
10290
10291         return m;
10292 }       
10293
10294 static MonoMethod*
10295 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10296 {
10297         ReflectionMethodBuilder rmb;
10298         MonoMethodSignature *sig;
10299
10300         mono_loader_lock ();
10301         sig = ctor_builder_to_signature (klass->image, mb);
10302         mono_loader_unlock ();
10303
10304         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10305
10306         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10307         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10308
10309         /* If we are in a generic class, we might be called multiple times from inflate_method */
10310         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10311                 /* ilgen is no longer needed */
10312                 mb->ilgen = NULL;
10313         }
10314
10315         return mb->mhandle;
10316 }
10317
10318 static MonoMethod*
10319 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10320 {
10321         ReflectionMethodBuilder rmb;
10322         MonoMethodSignature *sig;
10323
10324         mono_loader_lock ();
10325         sig = method_builder_to_signature (klass->image, mb);
10326         mono_loader_unlock ();
10327
10328         reflection_methodbuilder_from_method_builder (&rmb, mb);
10329
10330         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10331         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10332
10333         /* If we are in a generic class, we might be called multiple times from inflate_method */
10334         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10335                 /* ilgen is no longer needed */
10336                 mb->ilgen = NULL;
10337         }
10338         return mb->mhandle;
10339 }
10340
10341 static MonoClassField*
10342 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10343 {
10344         MonoClassField *field;
10345         MonoType *custom;
10346         MonoError error;
10347
10348         field = g_new0 (MonoClassField, 1);
10349
10350         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10351         g_assert (mono_error_ok (&error));
10352         if (fb->attrs || fb->modreq || fb->modopt) {
10353                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10354                 field->type->attrs = fb->attrs;
10355
10356                 g_assert (klass->image->dynamic);
10357                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10358                 g_free (field->type);
10359                 field->type = mono_metadata_type_dup (klass->image, custom);
10360                 g_free (custom);
10361         } else {
10362                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10363         }
10364         if (fb->offset != -1)
10365                 field->offset = fb->offset;
10366         field->parent = klass;
10367         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10368
10369         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10370
10371         return field;
10372 }
10373 #endif
10374
10375 MonoType*
10376 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10377 {
10378         MonoClass *klass;
10379         MonoReflectionTypeBuilder *tb = NULL;
10380         gboolean is_dynamic = FALSE;
10381         MonoDomain *domain;
10382         MonoClass *geninst;
10383
10384         mono_loader_lock ();
10385
10386         domain = mono_object_domain (type);
10387
10388         if (is_sre_type_builder (mono_object_class (type))) {
10389                 tb = (MonoReflectionTypeBuilder *) type;
10390
10391                 is_dynamic = TRUE;
10392         } else if (is_sre_generic_instance (mono_object_class (type))) {
10393                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10394                 MonoReflectionType *gtd = rgi->generic_type;
10395
10396                 if (is_sre_type_builder (mono_object_class (gtd))) {
10397                         tb = (MonoReflectionTypeBuilder *)gtd;
10398                         is_dynamic = TRUE;
10399                 }
10400         }
10401
10402         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10403         if (tb && tb->generic_container)
10404                 mono_reflection_create_generic_class (tb);
10405
10406         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10407         if (!klass->generic_container) {
10408                 mono_loader_unlock ();
10409                 return NULL;
10410         }
10411
10412         if (klass->wastypebuilder) {
10413                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10414
10415                 is_dynamic = TRUE;
10416         }
10417
10418         mono_loader_unlock ();
10419
10420         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10421
10422         return &geninst->byval_arg;
10423 }
10424
10425 MonoClass*
10426 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10427 {
10428         MonoGenericClass *gclass;
10429         MonoGenericInst *inst;
10430
10431         g_assert (klass->generic_container);
10432
10433         inst = mono_metadata_get_generic_inst (type_argc, types);
10434         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10435
10436         return mono_generic_class_get_class (gclass);
10437 }
10438
10439 MonoReflectionMethod*
10440 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10441 {
10442         MonoClass *klass;
10443         MonoMethod *method, *inflated;
10444         MonoMethodInflated *imethod;
10445         MonoGenericContext tmp_context;
10446         MonoGenericInst *ginst;
10447         MonoType **type_argv;
10448         int count, i;
10449
10450         MONO_ARCH_SAVE_REGS;
10451
10452         /*FIXME but this no longer should happen*/
10453         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10454 #ifndef DISABLE_REFLECTION_EMIT
10455                 MonoReflectionMethodBuilder *mb = NULL;
10456                 MonoReflectionTypeBuilder *tb;
10457                 MonoClass *klass;
10458
10459                 mb = (MonoReflectionMethodBuilder *) rmethod;
10460                 tb = (MonoReflectionTypeBuilder *) mb->type;
10461                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10462
10463                 method = methodbuilder_to_mono_method (klass, mb);
10464 #else
10465                 g_assert_not_reached ();
10466                 method = NULL;
10467 #endif
10468         } else {
10469                 method = rmethod->method;
10470         }
10471
10472         klass = method->klass;
10473
10474         if (method->is_inflated)
10475                 method = ((MonoMethodInflated *) method)->declaring;
10476
10477         count = mono_method_signature (method)->generic_param_count;
10478         if (count != mono_array_length (types))
10479                 return NULL;
10480
10481         type_argv = g_new0 (MonoType *, count);
10482         for (i = 0; i < count; i++) {
10483                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10484                 type_argv [i] = mono_reflection_type_get_handle (garg);
10485         }
10486         ginst = mono_metadata_get_generic_inst (count, type_argv);
10487         g_free (type_argv);
10488
10489         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10490         tmp_context.method_inst = ginst;
10491
10492         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10493         imethod = (MonoMethodInflated *) inflated;
10494
10495         /*FIXME but I think this is no longer necessary*/
10496         if (method->klass->image->dynamic) {
10497                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10498                 /*
10499                  * This table maps metadata structures representing inflated methods/fields
10500                  * to the reflection objects representing their generic definitions.
10501                  */
10502                 mono_loader_lock ();
10503                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10504                 mono_loader_unlock ();
10505         }
10506
10507         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10508                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10509         
10510         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10511 }
10512
10513 #ifndef DISABLE_REFLECTION_EMIT
10514
10515 static MonoMethod *
10516 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10517 {
10518         MonoMethodInflated *imethod;
10519         MonoGenericContext *context;
10520         int i;
10521
10522         /*
10523          * With generic code sharing the klass might not be inflated.
10524          * This can happen because classes inflated with their own
10525          * type arguments are "normalized" to the uninflated class.
10526          */
10527         if (!klass->generic_class)
10528                 return method;
10529
10530         context = mono_class_get_context (klass);
10531
10532         if (klass->method.count && klass->methods) {
10533                 /* Find the already created inflated method */
10534                 for (i = 0; i < klass->method.count; ++i) {
10535                         g_assert (klass->methods [i]->is_inflated);
10536                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10537                                 break;
10538                 }
10539                 g_assert (i < klass->method.count);
10540                 imethod = (MonoMethodInflated*)klass->methods [i];
10541         } else {
10542                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10543         }
10544
10545         if (method->is_generic && method->klass->image->dynamic) {
10546                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10547
10548                 mono_loader_lock ();
10549                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10550                 mono_loader_unlock ();
10551         }
10552         return (MonoMethod *) imethod;
10553 }
10554
10555 static MonoMethod *
10556 inflate_method (MonoReflectionType *type, MonoObject *obj)
10557 {
10558         MonoMethod *method;
10559         MonoClass *gklass;
10560
10561         MonoClass *type_class = mono_object_class (type);
10562
10563         if (is_sre_generic_instance (type_class)) {
10564                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10565                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10566         } else if (is_sre_type_builder (type_class)) {
10567                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10568         } else if (type->type) {
10569                 gklass = mono_class_from_mono_type (type->type);
10570                 gklass = mono_class_get_generic_type_definition (gklass);
10571         } else {
10572                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10573         }
10574
10575         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10576                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10577                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10578                 else
10579                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10580         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10581                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10582         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10583                 method = ((MonoReflectionMethod *) obj)->method;
10584         else {
10585                 method = NULL; /* prevent compiler warning */
10586                 g_error ("can't handle type %s", obj->vtable->klass->name);
10587         }
10588
10589         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10590 }
10591
10592 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10593 void
10594 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10595                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10596                                           MonoArray *events)
10597 {
10598         MonoGenericClass *gclass;
10599         MonoDynamicGenericClass *dgclass;
10600         MonoClass *klass, *gklass;
10601         MonoType *gtype;
10602         int i;
10603
10604         MONO_ARCH_SAVE_REGS;
10605
10606         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10607         klass = mono_class_from_mono_type (gtype);
10608         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10609         gclass = gtype->data.generic_class;
10610
10611         if (!gclass->is_dynamic)
10612                 return;
10613
10614         dgclass = (MonoDynamicGenericClass *) gclass;
10615
10616         if (dgclass->initialized)
10617                 return;
10618
10619         gklass = gclass->container_class;
10620         mono_class_init (gklass);
10621
10622         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10623
10624         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10625         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10626         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10627
10628         for (i = 0; i < dgclass->count_fields; i++) {
10629                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10630                 MonoClassField *field, *inflated_field = NULL;
10631
10632                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10633                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10634                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10635                         field = ((MonoReflectionField *) obj)->field;
10636                 else {
10637                         field = NULL; /* prevent compiler warning */
10638                         g_assert_not_reached ();
10639                 }
10640
10641                 dgclass->fields [i] = *field;
10642                 dgclass->fields [i].parent = klass;
10643                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10644                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10645                 dgclass->field_generic_types [i] = field->type;
10646                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10647                 dgclass->field_objects [i] = obj;
10648
10649                 if (inflated_field) {
10650                         g_free (inflated_field);
10651                 } else {
10652                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10653                 }
10654         }
10655
10656         dgclass->initialized = TRUE;
10657 }
10658
10659 void
10660 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10661 {
10662         MonoDynamicGenericClass *dgclass;
10663         int i;
10664
10665         g_assert (gclass->is_dynamic);
10666
10667         dgclass = (MonoDynamicGenericClass *)gclass;
10668
10669         for (i = 0; i < dgclass->count_fields; ++i) {
10670                 MonoClassField *field = dgclass->fields + i;
10671                 mono_metadata_free_type (field->type);
10672                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10673         }
10674 }
10675
10676 static void
10677 fix_partial_generic_class (MonoClass *klass)
10678 {
10679         MonoClass *gklass = klass->generic_class->container_class;
10680         MonoDynamicGenericClass *dgclass;
10681         int i;
10682
10683         if (klass->wastypebuilder)
10684                 return;
10685
10686         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10687         if (klass->parent != gklass->parent) {
10688                 MonoError error;
10689                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10690                 if (mono_error_ok (&error)) {
10691                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10692                         mono_metadata_free_type (parent_type);
10693                         if (parent != klass->parent) {
10694                                 /*fool mono_class_setup_parent*/
10695                                 klass->supertypes = NULL;
10696                                 mono_class_setup_parent (klass, parent);
10697                         }
10698                 } else {
10699                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10700                         mono_error_cleanup (&error);
10701                         if (gklass->wastypebuilder)
10702                                 klass->wastypebuilder = TRUE;
10703                         return;
10704                 }
10705         }
10706
10707         if (!dgclass->initialized)
10708                 return;
10709
10710         if (klass->method.count != gklass->method.count) {
10711                 klass->method.count = gklass->method.count;
10712                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10713
10714                 for (i = 0; i < klass->method.count; i++) {
10715                         klass->methods [i] = mono_class_inflate_generic_method_full (
10716                                 gklass->methods [i], klass, mono_class_get_context (klass));
10717                 }
10718         }
10719
10720         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10721                 klass->interface_count = gklass->interface_count;
10722                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10723                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10724
10725                 for (i = 0; i < gklass->interface_count; ++i) {
10726                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10727                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10728                         mono_metadata_free_type (iface_type);
10729
10730                         ensure_runtime_vtable (klass->interfaces [i]);
10731                 }
10732                 klass->interfaces_inited = 1;
10733         }
10734
10735         if (klass->field.count != gklass->field.count) {
10736                 klass->field.count = gklass->field.count;
10737                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10738
10739                 for (i = 0; i < klass->field.count; i++) {
10740                         klass->fields [i] = gklass->fields [i];
10741                         klass->fields [i].parent = klass;
10742                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10743                 }
10744         }
10745
10746         /*We can only finish with this klass once it's parent has as well*/
10747         if (gklass->wastypebuilder)
10748                 klass->wastypebuilder = TRUE;
10749         return;
10750 }
10751
10752 static void
10753 ensure_generic_class_runtime_vtable (MonoClass *klass)
10754 {
10755         MonoClass *gklass = klass->generic_class->container_class;
10756
10757         ensure_runtime_vtable (gklass); 
10758
10759         fix_partial_generic_class (klass);
10760 }
10761
10762 static void
10763 ensure_runtime_vtable (MonoClass *klass)
10764 {
10765         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10766         int i, num, j;
10767
10768         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10769                 return;
10770         if (klass->parent)
10771                 ensure_runtime_vtable (klass->parent);
10772
10773         if (tb) {
10774                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10775                 num += tb->num_methods;
10776                 klass->method.count = num;
10777                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10778                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10779                 for (i = 0; i < num; ++i)
10780                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10781                 num = tb->num_methods;
10782                 j = i;
10783                 for (i = 0; i < num; ++i)
10784                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10785         
10786                 if (tb->interfaces) {
10787                         klass->interface_count = mono_array_length (tb->interfaces);
10788                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10789                         for (i = 0; i < klass->interface_count; ++i) {
10790                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10791                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10792                                 ensure_runtime_vtable (klass->interfaces [i]);
10793                         }
10794                         klass->interfaces_inited = 1;
10795                 }
10796         } else if (klass->generic_class){
10797                 ensure_generic_class_runtime_vtable (klass);
10798         }
10799
10800         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10801                 int slot_num = 0;
10802                 for (i = 0; i < klass->method.count; ++i) {
10803                         MonoMethod *im = klass->methods [i];
10804                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10805                                 im->slot = slot_num++;
10806                 }
10807                 
10808                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10809                 mono_class_setup_interface_offsets (klass);
10810                 mono_class_setup_interface_id (klass);
10811         }
10812
10813         /*
10814          * The generic vtable is needed even if image->run is not set since some
10815          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10816          * method->slot being defined.
10817          */
10818
10819         /* 
10820          * tb->methods could not be freed since it is used for determining 
10821          * overrides during dynamic vtable construction.
10822          */
10823 }
10824
10825 static MonoMethod*
10826 mono_reflection_method_get_handle (MonoObject *method)
10827 {
10828         MonoClass *class = mono_object_class (method);
10829         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10830                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10831                 return sr_method->method;
10832         }
10833         if (is_sre_method_builder (class)) {
10834                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10835                 return mb->mhandle;
10836         }
10837         if (is_sre_method_on_tb_inst (class)) {
10838                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10839                 MonoMethod *result;
10840                 /*FIXME move this to a proper method and unify with resolve_object*/
10841                 if (m->method_args) {
10842                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10843                 } else {
10844                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10845                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10846                         MonoMethod *mono_method;
10847
10848                         if (is_sre_method_builder (mono_object_class (m->mb)))
10849                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10850                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10851                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10852                         else
10853                                 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)));
10854
10855                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10856                 }
10857                 return result;
10858         }
10859
10860         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10861         return NULL;
10862 }
10863
10864 void
10865 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10866 {
10867         MonoReflectionTypeBuilder *tb;
10868         int i, onum;
10869
10870         *overrides = NULL;
10871         *num_overrides = 0;
10872
10873         g_assert (klass->image->dynamic);
10874
10875         if (!mono_class_get_ref_info (klass))
10876                 return;
10877
10878         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10879
10880         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10881
10882         onum = 0;
10883         if (tb->methods) {
10884                 for (i = 0; i < tb->num_methods; ++i) {
10885                         MonoReflectionMethodBuilder *mb = 
10886                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10887                         if (mb->override_method)
10888                                 onum ++;
10889                 }
10890         }
10891
10892         if (onum) {
10893                 *overrides = g_new0 (MonoMethod*, onum * 2);
10894
10895                 onum = 0;
10896                 for (i = 0; i < tb->num_methods; ++i) {
10897                         MonoReflectionMethodBuilder *mb = 
10898                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10899                         if (mb->override_method) {
10900                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10901                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10902
10903                                 g_assert (mb->mhandle);
10904
10905                                 onum ++;
10906                         }
10907                 }
10908         }
10909
10910         *num_overrides = onum;
10911 }
10912
10913 static void
10914 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10915 {
10916         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10917         MonoReflectionFieldBuilder *fb;
10918         MonoClassField *field;
10919         MonoImage *image = klass->image;
10920         const char *p, *p2;
10921         int i;
10922         guint32 len, idx, real_size = 0;
10923
10924         klass->field.count = tb->num_fields;
10925         klass->field.first = 0;
10926
10927         mono_error_init (error);
10928
10929         if (tb->class_size) {
10930                 if ((tb->packing_size & 0xfffffff0) != 0) {
10931                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10932                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10933                         return;
10934                 }
10935                 klass->packing_size = tb->packing_size;
10936                 real_size = klass->instance_size + tb->class_size;
10937         }
10938
10939         if (!klass->field.count) {
10940                 klass->instance_size = MAX (klass->instance_size, real_size);
10941                 return;
10942         }
10943         
10944         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10945         mono_class_alloc_ext (klass);
10946         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10947         /*
10948         This is, guess what, a hack.
10949         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10950         On the static path no field class is resolved, only types are built. This is the right thing to do
10951         but we suck.
10952         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10953         */
10954         klass->size_inited = 1;
10955
10956         for (i = 0; i < klass->field.count; ++i) {
10957                 MonoArray *rva_data;
10958                 fb = mono_array_get (tb->fields, gpointer, i);
10959                 field = &klass->fields [i];
10960                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10961                 if (!mono_error_ok (error))
10962                         return;
10963                 if (fb->attrs) {
10964                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10965                         field->type->attrs = fb->attrs;
10966                 } else {
10967                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10968                 }
10969
10970                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
10971                         char *base = mono_array_addr (rva_data, char, 0);
10972                         size_t size = mono_array_length (rva_data);
10973                         char *data = mono_image_alloc (klass->image, size);
10974                         memcpy (data, base, size);
10975                         klass->ext->field_def_values [i].data = data;
10976                 }
10977                 if (fb->offset != -1)
10978                         field->offset = fb->offset;
10979                 field->parent = klass;
10980                 fb->handle = field;
10981                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10982
10983                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10984                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10985                 }
10986                 if (fb->def_value) {
10987                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10988                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10989                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10990                         /* Copy the data from the blob since it might get realloc-ed */
10991                         p = assembly->blob.data + idx;
10992                         len = mono_metadata_decode_blob_size (p, &p2);
10993                         len += p2 - p;
10994                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10995                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10996                 }
10997         }
10998
10999         klass->instance_size = MAX (klass->instance_size, real_size);
11000         mono_class_layout_fields (klass);
11001 }
11002
11003 static void
11004 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11005 {
11006         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11007         MonoReflectionPropertyBuilder *pb;
11008         MonoImage *image = klass->image;
11009         MonoProperty *properties;
11010         int i;
11011
11012         mono_error_init (error);
11013
11014         if (!klass->ext)
11015                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11016
11017         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11018         klass->ext->property.first = 0;
11019
11020         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11021         klass->ext->properties = properties;
11022         for (i = 0; i < klass->ext->property.count; ++i) {
11023                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11024                 properties [i].parent = klass;
11025                 properties [i].attrs = pb->attrs;
11026                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11027                 if (!mono_error_ok (error))
11028                         return;
11029                 if (pb->get_method)
11030                         properties [i].get = pb->get_method->mhandle;
11031                 if (pb->set_method)
11032                         properties [i].set = pb->set_method->mhandle;
11033
11034                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11035                 if (pb->def_value) {
11036                         guint32 len, idx;
11037                         const char *p, *p2;
11038                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11039                         if (!klass->ext->prop_def_values)
11040                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11041                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11042                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11043                         /* Copy the data from the blob since it might get realloc-ed */
11044                         p = assembly->blob.data + idx;
11045                         len = mono_metadata_decode_blob_size (p, &p2);
11046                         len += p2 - p;
11047                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11048                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11049                 }
11050         }
11051 }
11052
11053 MonoReflectionEvent *
11054 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11055 {
11056         MonoEvent *event = g_new0 (MonoEvent, 1);
11057         MonoClass *klass;
11058
11059         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11060
11061         event->parent = klass;
11062         event->attrs = eb->attrs;
11063         event->name = mono_string_to_utf8 (eb->name);
11064         if (eb->add_method)
11065                 event->add = eb->add_method->mhandle;
11066         if (eb->remove_method)
11067                 event->remove = eb->remove_method->mhandle;
11068         if (eb->raise_method)
11069                 event->raise = eb->raise_method->mhandle;
11070
11071 #ifndef MONO_SMALL_CONFIG
11072         if (eb->other_methods) {
11073                 int j;
11074                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11075                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11076                         MonoReflectionMethodBuilder *mb = 
11077                                 mono_array_get (eb->other_methods,
11078                                                 MonoReflectionMethodBuilder*, j);
11079                         event->other [j] = mb->mhandle;
11080                 }
11081         }
11082 #endif
11083
11084         return mono_event_get_object (mono_object_domain (tb), klass, event);
11085 }
11086
11087 static void
11088 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11089 {
11090         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11091         MonoReflectionEventBuilder *eb;
11092         MonoImage *image = klass->image;
11093         MonoEvent *events;
11094         int i;
11095
11096         mono_error_init (error);
11097
11098         if (!klass->ext)
11099                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11100
11101         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11102         klass->ext->event.first = 0;
11103
11104         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11105         klass->ext->events = events;
11106         for (i = 0; i < klass->ext->event.count; ++i) {
11107                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11108                 events [i].parent = klass;
11109                 events [i].attrs = eb->attrs;
11110                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11111                 if (!mono_error_ok (error))
11112                         return;
11113                 if (eb->add_method)
11114                         events [i].add = eb->add_method->mhandle;
11115                 if (eb->remove_method)
11116                         events [i].remove = eb->remove_method->mhandle;
11117                 if (eb->raise_method)
11118                         events [i].raise = eb->raise_method->mhandle;
11119
11120 #ifndef MONO_SMALL_CONFIG
11121                 if (eb->other_methods) {
11122                         int j;
11123                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11124                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11125                                 MonoReflectionMethodBuilder *mb = 
11126                                         mono_array_get (eb->other_methods,
11127                                                                         MonoReflectionMethodBuilder*, j);
11128                                 events [i].other [j] = mb->mhandle;
11129                         }
11130                 }
11131 #endif
11132                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11133         }
11134 }
11135
11136 static gboolean
11137 remove_instantiations_of_and_ensure_contents (gpointer key,
11138                                                   gpointer value,
11139                                                   gpointer user_data)
11140 {
11141         MonoType *type = (MonoType*)key;
11142         MonoClass *klass = (MonoClass*)user_data;
11143
11144         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11145                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11146                 return TRUE;
11147         } else
11148                 return FALSE;
11149 }
11150
11151 static void
11152 check_array_for_usertypes (MonoArray *arr)
11153 {
11154         int i;
11155
11156         if (!arr)
11157                 return;
11158
11159         for (i = 0; i < mono_array_length (arr); ++i)
11160                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11161 }
11162
11163 MonoReflectionType*
11164 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11165 {
11166         MonoError error;
11167         MonoClass *klass;
11168         MonoDomain* domain;
11169         MonoReflectionType* res;
11170         int i, j;
11171
11172         MONO_ARCH_SAVE_REGS;
11173
11174         domain = mono_object_domain (tb);
11175         klass = mono_class_from_mono_type (tb->type.type);
11176
11177         /*
11178          * Check for user defined Type subclasses.
11179          */
11180         RESOLVE_TYPE (tb->parent);
11181         check_array_for_usertypes (tb->interfaces);
11182         if (tb->fields) {
11183                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11184                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11185                         if (fb) {
11186                                 RESOLVE_TYPE (fb->type);
11187                                 check_array_for_usertypes (fb->modreq);
11188                                 check_array_for_usertypes (fb->modopt);
11189                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11190                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11191                         }
11192                 }
11193         }
11194         if (tb->methods) {
11195                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11196                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11197                         if (mb) {
11198                                 RESOLVE_TYPE (mb->rtype);
11199                                 check_array_for_usertypes (mb->return_modreq);
11200                                 check_array_for_usertypes (mb->return_modopt);
11201                                 check_array_for_usertypes (mb->parameters);
11202                                 if (mb->param_modreq)
11203                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11204                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11205                                 if (mb->param_modopt)
11206                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11207                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11208                         }
11209                 }
11210         }
11211         if (tb->ctors) {
11212                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11213                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11214                         if (mb) {
11215                                 check_array_for_usertypes (mb->parameters);
11216                                 if (mb->param_modreq)
11217                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11218                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11219                                 if (mb->param_modopt)
11220                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11221                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11222                         }
11223                 }
11224         }
11225
11226         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11227
11228         /* 
11229          * we need to lock the domain because the lock will be taken inside
11230          * So, we need to keep the locking order correct.
11231          */
11232         mono_loader_lock ();
11233         mono_domain_lock (domain);
11234         if (klass->wastypebuilder) {
11235                 mono_domain_unlock (domain);
11236                 mono_loader_unlock ();
11237                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11238         }
11239         /*
11240          * Fields to set in klass:
11241          * the various flags: delegate/unicode/contextbound etc.
11242          */
11243         klass->flags = tb->attrs;
11244         klass->has_cctor = 1;
11245         klass->has_finalize = 1;
11246         klass->has_finalize_inited = 1;
11247
11248         /* fool mono_class_setup_parent */
11249         klass->supertypes = NULL;
11250         mono_class_setup_parent (klass, klass->parent);
11251         mono_class_setup_mono_type (klass);
11252
11253 #if 0
11254         if (!((MonoDynamicImage*)klass->image)->run) {
11255                 if (klass->generic_container) {
11256                         /* FIXME: The code below can't handle generic classes */
11257                         klass->wastypebuilder = TRUE;
11258                         mono_loader_unlock ();
11259                         mono_domain_unlock (domain);
11260                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11261                 }
11262         }
11263 #endif
11264
11265         /* enums are done right away */
11266         if (!klass->enumtype)
11267                 ensure_runtime_vtable (klass);
11268
11269         if (tb->subtypes) {
11270                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11271                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11272                         mono_class_alloc_ext (klass);
11273                         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)));
11274                 }
11275         }
11276
11277         klass->nested_classes_inited = TRUE;
11278
11279         /* fields and object layout */
11280         if (klass->parent) {
11281                 if (!klass->parent->size_inited)
11282                         mono_class_init (klass->parent);
11283                 klass->instance_size = klass->parent->instance_size;
11284                 klass->sizes.class_size = 0;
11285                 klass->min_align = klass->parent->min_align;
11286                 /* if the type has no fields we won't call the field_setup
11287                  * routine which sets up klass->has_references.
11288                  */
11289                 klass->has_references |= klass->parent->has_references;
11290         } else {
11291                 klass->instance_size = sizeof (MonoObject);
11292                 klass->min_align = 1;
11293         }
11294
11295         /* FIXME: handle packing_size and instance_size */
11296         typebuilder_setup_fields (klass, &error);
11297         if (!mono_error_ok (&error))
11298                 goto failure;
11299         typebuilder_setup_properties (klass, &error);
11300         if (!mono_error_ok (&error))
11301                 goto failure;
11302
11303         typebuilder_setup_events (klass, &error);
11304         if (!mono_error_ok (&error))
11305                 goto failure;
11306
11307         klass->wastypebuilder = TRUE;
11308
11309         /* 
11310          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11311          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11312          * we want to return normal System.MonoType objects, so clear these out from the cache.
11313          *
11314          * Together with this we must ensure the contents of all instances to match the created type.
11315          */
11316         if (domain->type_hash && klass->generic_container)
11317                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11318
11319         mono_domain_unlock (domain);
11320         mono_loader_unlock ();
11321
11322         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11323                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11324                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11325         }
11326
11327         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11328         g_assert (res != (MonoReflectionType*)tb);
11329
11330         return res;
11331
11332 failure:
11333         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11334         klass->wastypebuilder = TRUE;
11335         mono_domain_unlock (domain);
11336         mono_loader_unlock ();
11337         mono_error_raise_exception (&error);
11338         return NULL;
11339 }
11340
11341 void
11342 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11343 {
11344         MonoGenericParamFull *param;
11345         MonoImage *image;
11346         MonoClass *pklass;
11347         MonoError error;
11348
11349         MONO_ARCH_SAVE_REGS;
11350
11351         image = &gparam->tbuilder->module->dynamic_image->image;
11352
11353         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11354
11355         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11356         g_assert (mono_error_ok (&error));
11357         param->param.num = gparam->index;
11358
11359         if (gparam->mbuilder) {
11360                 if (!gparam->mbuilder->generic_container) {
11361                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11362                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11363                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11364                         gparam->mbuilder->generic_container->is_method = TRUE;
11365                         /* 
11366                          * Cannot set owner.method, since the MonoMethod is not created yet.
11367                          * Set the image field instead, so type_in_image () works.
11368                          */
11369                         gparam->mbuilder->generic_container->image = klass->image;
11370                 }
11371                 param->param.owner = gparam->mbuilder->generic_container;
11372         } else if (gparam->tbuilder) {
11373                 if (!gparam->tbuilder->generic_container) {
11374                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11375                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11376                         gparam->tbuilder->generic_container->owner.klass = klass;
11377                 }
11378                 param->param.owner = gparam->tbuilder->generic_container;
11379         }
11380
11381         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11382
11383         gparam->type.type = &pklass->byval_arg;
11384
11385         mono_class_set_ref_info (pklass, gparam);
11386         mono_image_lock (image);
11387         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11388         mono_image_unlock (image);
11389 }
11390
11391 MonoArray *
11392 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11393 {
11394         MonoReflectionModuleBuilder *module = sig->module;
11395         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11396         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11397         guint32 buflen, i;
11398         MonoArray *result;
11399         SigBuffer buf;
11400
11401         check_array_for_usertypes (sig->arguments);
11402
11403         sigbuffer_init (&buf, 32);
11404
11405         sigbuffer_add_value (&buf, 0x07);
11406         sigbuffer_add_value (&buf, na);
11407         if (assembly != NULL){
11408                 for (i = 0; i < na; ++i) {
11409                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11410                         encode_reflection_type (assembly, type, &buf);
11411                 }
11412         }
11413
11414         buflen = buf.p - buf.buf;
11415         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11416         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11417         sigbuffer_free (&buf);
11418
11419         return result;
11420 }
11421
11422 MonoArray *
11423 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11424 {
11425         MonoDynamicImage *assembly = sig->module->dynamic_image;
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, 0x06);
11436         for (i = 0; i < na; ++i) {
11437                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11438                 encode_reflection_type (assembly, type, &buf);
11439         }
11440
11441         buflen = buf.p - buf.buf;
11442         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11443         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11444         sigbuffer_free (&buf);
11445
11446         return result;
11447 }
11448
11449 typedef struct {
11450         MonoMethod *handle;
11451         MonoDomain *domain;
11452 } DynamicMethodReleaseData;
11453
11454 /*
11455  * The runtime automatically clean up those after finalization.
11456 */      
11457 static MonoReferenceQueue *dynamic_method_queue;
11458
11459 static void
11460 free_dynamic_method (void *dynamic_method)
11461 {
11462         DynamicMethodReleaseData *data = dynamic_method;
11463
11464         mono_runtime_free_method (data->domain, data->handle);
11465         g_free (data);
11466 }
11467
11468 void 
11469 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11470 {
11471         MonoReferenceQueue *queue;
11472         MonoMethod *handle;
11473         DynamicMethodReleaseData *release_data;
11474         ReflectionMethodBuilder rmb;
11475         MonoMethodSignature *sig;
11476         MonoClass *klass;
11477         GSList *l;
11478         int i;
11479
11480         if (mono_runtime_is_shutting_down ())
11481                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11482
11483         if (!(queue = dynamic_method_queue)) {
11484                 mono_loader_lock ();
11485                 if (!(queue = dynamic_method_queue))
11486                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11487                 mono_loader_unlock ();
11488         }
11489
11490         sig = dynamic_method_to_signature (mb);
11491
11492         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11493
11494         /*
11495          * Resolve references.
11496          */
11497         /* 
11498          * Every second entry in the refs array is reserved for storing handle_class,
11499          * which is needed by the ldtoken implementation in the JIT.
11500          */
11501         rmb.nrefs = mb->nrefs;
11502         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11503         for (i = 0; i < mb->nrefs; i += 2) {
11504                 MonoClass *handle_class;
11505                 gpointer ref;
11506                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11507
11508                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11509                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11510                         /*
11511                          * The referenced DynamicMethod should already be created by the managed
11512                          * code, except in the case of circular references. In that case, we store
11513                          * method in the refs array, and fix it up later when the referenced 
11514                          * DynamicMethod is created.
11515                          */
11516                         if (method->mhandle) {
11517                                 ref = method->mhandle;
11518                         } else {
11519                                 /* FIXME: GC object stored in unmanaged memory */
11520                                 ref = method;
11521
11522                                 /* FIXME: GC object stored in unmanaged memory */
11523                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11524                         }
11525                         handle_class = mono_defaults.methodhandle_class;
11526                 } else {
11527                         MonoException *ex = NULL;
11528                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11529                         if (!ref)
11530                                 ex = mono_get_exception_type_load (NULL, NULL);
11531                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11532                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11533
11534                         if (ex) {
11535                                 g_free (rmb.refs);
11536                                 mono_raise_exception (ex);
11537                                 return;
11538                         }
11539                 }
11540
11541                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11542                 rmb.refs [i + 1] = handle_class;
11543         }               
11544
11545         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11546
11547         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11548         release_data = g_new (DynamicMethodReleaseData, 1);
11549         release_data->handle = handle;
11550         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11551         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11552                 g_free (release_data);
11553
11554         /* Fix up refs entries pointing at us */
11555         for (l = mb->referenced_by; l; l = l->next) {
11556                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11557                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11558                 gpointer *data;
11559                 
11560                 g_assert (method->mhandle);
11561
11562                 data = (gpointer*)wrapper->method_data;
11563                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11564                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11565                                 data [i + 1] = mb->mhandle;
11566                 }
11567         }
11568         g_slist_free (mb->referenced_by);
11569
11570         g_free (rmb.refs);
11571
11572         /* ilgen is no longer needed */
11573         mb->ilgen = NULL;
11574 }
11575
11576 #endif /* DISABLE_REFLECTION_EMIT */
11577
11578 /**
11579  * 
11580  * mono_reflection_is_valid_dynamic_token:
11581  * 
11582  * Returns TRUE if token is valid.
11583  * 
11584  */
11585 gboolean
11586 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11587 {
11588         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11589 }
11590
11591 MonoMethodSignature *
11592 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11593 {
11594         MonoMethodSignature *sig;
11595         g_assert (image->dynamic);
11596
11597         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11598         if (sig)
11599                 return sig;
11600
11601         return mono_method_signature (method);
11602 }
11603
11604 #ifndef DISABLE_REFLECTION_EMIT
11605
11606 /**
11607  * mono_reflection_lookup_dynamic_token:
11608  *
11609  * Finish the Builder object pointed to by TOKEN and return the corresponding
11610  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11611  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11612  * mapping table.
11613  *
11614  * LOCKING: Take the loader lock
11615  */
11616 gpointer
11617 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11618 {
11619         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11620         MonoObject *obj;
11621         MonoClass *klass;
11622
11623         mono_loader_lock ();
11624         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11625         mono_loader_unlock ();
11626         if (!obj) {
11627                 if (valid_token)
11628                         g_error ("Could not find required dynamic token 0x%08x", token);
11629                 else
11630                         return NULL;
11631         }
11632
11633         if (!handle_class)
11634                 handle_class = &klass;
11635         return resolve_object (image, obj, handle_class, context);
11636 }
11637
11638 /*
11639  * ensure_complete_type:
11640  *
11641  *   Ensure that KLASS is completed if it is a dynamic type, or references
11642  * dynamic types.
11643  */
11644 static void
11645 ensure_complete_type (MonoClass *klass)
11646 {
11647         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11648                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11649
11650                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11651
11652                 // Asserting here could break a lot of code
11653                 //g_assert (klass->wastypebuilder);
11654         }
11655
11656         if (klass->generic_class) {
11657                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11658                 int i;
11659
11660                 for (i = 0; i < inst->type_argc; ++i) {
11661                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11662                 }
11663         }
11664 }
11665
11666 static gpointer
11667 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11668 {
11669         gpointer result = NULL;
11670
11671         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11672                 result = mono_string_intern ((MonoString*)obj);
11673                 *handle_class = mono_defaults.string_class;
11674                 g_assert (result);
11675         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11676                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11677                 MonoClass *mc = mono_class_from_mono_type (type);
11678                 if (!mono_class_init (mc))
11679                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11680
11681                 if (context) {
11682                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11683                         result = mono_class_from_mono_type (inflated);
11684                         mono_metadata_free_type (inflated);
11685                 } else {
11686                         result = mono_class_from_mono_type (type);
11687                 }
11688                 *handle_class = mono_defaults.typehandle_class;
11689                 g_assert (result);
11690         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11691                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11692                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11693                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11694                 result = ((MonoReflectionMethod*)obj)->method;
11695                 if (context)
11696                         result = mono_class_inflate_generic_method (result, context);
11697                 *handle_class = mono_defaults.methodhandle_class;
11698                 g_assert (result);
11699         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11700                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11701                 result = mb->mhandle;
11702                 if (!result) {
11703                         /* Type is not yet created */
11704                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11705
11706                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11707
11708                         /*
11709                          * Hopefully this has been filled in by calling CreateType() on the
11710                          * TypeBuilder.
11711                          */
11712                         /*
11713                          * TODO: This won't work if the application finishes another 
11714                          * TypeBuilder instance instead of this one.
11715                          */
11716                         result = mb->mhandle;
11717                 }
11718                 if (context)
11719                         result = mono_class_inflate_generic_method (result, context);
11720                 *handle_class = mono_defaults.methodhandle_class;
11721         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11722                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11723
11724                 result = cb->mhandle;
11725                 if (!result) {
11726                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11727
11728                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11729                         result = cb->mhandle;
11730                 }
11731                 if (context)
11732                         result = mono_class_inflate_generic_method (result, context);
11733                 *handle_class = mono_defaults.methodhandle_class;
11734         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11735                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11736
11737                 ensure_complete_type (field->parent);
11738                 if (context) {
11739                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11740                         MonoClass *class = mono_class_from_mono_type (inflated);
11741                         MonoClassField *inflated_field;
11742                         gpointer iter = NULL;
11743                         mono_metadata_free_type (inflated);
11744                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11745                                 if (!strcmp (field->name, inflated_field->name))
11746                                         break;
11747                         }
11748                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11749                         result = inflated_field;
11750                 } else {
11751                         result = field;
11752                 }
11753                 *handle_class = mono_defaults.fieldhandle_class;
11754                 g_assert (result);
11755         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11756                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11757                 result = fb->handle;
11758
11759                 if (!result) {
11760                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11761
11762                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11763                         result = fb->handle;
11764                 }
11765
11766                 if (fb->handle && fb->handle->parent->generic_container) {
11767                         MonoClass *klass = fb->handle->parent;
11768                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11769                         MonoClass *inflated = mono_class_from_mono_type (type);
11770
11771                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11772                         g_assert (result);
11773                         mono_metadata_free_type (type);
11774                 }
11775                 *handle_class = mono_defaults.fieldhandle_class;
11776         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11777                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11778                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11779                 MonoClass *klass;
11780
11781                 klass = type->data.klass;
11782                 if (klass->wastypebuilder) {
11783                         /* Already created */
11784                         result = klass;
11785                 }
11786                 else {
11787                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11788                         result = type->data.klass;
11789                         g_assert (result);
11790                 }
11791                 *handle_class = mono_defaults.typehandle_class;
11792         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11793                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11794                 MonoMethodSignature *sig;
11795                 int nargs, i;
11796
11797                 if (helper->arguments)
11798                         nargs = mono_array_length (helper->arguments);
11799                 else
11800                         nargs = 0;
11801
11802                 sig = mono_metadata_signature_alloc (image, nargs);
11803                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11804                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11805
11806                 if (helper->unmanaged_call_conv) { /* unmanaged */
11807                         sig->call_convention = helper->unmanaged_call_conv - 1;
11808                         sig->pinvoke = TRUE;
11809                 } else if (helper->call_conv & 0x02) {
11810                         sig->call_convention = MONO_CALL_VARARG;
11811                 } else {
11812                         sig->call_convention = MONO_CALL_DEFAULT;
11813                 }
11814
11815                 sig->param_count = nargs;
11816                 /* TODO: Copy type ? */
11817                 sig->ret = helper->return_type->type;
11818                 for (i = 0; i < nargs; ++i)
11819                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11820
11821                 result = sig;
11822                 *handle_class = NULL;
11823         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11824                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11825                 /* Already created by the managed code */
11826                 g_assert (method->mhandle);
11827                 result = method->mhandle;
11828                 *handle_class = mono_defaults.methodhandle_class;
11829         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11830                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11831                 type = mono_class_inflate_generic_type (type, context);
11832                 result = mono_class_from_mono_type (type);
11833                 *handle_class = mono_defaults.typehandle_class;
11834                 g_assert (result);
11835                 mono_metadata_free_type (type);
11836         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11837                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11838                 type = mono_class_inflate_generic_type (type, context);
11839                 result = mono_class_from_mono_type (type);
11840                 *handle_class = mono_defaults.typehandle_class;
11841                 g_assert (result);
11842                 mono_metadata_free_type (type);
11843         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11844                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11845                 MonoClass *inflated;
11846                 MonoType *type;
11847                 MonoClassField *field;
11848
11849                 if (is_sre_field_builder (mono_object_class (f->fb)))
11850                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11851                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11852                         field = ((MonoReflectionField*)f->fb)->field;
11853                 else
11854                         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)));
11855
11856                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11857                 inflated = mono_class_from_mono_type (type);
11858
11859                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11860                 ensure_complete_type (field->parent);
11861                 g_assert (result);
11862                 mono_metadata_free_type (type);
11863                 *handle_class = mono_defaults.fieldhandle_class;
11864         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11865                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11866                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11867                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11868                 MonoMethod *method;
11869
11870                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11871                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11872                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11873                         method = ((MonoReflectionMethod *)c->cb)->method;
11874                 else
11875                         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)));
11876
11877                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11878                 *handle_class = mono_defaults.methodhandle_class;
11879                 mono_metadata_free_type (type);
11880         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11881                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11882                 if (m->method_args) {
11883                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11884                         if (context)
11885                                 result = mono_class_inflate_generic_method (result, context);
11886                 } else {
11887                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11888                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11889                         MonoMethod *method;
11890
11891                         if (is_sre_method_builder (mono_object_class (m->mb)))
11892                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11893                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11894                                 method = ((MonoReflectionMethod *)m->mb)->method;
11895                         else
11896                                 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)));
11897
11898                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11899                         mono_metadata_free_type (type);
11900                 }
11901                 *handle_class = mono_defaults.methodhandle_class;
11902         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11903                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11904                 MonoType *mtype;
11905                 MonoClass *klass;
11906                 MonoMethod *method;
11907                 gpointer iter;
11908                 char *name;
11909
11910                 mtype = mono_reflection_type_get_handle (m->parent);
11911                 klass = mono_class_from_mono_type (mtype);
11912
11913                 /* Find the method */
11914
11915                 name = mono_string_to_utf8 (m->name);
11916                 iter = NULL;
11917                 while ((method = mono_class_get_methods (klass, &iter))) {
11918                         if (!strcmp (method->name, name))
11919                                 break;
11920                 }
11921                 g_free (name);
11922
11923                 // FIXME:
11924                 g_assert (method);
11925                 // FIXME: Check parameters/return value etc. match
11926
11927                 result = method;
11928                 *handle_class = mono_defaults.methodhandle_class;
11929         } else if (is_sre_array (mono_object_get_class(obj)) ||
11930                                 is_sre_byref (mono_object_get_class(obj)) ||
11931                                 is_sre_pointer (mono_object_get_class(obj))) {
11932                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11933                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11934                 result = mono_class_from_mono_type (type);
11935                 *handle_class = mono_defaults.typehandle_class;
11936         } else {
11937                 g_print ("%s\n", obj->vtable->klass->name);
11938                 g_assert_not_reached ();
11939         }
11940         return result;
11941 }
11942
11943 #else /* DISABLE_REFLECTION_EMIT */
11944
11945 MonoArray*
11946 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11947 {
11948         g_assert_not_reached ();
11949         return NULL;
11950 }
11951
11952 void
11953 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11954 {
11955         g_assert_not_reached ();
11956 }
11957
11958 void
11959 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11960 {
11961         g_assert_not_reached ();
11962 }
11963
11964 void
11965 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11966 {
11967         g_assert_not_reached ();
11968 }
11969
11970 void
11971 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11972 {
11973         g_assert_not_reached ();
11974 }
11975
11976 void
11977 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11978 {
11979         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11980 }
11981
11982 void
11983 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11984 {
11985         g_assert_not_reached ();
11986 }
11987
11988 void
11989 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11990 {
11991         g_assert_not_reached ();
11992 }
11993
11994 MonoReflectionModule *
11995 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11996 {
11997         g_assert_not_reached ();
11998         return NULL;
11999 }
12000
12001 guint32
12002 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12003 {
12004         g_assert_not_reached ();
12005         return 0;
12006 }
12007
12008 guint32
12009 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12010 {
12011         g_assert_not_reached ();
12012         return 0;
12013 }
12014
12015 guint32
12016 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12017                                                  gboolean create_open_instance, gboolean register_token)
12018 {
12019         g_assert_not_reached ();
12020         return 0;
12021 }
12022
12023 void
12024 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12025 {
12026 }
12027
12028 void
12029 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
12030                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12031                                           MonoArray *events)
12032 {
12033         g_assert_not_reached ();
12034 }
12035
12036 void
12037 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12038 {
12039         *overrides = NULL;
12040         *num_overrides = 0;
12041 }
12042
12043 MonoReflectionEvent *
12044 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12045 {
12046         g_assert_not_reached ();
12047         return NULL;
12048 }
12049
12050 MonoReflectionType*
12051 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12052 {
12053         g_assert_not_reached ();
12054         return NULL;
12055 }
12056
12057 void
12058 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12059 {
12060         g_assert_not_reached ();
12061 }
12062
12063 MonoArray *
12064 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12065 {
12066         g_assert_not_reached ();
12067         return NULL;
12068 }
12069
12070 MonoArray *
12071 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12072 {
12073         g_assert_not_reached ();
12074         return NULL;
12075 }
12076
12077 void 
12078 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12079 {
12080 }
12081
12082 gpointer
12083 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12084 {
12085         return NULL;
12086 }
12087
12088 MonoType*
12089 mono_reflection_type_get_handle (MonoReflectionType* ref)
12090 {
12091         if (!ref)
12092                 return NULL;
12093         return ref->type;
12094 }
12095
12096 void
12097 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12098 {
12099         g_assert_not_reached ();
12100 }
12101
12102 #endif /* DISABLE_REFLECTION_EMIT */
12103
12104 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12105 const static guint32 declsec_flags_map[] = {
12106         0x00000000,                                     /* empty */
12107         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12108         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12109         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12110         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12111         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12112         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12113         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12114         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12115         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12116         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12117         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12118         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12119         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12120         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12121         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12122         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12123         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12124         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12125 };
12126
12127 /*
12128  * Returns flags that includes all available security action associated to the handle.
12129  * @token: metadata token (either for a class or a method)
12130  * @image: image where resides the metadata.
12131  */
12132 static guint32
12133 mono_declsec_get_flags (MonoImage *image, guint32 token)
12134 {
12135         int index = mono_metadata_declsec_from_index (image, token);
12136         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12137         guint32 result = 0;
12138         guint32 action;
12139         int i;
12140
12141         /* HasSecurity can be present for other, not specially encoded, attributes,
12142            e.g. SuppressUnmanagedCodeSecurityAttribute */
12143         if (index < 0)
12144                 return 0;
12145
12146         for (i = index; i < t->rows; i++) {
12147                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12148
12149                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12150                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12151                         break;
12152
12153                 action = cols [MONO_DECL_SECURITY_ACTION];
12154                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12155                         result |= declsec_flags_map [action];
12156                 } else {
12157                         g_assert_not_reached ();
12158                 }
12159         }
12160         return result;
12161 }
12162
12163 /*
12164  * Get the security actions (in the form of flags) associated with the specified method.
12165  *
12166  * @method: The method for which we want the declarative security flags.
12167  * Return the declarative security flags for the method (only).
12168  *
12169  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12170  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12171  */
12172 guint32
12173 mono_declsec_flags_from_method (MonoMethod *method)
12174 {
12175         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12176                 /* FIXME: No cache (for the moment) */
12177                 guint32 idx = mono_method_get_index (method);
12178                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12179                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12180                 return mono_declsec_get_flags (method->klass->image, idx);
12181         }
12182         return 0;
12183 }
12184
12185 /*
12186  * Get the security actions (in the form of flags) associated with the specified class.
12187  *
12188  * @klass: The class for which we want the declarative security flags.
12189  * Return the declarative security flags for the class.
12190  *
12191  * Note: We cache the flags inside the MonoClass structure as this will get 
12192  *       called very often (at least for each method).
12193  */
12194 guint32
12195 mono_declsec_flags_from_class (MonoClass *klass)
12196 {
12197         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12198                 if (!klass->ext || !klass->ext->declsec_flags) {
12199                         guint32 idx;
12200
12201                         idx = mono_metadata_token_index (klass->type_token);
12202                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12203                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12204                         mono_loader_lock ();
12205                         mono_class_alloc_ext (klass);
12206                         mono_loader_unlock ();
12207                         /* we cache the flags on classes */
12208                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12209                 }
12210                 return klass->ext->declsec_flags;
12211         }
12212         return 0;
12213 }
12214
12215 /*
12216  * Get the security actions (in the form of flags) associated with the specified assembly.
12217  *
12218  * @assembly: The assembly for which we want the declarative security flags.
12219  * Return the declarative security flags for the assembly.
12220  */
12221 guint32
12222 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12223 {
12224         guint32 idx = 1; /* there is only one assembly */
12225         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12226         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12227         return mono_declsec_get_flags (assembly->image, idx);
12228 }
12229
12230
12231 /*
12232  * Fill actions for the specific index (which may either be an encoded class token or
12233  * an encoded method token) from the metadata image.
12234  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12235  */
12236 static MonoBoolean
12237 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12238         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12239 {
12240         MonoBoolean result = FALSE;
12241         MonoTableInfo *t;
12242         guint32 cols [MONO_DECL_SECURITY_SIZE];
12243         int index = mono_metadata_declsec_from_index (image, token);
12244         int i;
12245
12246         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12247         for (i = index; i < t->rows; i++) {
12248                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12249
12250                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12251                         return result;
12252
12253                 /* if present only replace (class) permissions with method permissions */
12254                 /* if empty accept either class or method permissions */
12255                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12256                         if (!actions->demand.blob) {
12257                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12258                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12259                                 actions->demand.blob = (char*) (blob + 2);
12260                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12261                                 result = TRUE;
12262                         }
12263                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12264                         if (!actions->noncasdemand.blob) {
12265                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12266                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12267                                 actions->noncasdemand.blob = (char*) (blob + 2);
12268                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12269                                 result = TRUE;
12270                         }
12271                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12272                         if (!actions->demandchoice.blob) {
12273                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12274                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12275                                 actions->demandchoice.blob = (char*) (blob + 2);
12276                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12277                                 result = TRUE;
12278                         }
12279                 }
12280         }
12281
12282         return result;
12283 }
12284
12285 static MonoBoolean
12286 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12287         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12288 {
12289         guint32 idx = mono_metadata_token_index (klass->type_token);
12290         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12291         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12292         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12293 }
12294
12295 static MonoBoolean
12296 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12297         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12298 {
12299         guint32 idx = mono_method_get_index (method);
12300         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12301         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12302         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12303 }
12304
12305 /*
12306  * Collect all actions (that requires to generate code in mini) assigned for
12307  * the specified method.
12308  * Note: Don't use the content of actions if the function return FALSE.
12309  */
12310 MonoBoolean
12311 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12312 {
12313         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12314                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12315         MonoBoolean result = FALSE;
12316         guint32 flags;
12317
12318         /* quick exit if no declarative security is present in the metadata */
12319         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12320                 return FALSE;
12321
12322         /* we want the original as the wrapper is "free" of the security informations */
12323         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12324                 method = mono_marshal_method_from_wrapper (method);
12325                 if (!method)
12326                         return FALSE;
12327         }
12328
12329         /* First we look for method-level attributes */
12330         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12331                 mono_class_init (method->klass);
12332                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12333
12334                 result = mono_declsec_get_method_demands_params (method, demands, 
12335                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12336         }
12337
12338         /* Here we use (or create) the class declarative cache to look for demands */
12339         flags = mono_declsec_flags_from_class (method->klass);
12340         if (flags & mask) {
12341                 if (!result) {
12342                         mono_class_init (method->klass);
12343                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12344                 }
12345                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12346                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12347         }
12348
12349         /* The boolean return value is used as a shortcut in case nothing needs to
12350            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12351         return result;
12352 }
12353
12354
12355 /*
12356  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12357  *
12358  * Note: Don't use the content of actions if the function return FALSE.
12359  */
12360 MonoBoolean
12361 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12362 {
12363         MonoBoolean result = FALSE;
12364         guint32 flags;
12365
12366         /* quick exit if no declarative security is present in the metadata */
12367         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12368                 return FALSE;
12369
12370         /* we want the original as the wrapper is "free" of the security informations */
12371         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12372                 method = mono_marshal_method_from_wrapper (method);
12373                 if (!method)
12374                         return FALSE;
12375         }
12376
12377         /* results are independant - zeroize both */
12378         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12379         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12380
12381         /* First we look for method-level attributes */
12382         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12383                 mono_class_init (method->klass);
12384
12385                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12386                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12387         }
12388
12389         /* Here we use (or create) the class declarative cache to look for demands */
12390         flags = mono_declsec_flags_from_class (method->klass);
12391         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12392                 mono_class_init (method->klass);
12393
12394                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12395                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12396         }
12397
12398         return result;
12399 }
12400
12401 /*
12402  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12403  *
12404  * @klass       The inherited class - this is the class that provides the security check (attributes)
12405  * @demans      
12406  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12407  * 
12408  * Note: Don't use the content of actions if the function return FALSE.
12409  */
12410 MonoBoolean
12411 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12412 {
12413         MonoBoolean result = FALSE;
12414         guint32 flags;
12415
12416         /* quick exit if no declarative security is present in the metadata */
12417         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12418                 return FALSE;
12419
12420         /* Here we use (or create) the class declarative cache to look for demands */
12421         flags = mono_declsec_flags_from_class (klass);
12422         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12423                 mono_class_init (klass);
12424                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12425
12426                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12427                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12428         }
12429
12430         return result;
12431 }
12432
12433 /*
12434  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12435  *
12436  * Note: Don't use the content of actions if the function return FALSE.
12437  */
12438 MonoBoolean
12439 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12440 {
12441         /* quick exit if no declarative security is present in the metadata */
12442         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12443                 return FALSE;
12444
12445         /* we want the original as the wrapper is "free" of the security informations */
12446         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12447                 method = mono_marshal_method_from_wrapper (method);
12448                 if (!method)
12449                         return FALSE;
12450         }
12451
12452         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12453                 mono_class_init (method->klass);
12454                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12455
12456                 return mono_declsec_get_method_demands_params (method, demands, 
12457                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12458         }
12459         return FALSE;
12460 }
12461
12462
12463 static MonoBoolean
12464 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12465 {
12466         guint32 cols [MONO_DECL_SECURITY_SIZE];
12467         MonoTableInfo *t;
12468         int i;
12469
12470         int index = mono_metadata_declsec_from_index (image, token);
12471         if (index == -1)
12472                 return FALSE;
12473
12474         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12475         for (i = index; i < t->rows; i++) {
12476                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12477
12478                 /* shortcut - index are ordered */
12479                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12480                         return FALSE;
12481
12482                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12483                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12484                         entry->blob = (char*) (metadata + 2);
12485                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12486                         return TRUE;
12487                 }
12488         }
12489
12490         return FALSE;
12491 }
12492
12493 MonoBoolean
12494 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12495 {
12496         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12497                 guint32 idx = mono_method_get_index (method);
12498                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12499                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12500                 return get_declsec_action (method->klass->image, idx, action, entry);
12501         }
12502         return FALSE;
12503 }
12504
12505 MonoBoolean
12506 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12507 {
12508         /* use cache */
12509         guint32 flags = mono_declsec_flags_from_class (klass);
12510         if (declsec_flags_map [action] & flags) {
12511                 guint32 idx = mono_metadata_token_index (klass->type_token);
12512                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12513                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12514                 return get_declsec_action (klass->image, idx, action, entry);
12515         }
12516         return FALSE;
12517 }
12518
12519 MonoBoolean
12520 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12521 {
12522         guint32 idx = 1; /* there is only one assembly */
12523         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12524         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12525
12526         return get_declsec_action (assembly->image, idx, action, entry);
12527 }
12528
12529 gboolean
12530 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12531 {
12532         MonoObject *res, *exc;
12533         void *params [1];
12534         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12535         static MonoMethod *method = NULL;
12536
12537         if (!System_Reflection_Emit_TypeBuilder) {
12538                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12539                 g_assert (System_Reflection_Emit_TypeBuilder);
12540         }
12541         if (method == NULL) {
12542                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12543                 g_assert (method);
12544         }
12545
12546         /* 
12547          * The result of mono_type_get_object () might be a System.MonoType but we
12548          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12549          */
12550         g_assert (mono_class_get_ref_info (klass));
12551         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12552
12553         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12554
12555         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12556         if (exc)
12557                 return FALSE;
12558         else
12559                 return *(MonoBoolean*)mono_object_unbox (res);
12560 }
12561
12562 /**
12563  * mono_reflection_type_get_type:
12564  * @reftype: the System.Type object
12565  *
12566  * Returns the MonoType* associated with the C# System.Type object @reftype.
12567  */
12568 MonoType*
12569 mono_reflection_type_get_type (MonoReflectionType *reftype)
12570 {
12571         g_assert (reftype);
12572
12573         return mono_reflection_type_get_handle (reftype);
12574 }
12575