Normalize line endings.
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45
46
47 #if HAVE_SGEN_GC
48 static void* reflection_info_desc = NULL;
49 #define MOVING_GC_REGISTER(addr) do {   \
50                 if (!reflection_info_desc) {    \
51                         gsize bmap = 1;         \
52                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
53                 }       \
54                 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
55         } while (0)
56 #else
57 #define MOVING_GC_REGISTER(addr)
58 #endif
59
60 static gboolean is_usertype (MonoReflectionType *ref);
61 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
62
63 typedef struct {
64         char *p;
65         char *buf;
66         char *end;
67 } SigBuffer;
68
69 #define TEXT_OFFSET 512
70 #define CLI_H_SIZE 136
71 #define FILE_ALIGN 512
72 #define VIRT_ALIGN 8192
73 #define START_TEXT_RVA  0x00002000
74
75 typedef struct {
76         MonoReflectionILGen *ilgen;
77         MonoReflectionType *rtype;
78         MonoArray *parameters;
79         MonoArray *generic_params;
80         MonoGenericContainer *generic_container;
81         MonoArray *pinfo;
82         MonoArray *opt_types;
83         guint32 attrs;
84         guint32 iattrs;
85         guint32 call_conv;
86         guint32 *table_idx; /* note: it's a pointer */
87         MonoArray *code;
88         MonoObject *type;
89         MonoString *name;
90         MonoBoolean init_locals;
91         MonoBoolean skip_visibility;
92         MonoArray *return_modreq;
93         MonoArray *return_modopt;
94         MonoArray *param_modreq;
95         MonoArray *param_modopt;
96         MonoArray *permissions;
97         MonoMethod *mhandle;
98         guint32 nrefs;
99         gpointer *refs;
100         /* for PInvoke */
101         int charset, extra_flags, native_cc;
102         MonoString *dll, *dllentry;
103 } ReflectionMethodBuilder;
104
105 typedef struct {
106         guint32 owner;
107         MonoReflectionGenericParam *gparam;
108 } GenericParamTableEntry;
109
110 const unsigned char table_sizes [MONO_TABLE_NUM] = {
111         MONO_MODULE_SIZE,
112         MONO_TYPEREF_SIZE,
113         MONO_TYPEDEF_SIZE,
114         0,
115         MONO_FIELD_SIZE,
116         0,
117         MONO_METHOD_SIZE,
118         0,
119         MONO_PARAM_SIZE,
120         MONO_INTERFACEIMPL_SIZE,
121         MONO_MEMBERREF_SIZE,    /* 0x0A */
122         MONO_CONSTANT_SIZE,
123         MONO_CUSTOM_ATTR_SIZE,
124         MONO_FIELD_MARSHAL_SIZE,
125         MONO_DECL_SECURITY_SIZE,
126         MONO_CLASS_LAYOUT_SIZE,
127         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
128         MONO_STAND_ALONE_SIGNATURE_SIZE,
129         MONO_EVENT_MAP_SIZE,
130         0,
131         MONO_EVENT_SIZE,
132         MONO_PROPERTY_MAP_SIZE,
133         0,
134         MONO_PROPERTY_SIZE,
135         MONO_METHOD_SEMA_SIZE,
136         MONO_METHODIMPL_SIZE,
137         MONO_MODULEREF_SIZE,    /* 0x1A */
138         MONO_TYPESPEC_SIZE,
139         MONO_IMPLMAP_SIZE,      
140         MONO_FIELD_RVA_SIZE,
141         0,
142         0,
143         MONO_ASSEMBLY_SIZE,     /* 0x20 */
144         MONO_ASSEMBLY_PROCESSOR_SIZE,
145         MONO_ASSEMBLYOS_SIZE,
146         MONO_ASSEMBLYREF_SIZE,
147         MONO_ASSEMBLYREFPROC_SIZE,
148         MONO_ASSEMBLYREFOS_SIZE,
149         MONO_FILE_SIZE,
150         MONO_EXP_TYPE_SIZE,
151         MONO_MANIFEST_SIZE,
152         MONO_NESTED_CLASS_SIZE,
153
154         MONO_GENERICPARAM_SIZE, /* 0x2A */
155         MONO_METHODSPEC_SIZE,
156         MONO_GENPARCONSTRAINT_SIZE
157
158 };
159
160 #ifndef DISABLE_REFLECTION_EMIT
161 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
162 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
163 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
164 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
165 static void    ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
168 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
169 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
173 #endif
174
175 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
176 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
177 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
178 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
179 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
180 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
181 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
182 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
183 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
184 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
185 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
186 static gboolean is_sre_array (MonoClass *class);
187 static gboolean is_sre_byref (MonoClass *class);
188 static gboolean is_sre_pointer (MonoClass *class);
189 static gboolean is_sre_type_builder (MonoClass *class);
190 static gboolean is_sre_method_builder (MonoClass *class);
191 static gboolean is_sre_ctor_builder (MonoClass *class);
192 static gboolean is_sre_field_builder (MonoClass *class);
193 static gboolean is_sr_mono_method (MonoClass *class);
194 static gboolean is_sr_mono_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_generic_method (MonoClass *class);
196 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
197 static gboolean is_sr_mono_field (MonoClass *class);
198 static gboolean is_sr_mono_property (MonoClass *class);
199 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
200 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
201
202 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
203 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
204 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
205
206 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
207 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
208         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
209         __type = mono_reflection_type_resolve_user_types (__type);      \
210         mono_array_set (arr, MonoReflectionType*, index, __type);       \
211 } while (0)
212
213 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
214
215 void
216 mono_reflection_init (void)
217 {
218 }
219
220 static void
221 sigbuffer_init (SigBuffer *buf, int size)
222 {
223         buf->buf = g_malloc (size);
224         buf->p = buf->buf;
225         buf->end = buf->buf + size;
226 }
227
228 static void
229 sigbuffer_make_room (SigBuffer *buf, int size)
230 {
231         if (buf->end - buf->p < size) {
232                 int new_size = buf->end - buf->buf + size + 32;
233                 char *p = g_realloc (buf->buf, new_size);
234                 size = buf->p - buf->buf;
235                 buf->buf = p;
236                 buf->p = p + size;
237                 buf->end = buf->buf + new_size;
238         }
239 }
240
241 static void
242 sigbuffer_add_value (SigBuffer *buf, guint32 val)
243 {
244         sigbuffer_make_room (buf, 6);
245         mono_metadata_encode_value (val, buf->p, &buf->p);
246 }
247
248 static void
249 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
250 {
251         sigbuffer_make_room (buf, 1);
252         buf->p [0] = val;
253         buf->p++;
254 }
255
256 static void
257 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
258 {
259         sigbuffer_make_room (buf, size);
260         memcpy (buf->p, p, size);
261         buf->p += size;
262 }
263
264 static void
265 sigbuffer_free (SigBuffer *buf)
266 {
267         g_free (buf->buf);
268 }
269
270 #ifndef DISABLE_REFLECTION_EMIT
271 /**
272  * mp_g_alloc:
273  *
274  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
275  * from the C heap.
276  */
277 static gpointer
278 image_g_malloc (MonoImage *image, guint size)
279 {
280         if (image)
281                 return mono_image_alloc (image, size);
282         else
283                 return g_malloc (size);
284 }
285 #endif /* !DISABLE_REFLECTION_EMIT */
286
287 /**
288  * image_g_alloc0:
289  *
290  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
291  * from the C heap.
292  */
293 static gpointer
294 image_g_malloc0 (MonoImage *image, guint size)
295 {
296         if (image)
297                 return mono_image_alloc0 (image, size);
298         else
299                 return g_malloc0 (size);
300 }
301
302 #ifndef DISABLE_REFLECTION_EMIT
303 static char*
304 image_strdup (MonoImage *image, const char *s)
305 {
306         if (image)
307                 return mono_image_strdup (image, s);
308         else
309                 return g_strdup (s);
310 }
311 #endif
312
313 #define image_g_new(image,struct_type, n_structs)               \
314     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
315
316 #define image_g_new0(image,struct_type, n_structs)              \
317     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318
319
320 static void
321 alloc_table (MonoDynamicTable *table, guint nrows)
322 {
323         table->rows = nrows;
324         g_assert (table->columns);
325         if (nrows + 1 >= table->alloc_rows) {
326                 while (nrows + 1 >= table->alloc_rows) {
327                         if (table->alloc_rows == 0)
328                                 table->alloc_rows = 16;
329                         else
330                                 table->alloc_rows *= 2;
331                 }
332
333                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
334         }
335 }
336
337 static void
338 make_room_in_stream (MonoDynamicStream *stream, int size)
339 {
340         if (size <= stream->alloc_size)
341                 return;
342         
343         while (stream->alloc_size <= size) {
344                 if (stream->alloc_size < 4096)
345                         stream->alloc_size = 4096;
346                 else
347                         stream->alloc_size *= 2;
348         }
349         
350         stream->data = g_realloc (stream->data, stream->alloc_size);
351 }
352
353 static guint32
354 string_heap_insert (MonoDynamicStream *sh, const char *str)
355 {
356         guint32 idx;
357         guint32 len;
358         gpointer oldkey, oldval;
359
360         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
361                 return GPOINTER_TO_UINT (oldval);
362
363         len = strlen (str) + 1;
364         idx = sh->index;
365         
366         make_room_in_stream (sh, idx + len);
367
368         /*
369          * We strdup the string even if we already copy them in sh->data
370          * so that the string pointers in the hash remain valid even if
371          * we need to realloc sh->data. We may want to avoid that later.
372          */
373         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
374         memcpy (sh->data + idx, str, len);
375         sh->index += len;
376         return idx;
377 }
378
379 static guint32
380 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
381 {
382         char *name = mono_string_to_utf8 (str);
383         guint32 idx;
384         idx = string_heap_insert (sh, name);
385         g_free (name);
386         return idx;
387 }
388
389 #ifndef DISABLE_REFLECTION_EMIT
390 static void
391 string_heap_init (MonoDynamicStream *sh)
392 {
393         sh->index = 0;
394         sh->alloc_size = 4096;
395         sh->data = g_malloc (4096);
396         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
397         string_heap_insert (sh, "");
398 }
399 #endif
400
401 static guint32
402 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
403 {
404         guint32 idx;
405         
406         make_room_in_stream (stream, stream->index + len);
407         memcpy (stream->data + stream->index, data, len);
408         idx = stream->index;
409         stream->index += len;
410         /* 
411          * align index? Not without adding an additional param that controls it since
412          * we may store a blob value in pieces.
413          */
414         return idx;
415 }
416
417 static guint32
418 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
419 {
420         guint32 idx;
421         
422         make_room_in_stream (stream, stream->index + len);
423         memset (stream->data + stream->index, 0, len);
424         idx = stream->index;
425         stream->index += len;
426         return idx;
427 }
428
429 static void
430 stream_data_align (MonoDynamicStream *stream)
431 {
432         char buf [4] = {0};
433         guint32 count = stream->index % 4;
434
435         /* we assume the stream data will be aligned */
436         if (count)
437                 mono_image_add_stream_data (stream, buf, 4 - count);
438 }
439
440 #ifndef DISABLE_REFLECTION_EMIT
441 static int
442 mono_blob_entry_hash (const char* str)
443 {
444         guint len, h;
445         const char *end;
446         len = mono_metadata_decode_blob_size (str, &str);
447         if (len > 0) {
448                 end = str + len;
449                 h = *str;
450                 for (str += 1; str < end; str++)
451                         h = (h << 5) - h + *str;
452                 return h;
453         } else {
454                 return 0;
455         }
456 }
457
458 static gboolean
459 mono_blob_entry_equal (const char *str1, const char *str2) {
460         int len, len2;
461         const char *end1;
462         const char *end2;
463         len = mono_metadata_decode_blob_size (str1, &end1);
464         len2 = mono_metadata_decode_blob_size (str2, &end2);
465         if (len != len2)
466                 return 0;
467         return memcmp (end1, end2, len) == 0;
468 }
469 #endif
470 static guint32
471 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
472 {
473         guint32 idx;
474         char *copy;
475         gpointer oldkey, oldval;
476
477         copy = g_malloc (s1+s2);
478         memcpy (copy, b1, s1);
479         memcpy (copy + s1, b2, s2);
480         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
481                 g_free (copy);
482                 idx = GPOINTER_TO_UINT (oldval);
483         } else {
484                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
485                 mono_image_add_stream_data (&assembly->blob, b2, s2);
486                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
487         }
488         return idx;
489 }
490
491 static guint32
492 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
493 {
494         char blob_size [8];
495         char *b = blob_size;
496         guint32 size = buf->p - buf->buf;
497         /* store length */
498         g_assert (size <= (buf->end - buf->buf));
499         mono_metadata_encode_value (size, b, &b);
500         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
501 }
502
503 /*
504  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
505  * dest may be misaligned.
506  */
507 static void
508 swap_with_size (char *dest, const char* val, int len, int nelem) {
509 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
510         int elem;
511
512         for (elem = 0; elem < nelem; ++elem) {
513                 switch (len) {
514                 case 1:
515                         *dest = *val;
516                         break;
517                 case 2:
518                         dest [0] = val [1];
519                         dest [1] = val [0];
520                         break;
521                 case 4:
522                         dest [0] = val [3];
523                         dest [1] = val [2];
524                         dest [2] = val [1];
525                         dest [3] = val [0];
526                         break;
527                 case 8:
528                         dest [0] = val [7];
529                         dest [1] = val [6];
530                         dest [2] = val [5];
531                         dest [3] = val [4];
532                         dest [4] = val [3];
533                         dest [5] = val [2];
534                         dest [6] = val [1];
535                         dest [7] = val [0];
536                         break;
537                 default:
538                         g_assert_not_reached ();
539                 }
540                 dest += len;
541                 val += len;
542         }
543 #else
544         memcpy (dest, val, len * nelem);
545 #endif
546 }
547
548 static guint32
549 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
550 {
551         char blob_size [64];
552         char *b = blob_size;
553         guint32 idx = 0, len;
554
555         len = str->length * 2;
556         mono_metadata_encode_value (len, b, &b);
557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
558         {
559                 char *swapped = g_malloc (2 * mono_string_length (str));
560                 const char *p = (const char*)mono_string_chars (str);
561
562                 swap_with_size (swapped, p, 2, mono_string_length (str));
563                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
564                 g_free (swapped);
565         }
566 #else
567         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
568 #endif
569         return idx;
570 }
571
572 #ifndef DISABLE_REFLECTION_EMIT
573 static MonoClass *
574 default_class_from_mono_type (MonoType *type)
575 {
576         switch (type->type) {
577         case MONO_TYPE_OBJECT:
578                 return mono_defaults.object_class;
579         case MONO_TYPE_VOID:
580                 return mono_defaults.void_class;
581         case MONO_TYPE_BOOLEAN:
582                 return mono_defaults.boolean_class;
583         case MONO_TYPE_CHAR:
584                 return mono_defaults.char_class;
585         case MONO_TYPE_I1:
586                 return mono_defaults.sbyte_class;
587         case MONO_TYPE_U1:
588                 return mono_defaults.byte_class;
589         case MONO_TYPE_I2:
590                 return mono_defaults.int16_class;
591         case MONO_TYPE_U2:
592                 return mono_defaults.uint16_class;
593         case MONO_TYPE_I4:
594                 return mono_defaults.int32_class;
595         case MONO_TYPE_U4:
596                 return mono_defaults.uint32_class;
597         case MONO_TYPE_I:
598                 return mono_defaults.int_class;
599         case MONO_TYPE_U:
600                 return mono_defaults.uint_class;
601         case MONO_TYPE_I8:
602                 return mono_defaults.int64_class;
603         case MONO_TYPE_U8:
604                 return mono_defaults.uint64_class;
605         case MONO_TYPE_R4:
606                 return mono_defaults.single_class;
607         case MONO_TYPE_R8:
608                 return mono_defaults.double_class;
609         case MONO_TYPE_STRING:
610                 return mono_defaults.string_class;
611         default:
612                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
613                 g_assert_not_reached ();
614         }
615         
616         return NULL;
617 }
618 #endif
619
620 /*
621  * mono_class_get_ref_info:
622  *
623  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
624  */
625 gpointer
626 mono_class_get_ref_info (MonoClass *klass)
627 {
628         if (klass->ref_info_handle == 0)
629                 return NULL;
630         else
631                 return mono_gchandle_get_target (klass->ref_info_handle);
632 }
633
634 void
635 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
636 {
637         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
638         g_assert (klass->ref_info_handle != 0);
639 }
640
641 void
642 mono_class_free_ref_info (MonoClass *klass)
643 {
644         if (klass->ref_info_handle) {
645                 mono_gchandle_free (klass->ref_info_handle);
646                 klass->ref_info_handle = 0;
647         }
648 }
649
650 static void
651 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
652 {
653         int i;
654         MonoGenericInst *class_inst;
655         MonoClass *klass;
656
657         g_assert (gclass);
658
659         class_inst = gclass->context.class_inst;
660
661         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
662         klass = gclass->container_class;
663         sigbuffer_add_value (buf, klass->byval_arg.type);
664         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
665
666         sigbuffer_add_value (buf, class_inst->type_argc);
667         for (i = 0; i < class_inst->type_argc; ++i)
668                 encode_type (assembly, class_inst->type_argv [i], buf);
669
670 }
671
672 static void
673 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
674 {
675         if (!type) {
676                 g_assert_not_reached ();
677                 return;
678         }
679                 
680         if (type->byref)
681                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
682
683         switch (type->type){
684         case MONO_TYPE_VOID:
685         case MONO_TYPE_BOOLEAN:
686         case MONO_TYPE_CHAR:
687         case MONO_TYPE_I1:
688         case MONO_TYPE_U1:
689         case MONO_TYPE_I2:
690         case MONO_TYPE_U2:
691         case MONO_TYPE_I4:
692         case MONO_TYPE_U4:
693         case MONO_TYPE_I8:
694         case MONO_TYPE_U8:
695         case MONO_TYPE_R4:
696         case MONO_TYPE_R8:
697         case MONO_TYPE_I:
698         case MONO_TYPE_U:
699         case MONO_TYPE_STRING:
700         case MONO_TYPE_OBJECT:
701         case MONO_TYPE_TYPEDBYREF:
702                 sigbuffer_add_value (buf, type->type);
703                 break;
704         case MONO_TYPE_PTR:
705                 sigbuffer_add_value (buf, type->type);
706                 encode_type (assembly, type->data.type, buf);
707                 break;
708         case MONO_TYPE_SZARRAY:
709                 sigbuffer_add_value (buf, type->type);
710                 encode_type (assembly, &type->data.klass->byval_arg, buf);
711                 break;
712         case MONO_TYPE_VALUETYPE:
713         case MONO_TYPE_CLASS: {
714                 MonoClass *k = mono_class_from_mono_type (type);
715
716                 if (k->generic_container) {
717                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
718                         encode_generic_class (assembly, gclass, buf);
719                 } else {
720                         /*
721                          * Make sure we use the correct type.
722                          */
723                         sigbuffer_add_value (buf, k->byval_arg.type);
724                         /*
725                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
726                          * otherwise two typerefs could point to the same type, leading to
727                          * verification errors.
728                          */
729                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
730                 }
731                 break;
732         }
733         case MONO_TYPE_ARRAY:
734                 sigbuffer_add_value (buf, type->type);
735                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
736                 sigbuffer_add_value (buf, type->data.array->rank);
737                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
738                 sigbuffer_add_value (buf, 0);
739                 break;
740         case MONO_TYPE_GENERICINST:
741                 encode_generic_class (assembly, type->data.generic_class, buf);
742                 break;
743         case MONO_TYPE_VAR:
744         case MONO_TYPE_MVAR:
745                 sigbuffer_add_value (buf, type->type);
746                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
747                 break;
748         default:
749                 g_error ("need to encode type %x", type->type);
750         }
751 }
752
753 static void
754 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
755 {
756         if (!type) {
757                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
758                 return;
759         }
760
761         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
762 }
763
764 static void
765 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
766 {
767         int i;
768
769         if (modreq) {
770                 for (i = 0; i < mono_array_length (modreq); ++i) {
771                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
772                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
773                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
774                 }
775         }
776         if (modopt) {
777                 for (i = 0; i < mono_array_length (modopt); ++i) {
778                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
779                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
780                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
781                 }
782         }
783 }
784
785 #ifndef DISABLE_REFLECTION_EMIT
786 static guint32
787 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
788 {
789         SigBuffer buf;
790         int i;
791         guint32 nparams =  sig->param_count;
792         guint32 idx;
793
794         if (!assembly->save)
795                 return 0;
796
797         sigbuffer_init (&buf, 32);
798         /*
799          * FIXME: vararg, explicit_this, differenc call_conv values...
800          */
801         idx = sig->call_convention;
802         if (sig->hasthis)
803                 idx |= 0x20; /* hasthis */
804         if (sig->generic_param_count)
805                 idx |= 0x10; /* generic */
806         sigbuffer_add_byte (&buf, idx);
807         if (sig->generic_param_count)
808                 sigbuffer_add_value (&buf, sig->generic_param_count);
809         sigbuffer_add_value (&buf, nparams);
810         encode_type (assembly, sig->ret, &buf);
811         for (i = 0; i < nparams; ++i) {
812                 if (i == sig->sentinelpos)
813                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814                 encode_type (assembly, sig->params [i], &buf);
815         }
816         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
817         sigbuffer_free (&buf);
818         return idx;
819 }
820 #endif
821
822 static guint32
823 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
824 {
825         /*
826          * FIXME: reuse code from method_encode_signature().
827          */
828         SigBuffer buf;
829         int i;
830         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
831         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
832         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
833         guint32 idx;
834
835         sigbuffer_init (&buf, 32);
836         /* LAMESPEC: all the call conv spec is foobared */
837         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
838         if (mb->call_conv & 2)
839                 idx |= 0x5; /* vararg */
840         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
841                 idx |= 0x20; /* hasthis */
842         if (ngparams)
843                 idx |= 0x10; /* generic */
844         sigbuffer_add_byte (&buf, idx);
845         if (ngparams)
846                 sigbuffer_add_value (&buf, ngparams);
847         sigbuffer_add_value (&buf, nparams + notypes);
848         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
849         encode_reflection_type (assembly, mb->rtype, &buf);
850         for (i = 0; i < nparams; ++i) {
851                 MonoArray *modreq = NULL;
852                 MonoArray *modopt = NULL;
853                 MonoReflectionType *pt;
854
855                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
856                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
857                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
858                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
859                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
860                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
861                 encode_reflection_type (assembly, pt, &buf);
862         }
863         if (notypes)
864                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
865         for (i = 0; i < notypes; ++i) {
866                 MonoReflectionType *pt;
867
868                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
869                 encode_reflection_type (assembly, pt, &buf);
870         }
871
872         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
873         sigbuffer_free (&buf);
874         return idx;
875 }
876
877 static guint32
878 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
879 {
880         MonoDynamicTable *table;
881         guint32 *values;
882         guint32 idx, sig_idx;
883         guint nl = mono_array_length (ilgen->locals);
884         SigBuffer buf;
885         int i;
886
887         sigbuffer_init (&buf, 32);
888         sigbuffer_add_value (&buf, 0x07);
889         sigbuffer_add_value (&buf, nl);
890         for (i = 0; i < nl; ++i) {
891                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
892                 
893                 if (lb->is_pinned)
894                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
895                 
896                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
897         }
898         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
899         sigbuffer_free (&buf);
900
901         if (assembly->standalonesig_cache == NULL)
902                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
903         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
904         if (idx)
905                 return idx;
906
907         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
908         idx = table->next_idx ++;
909         table->rows ++;
910         alloc_table (table, table->rows);
911         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
912
913         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
914
915         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
916
917         return idx;
918 }
919
920 static guint32
921 method_count_clauses (MonoReflectionILGen *ilgen)
922 {
923         guint32 num_clauses = 0;
924         int i;
925
926         MonoILExceptionInfo *ex_info;
927         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
928                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
929                 if (ex_info->handlers)
930                         num_clauses += mono_array_length (ex_info->handlers);
931                 else
932                         num_clauses++;
933         }
934
935         return num_clauses;
936 }
937
938 #ifndef DISABLE_REFLECTION_EMIT
939 static MonoExceptionClause*
940 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
941 {
942         MonoExceptionClause *clauses;
943         MonoExceptionClause *clause;
944         MonoILExceptionInfo *ex_info;
945         MonoILExceptionBlock *ex_block;
946         guint32 finally_start;
947         int i, j, clause_index;;
948
949         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
950
951         clause_index = 0;
952         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
953                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
954                 finally_start = ex_info->start + ex_info->len;
955                 if (!ex_info->handlers)
956                         continue;
957                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
958                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
959                         clause = &(clauses [clause_index]);
960
961                         clause->flags = ex_block->type;
962                         clause->try_offset = ex_info->start;
963
964                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
965                                 clause->try_len = finally_start - ex_info->start;
966                         else
967                                 clause->try_len = ex_info->len;
968                         clause->handler_offset = ex_block->start;
969                         clause->handler_len = ex_block->len;
970                         if (ex_block->extype) {
971                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
972                         } else {
973                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
974                                         clause->data.filter_offset = ex_block->filter_offset;
975                                 else
976                                         clause->data.filter_offset = 0;
977                         }
978                         finally_start = ex_block->start + ex_block->len;
979
980                         clause_index ++;
981                 }
982         }
983
984         return clauses;
985 }
986 #endif /* !DISABLE_REFLECTION_EMIT */
987
988 static guint32
989 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
990 {
991         char flags = 0;
992         guint32 idx;
993         guint32 code_size;
994         gint32 max_stack, i;
995         gint32 num_locals = 0;
996         gint32 num_exception = 0;
997         gint maybe_small;
998         guint32 fat_flags;
999         char fat_header [12];
1000         guint32 int_value;
1001         guint16 short_value;
1002         guint32 local_sig = 0;
1003         guint32 header_size = 12;
1004         MonoArray *code;
1005
1006         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1007                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1008                 return 0;
1009
1010         /*if (mb->name)
1011                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1012         if (mb->ilgen) {
1013                 code = mb->ilgen->code;
1014                 code_size = mb->ilgen->code_len;
1015                 max_stack = mb->ilgen->max_stack;
1016                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1017                 if (mb->ilgen->ex_handlers)
1018                         num_exception = method_count_clauses (mb->ilgen);
1019         } else {
1020                 code = mb->code;
1021                 if (code == NULL){
1022                         char *name = mono_string_to_utf8 (mb->name);
1023                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1024                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1025                         g_free (str);
1026                         g_free (name);
1027                         mono_raise_exception (exception);
1028                 }
1029
1030                 code_size = mono_array_length (code);
1031                 max_stack = 8; /* we probably need to run a verifier on the code... */
1032         }
1033
1034         stream_data_align (&assembly->code);
1035
1036         /* check for exceptions, maxstack, locals */
1037         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1038         if (maybe_small) {
1039                 if (code_size < 64 && !(code_size & 1)) {
1040                         flags = (code_size << 2) | 0x2;
1041                 } else if (code_size < 32 && (code_size & 1)) {
1042                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1043                 } else {
1044                         goto fat_header;
1045                 }
1046                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1047                 /* add to the fixup todo list */
1048                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1049                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1050                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1051                 return assembly->text_rva + idx;
1052         } 
1053 fat_header:
1054         if (num_locals)
1055                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1056         /* 
1057          * FIXME: need to set also the header size in fat_flags.
1058          * (and more sects and init locals flags)
1059          */
1060         fat_flags =  0x03;
1061         if (num_exception)
1062                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1063         if (mb->init_locals)
1064                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1065         fat_header [0] = fat_flags;
1066         fat_header [1] = (header_size / 4 ) << 4;
1067         short_value = GUINT16_TO_LE (max_stack);
1068         memcpy (fat_header + 2, &short_value, 2);
1069         int_value = GUINT32_TO_LE (code_size);
1070         memcpy (fat_header + 4, &int_value, 4);
1071         int_value = GUINT32_TO_LE (local_sig);
1072         memcpy (fat_header + 8, &int_value, 4);
1073         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1074         /* add to the fixup todo list */
1075         if (mb->ilgen && mb->ilgen->num_token_fixups)
1076                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1077         
1078         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1079         if (num_exception) {
1080                 unsigned char sheader [4];
1081                 MonoILExceptionInfo * ex_info;
1082                 MonoILExceptionBlock * ex_block;
1083                 int j;
1084
1085                 stream_data_align (&assembly->code);
1086                 /* always use fat format for now */
1087                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1088                 num_exception *= 6 * sizeof (guint32);
1089                 num_exception += 4; /* include the size of the header */
1090                 sheader [1] = num_exception & 0xff;
1091                 sheader [2] = (num_exception >> 8) & 0xff;
1092                 sheader [3] = (num_exception >> 16) & 0xff;
1093                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1094                 /* fat header, so we are already aligned */
1095                 /* reverse order */
1096                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1097                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1098                         if (ex_info->handlers) {
1099                                 int finally_start = ex_info->start + ex_info->len;
1100                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1101                                         guint32 val;
1102                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1103                                         /* the flags */
1104                                         val = GUINT32_TO_LE (ex_block->type);
1105                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1106                                         /* try offset */
1107                                         val = GUINT32_TO_LE (ex_info->start);
1108                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109                                         /* need fault, too, probably */
1110                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1111                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1112                                         else
1113                                                 val = GUINT32_TO_LE (ex_info->len);
1114                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1115                                         /* handler offset */
1116                                         val = GUINT32_TO_LE (ex_block->start);
1117                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118                                         /* handler len */
1119                                         val = GUINT32_TO_LE (ex_block->len);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         finally_start = ex_block->start + ex_block->len;
1122                                         if (ex_block->extype) {
1123                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1124                                         } else {
1125                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1126                                                         val = ex_block->filter_offset;
1127                                                 else
1128                                                         val = 0;
1129                                         }
1130                                         val = GUINT32_TO_LE (val);
1131                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1132                                         /*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", 
1133                                                         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);*/
1134                                 }
1135                         } else {
1136                                 g_error ("No clauses for ex info block %d", i);
1137                         }
1138                 }
1139         }
1140         return assembly->text_rva + idx;
1141 }
1142
1143 static guint32
1144 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1145 {
1146         int i;
1147         MonoDynamicTable *table;
1148         guint32 *values;
1149         
1150         table = &assembly->tables [table_idx];
1151
1152         g_assert (col < table->columns);
1153
1154         values = table->values + table->columns;
1155         for (i = 1; i <= table->rows; ++i) {
1156                 if (values [col] == token)
1157                         return i;
1158                 values += table->columns;
1159         }
1160         return 0;
1161 }
1162
1163 /*
1164  * LOCKING: Acquires the loader lock. 
1165  */
1166 static MonoCustomAttrInfo*
1167 lookup_custom_attr (MonoImage *image, gpointer member)
1168 {
1169         MonoCustomAttrInfo* res;
1170
1171         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1172
1173         if (!res)
1174                 return NULL;
1175
1176         return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1177 }
1178
1179 static gboolean
1180 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1181 {
1182         /* FIXME: Need to do more checks */
1183         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1184                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1185
1186                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1187                         return FALSE;
1188         }
1189
1190         return TRUE;
1191 }
1192
1193 static MonoCustomAttrInfo*
1194 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1195 {
1196         int i, index, count, not_visible;
1197         MonoCustomAttrInfo *ainfo;
1198         MonoReflectionCustomAttr *cattr;
1199
1200         if (!cattrs)
1201                 return NULL;
1202         /* FIXME: check in assembly the Run flag is set */
1203
1204         count = mono_array_length (cattrs);
1205
1206         /* Skip nonpublic attributes since MS.NET seems to do the same */
1207         /* FIXME: This needs to be done more globally */
1208         not_visible = 0;
1209         for (i = 0; i < count; ++i) {
1210                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1211                 if (!custom_attr_visible (image, cattr))
1212                         not_visible ++;
1213         }
1214         count -= not_visible;
1215
1216         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1217
1218         ainfo->image = image;
1219         ainfo->num_attrs = count;
1220         ainfo->cached = alloc_img != NULL;
1221         index = 0;
1222         for (i = 0; i < count; ++i) {
1223                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1224                 if (custom_attr_visible (image, cattr)) {
1225                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1226                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1227                         ainfo->attrs [index].ctor = cattr->ctor->method;
1228                         ainfo->attrs [index].data = saved;
1229                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1230                         index ++;
1231                 }
1232         }
1233
1234         return ainfo;
1235 }
1236
1237 #ifndef DISABLE_REFLECTION_EMIT
1238 /*
1239  * LOCKING: Acquires the loader lock. 
1240  */
1241 static void
1242 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1243 {
1244         MonoCustomAttrInfo *ainfo, *tmp;
1245
1246         if (!cattrs || !mono_array_length (cattrs))
1247                 return;
1248
1249         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1250
1251         mono_loader_lock ();
1252         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1253         if (tmp)
1254                 mono_custom_attrs_free (tmp);
1255         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1256         mono_loader_unlock ();
1257
1258 }
1259 #endif
1260
1261 void
1262 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1263 {
1264         if (!ainfo->cached)
1265                 g_free (ainfo);
1266 }
1267
1268 /*
1269  * idx is the table index of the object
1270  * type is one of MONO_CUSTOM_ATTR_*
1271  */
1272 static void
1273 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1274 {
1275         MonoDynamicTable *table;
1276         MonoReflectionCustomAttr *cattr;
1277         guint32 *values;
1278         guint32 count, i, token;
1279         char blob_size [6];
1280         char *p = blob_size;
1281         
1282         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1283         if (!cattrs)
1284                 return;
1285         count = mono_array_length (cattrs);
1286         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1287         table->rows += count;
1288         alloc_table (table, table->rows);
1289         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1290         idx <<= MONO_CUSTOM_ATTR_BITS;
1291         idx |= type;
1292         for (i = 0; i < count; ++i) {
1293                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1294                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1295                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1296                 type = mono_metadata_token_index (token);
1297                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1298                 switch (mono_metadata_token_table (token)) {
1299                 case MONO_TABLE_METHOD:
1300                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1301                         break;
1302                 case MONO_TABLE_MEMBERREF:
1303                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1304                         break;
1305                 default:
1306                         g_warning ("got wrong token in custom attr");
1307                         continue;
1308                 }
1309                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1310                 p = blob_size;
1311                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1312                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1313                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1314                 values += MONO_CUSTOM_ATTR_SIZE;
1315                 ++table->next_idx;
1316         }
1317 }
1318
1319 static void
1320 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1321 {
1322         MonoDynamicTable *table;
1323         guint32 *values;
1324         guint32 count, i, idx;
1325         MonoReflectionPermissionSet *perm;
1326
1327         if (!permissions)
1328                 return;
1329
1330         count = mono_array_length (permissions);
1331         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1332         table->rows += count;
1333         alloc_table (table, table->rows);
1334
1335         for (i = 0; i < mono_array_length (permissions); ++i) {
1336                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1337
1338                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1339
1340                 idx = mono_metadata_token_index (parent_token);
1341                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1342                 switch (mono_metadata_token_table (parent_token)) {
1343                 case MONO_TABLE_TYPEDEF:
1344                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1345                         break;
1346                 case MONO_TABLE_METHOD:
1347                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1348                         break;
1349                 case MONO_TABLE_ASSEMBLY:
1350                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1351                         break;
1352                 default:
1353                         g_assert_not_reached ();
1354                 }
1355
1356                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1357                 values [MONO_DECL_SECURITY_PARENT] = idx;
1358                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1359
1360                 ++table->next_idx;
1361         }
1362 }
1363
1364 /*
1365  * Fill in the MethodDef and ParamDef tables for a method.
1366  * This is used for both normal methods and constructors.
1367  */
1368 static void
1369 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1370 {
1371         MonoDynamicTable *table;
1372         guint32 *values;
1373         guint i, count;
1374
1375         /* room in this table is already allocated */
1376         table = &assembly->tables [MONO_TABLE_METHOD];
1377         *mb->table_idx = table->next_idx ++;
1378         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1379         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1380         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1381         values [MONO_METHOD_FLAGS] = mb->attrs;
1382         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1383         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1384         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1385         
1386         table = &assembly->tables [MONO_TABLE_PARAM];
1387         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1388
1389         mono_image_add_decl_security (assembly, 
1390                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1391
1392         if (mb->pinfo) {
1393                 MonoDynamicTable *mtable;
1394                 guint32 *mvalues;
1395                 
1396                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1397                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1398                 
1399                 count = 0;
1400                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1401                         if (mono_array_get (mb->pinfo, gpointer, i))
1402                                 count++;
1403                 }
1404                 table->rows += count;
1405                 alloc_table (table, table->rows);
1406                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1407                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1408                         MonoReflectionParamBuilder *pb;
1409                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1410                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1411                                 values [MONO_PARAM_SEQUENCE] = i;
1412                                 if (pb->name != NULL) {
1413                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1414                                 } else {
1415                                         values [MONO_PARAM_NAME] = 0;
1416                                 }
1417                                 values += MONO_PARAM_SIZE;
1418                                 if (pb->marshal_info) {
1419                                         mtable->rows++;
1420                                         alloc_table (mtable, mtable->rows);
1421                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1422                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1423                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1424                                 }
1425                                 pb->table_idx = table->next_idx++;
1426                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1427                                         guint32 field_type = 0;
1428                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1429                                         mtable->rows ++;
1430                                         alloc_table (mtable, mtable->rows);
1431                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1432                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1433                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1434                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1435                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1436                                 }
1437                         }
1438                 }
1439         }
1440 }
1441
1442 #ifndef DISABLE_REFLECTION_EMIT
1443 static void
1444 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1445 {
1446         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1447
1448         rmb->ilgen = mb->ilgen;
1449         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1450         rmb->parameters = mb->parameters;
1451         rmb->generic_params = mb->generic_params;
1452         rmb->generic_container = mb->generic_container;
1453         rmb->opt_types = NULL;
1454         rmb->pinfo = mb->pinfo;
1455         rmb->attrs = mb->attrs;
1456         rmb->iattrs = mb->iattrs;
1457         rmb->call_conv = mb->call_conv;
1458         rmb->code = mb->code;
1459         rmb->type = mb->type;
1460         rmb->name = mb->name;
1461         rmb->table_idx = &mb->table_idx;
1462         rmb->init_locals = mb->init_locals;
1463         rmb->skip_visibility = FALSE;
1464         rmb->return_modreq = mb->return_modreq;
1465         rmb->return_modopt = mb->return_modopt;
1466         rmb->param_modreq = mb->param_modreq;
1467         rmb->param_modopt = mb->param_modopt;
1468         rmb->permissions = mb->permissions;
1469         rmb->mhandle = mb->mhandle;
1470         rmb->nrefs = 0;
1471         rmb->refs = NULL;
1472
1473         if (mb->dll) {
1474                 rmb->charset = mb->charset;
1475                 rmb->extra_flags = mb->extra_flags;
1476                 rmb->native_cc = mb->native_cc;
1477                 rmb->dllentry = mb->dllentry;
1478                 rmb->dll = mb->dll;
1479         }
1480 }
1481
1482 static void
1483 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1484 {
1485         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1486
1487         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1488
1489         rmb->ilgen = mb->ilgen;
1490         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1491         rmb->parameters = mb->parameters;
1492         rmb->generic_params = NULL;
1493         rmb->generic_container = NULL;
1494         rmb->opt_types = NULL;
1495         rmb->pinfo = mb->pinfo;
1496         rmb->attrs = mb->attrs;
1497         rmb->iattrs = mb->iattrs;
1498         rmb->call_conv = mb->call_conv;
1499         rmb->code = NULL;
1500         rmb->type = mb->type;
1501         rmb->name = mono_string_new (mono_domain_get (), name);
1502         rmb->table_idx = &mb->table_idx;
1503         rmb->init_locals = mb->init_locals;
1504         rmb->skip_visibility = FALSE;
1505         rmb->return_modreq = NULL;
1506         rmb->return_modopt = NULL;
1507         rmb->param_modreq = mb->param_modreq;
1508         rmb->param_modopt = mb->param_modopt;
1509         rmb->permissions = mb->permissions;
1510         rmb->mhandle = mb->mhandle;
1511         rmb->nrefs = 0;
1512         rmb->refs = NULL;
1513 }
1514
1515 static void
1516 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1517 {
1518         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1519
1520         rmb->ilgen = mb->ilgen;
1521         rmb->rtype = mb->rtype;
1522         rmb->parameters = mb->parameters;
1523         rmb->generic_params = NULL;
1524         rmb->generic_container = NULL;
1525         rmb->opt_types = NULL;
1526         rmb->pinfo = NULL;
1527         rmb->attrs = mb->attrs;
1528         rmb->iattrs = 0;
1529         rmb->call_conv = mb->call_conv;
1530         rmb->code = NULL;
1531         rmb->type = (MonoObject *) mb->owner;
1532         rmb->name = mb->name;
1533         rmb->table_idx = NULL;
1534         rmb->init_locals = mb->init_locals;
1535         rmb->skip_visibility = mb->skip_visibility;
1536         rmb->return_modreq = NULL;
1537         rmb->return_modopt = NULL;
1538         rmb->param_modreq = NULL;
1539         rmb->param_modopt = NULL;
1540         rmb->permissions = NULL;
1541         rmb->mhandle = mb->mhandle;
1542         rmb->nrefs = 0;
1543         rmb->refs = NULL;
1544 }       
1545 #endif
1546
1547 static void
1548 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1549 {
1550         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1551         MonoDynamicTable *table;
1552         guint32 *values;
1553         guint32 tok;
1554
1555         if (!mb->override_method)
1556                 return;
1557
1558         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1559         table->rows ++;
1560         alloc_table (table, table->rows);
1561         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1562         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1563         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1564
1565         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1566         switch (mono_metadata_token_table (tok)) {
1567         case MONO_TABLE_MEMBERREF:
1568                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1569                 break;
1570         case MONO_TABLE_METHOD:
1571                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1572                 break;
1573         default:
1574                 g_assert_not_reached ();
1575         }
1576         values [MONO_METHODIMPL_DECLARATION] = tok;
1577 }
1578
1579 #ifndef DISABLE_REFLECTION_EMIT
1580 static void
1581 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1582 {
1583         MonoDynamicTable *table;
1584         guint32 *values;
1585         ReflectionMethodBuilder rmb;
1586         int i;
1587
1588         reflection_methodbuilder_from_method_builder (&rmb, mb);
1589
1590         mono_image_basic_method (&rmb, assembly);
1591         mb->table_idx = *rmb.table_idx;
1592
1593         if (mb->dll) { /* It's a P/Invoke method */
1594                 guint32 moduleref;
1595                 /* map CharSet values to on-disk values */
1596                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1597                 int extra_flags = mb->extra_flags;
1598                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1599                 table->rows ++;
1600                 alloc_table (table, table->rows);
1601                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1602                 
1603                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1604                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1605                 if (mb->dllentry)
1606                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1607                 else
1608                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1610                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1611                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1612                         table->rows ++;
1613                         alloc_table (table, table->rows);
1614                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1615                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1616                 }
1617         }
1618
1619         if (mb->generic_params) {
1620                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1621                 table->rows += mono_array_length (mb->generic_params);
1622                 alloc_table (table, table->rows);
1623                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1624                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1625
1626                         mono_image_get_generic_param_info (
1627                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1628                 }
1629         }
1630
1631 }
1632
1633 static void
1634 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1635 {
1636         ReflectionMethodBuilder rmb;
1637
1638         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1639
1640         mono_image_basic_method (&rmb, assembly);
1641         mb->table_idx = *rmb.table_idx;
1642 }
1643 #endif
1644
1645 static char*
1646 type_get_fully_qualified_name (MonoType *type)
1647 {
1648         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1649 }
1650
1651 static char*
1652 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1653         MonoClass *klass;
1654         MonoAssembly *ta;
1655
1656         klass = mono_class_from_mono_type (type);
1657         if (!klass) 
1658                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1659         ta = klass->image->assembly;
1660         if (ta->dynamic || (ta == ass)) {
1661                 if (klass->generic_class || klass->generic_container)
1662                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1663                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1664                 else
1665                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1666         }
1667
1668         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1669 }
1670
1671 #ifndef DISABLE_REFLECTION_EMIT
1672 /*field_image is the image to which the eventual custom mods have been encoded against*/
1673 static guint32
1674 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1675 {
1676         SigBuffer buf;
1677         guint32 idx, i, token;
1678
1679         if (!assembly->save)
1680                 return 0;
1681
1682         sigbuffer_init (&buf, 32);
1683         
1684         sigbuffer_add_value (&buf, 0x06);
1685         /* encode custom attributes before the type */
1686         if (type->num_mods) {
1687                 for (i = 0; i < type->num_mods; ++i) {
1688                         if (field_image) {
1689                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1690                                 g_assert (class);
1691                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1692                         } else {
1693                                 token = type->modifiers [i].token;
1694                         }
1695
1696                         if (type->modifiers [i].required)
1697                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1698                         else
1699                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1700
1701                         sigbuffer_add_value (&buf, token);
1702                 }
1703         }
1704         encode_type (assembly, type, &buf);
1705         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1706         sigbuffer_free (&buf);
1707         return idx;
1708 }
1709 #endif
1710
1711 static guint32
1712 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1713 {
1714         SigBuffer buf;
1715         guint32 idx;
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         encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1723         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724         sigbuffer_free (&buf);
1725         return idx;
1726 }
1727
1728 static guint32
1729 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1730         char blob_size [64];
1731         char *b = blob_size;
1732         char *p, *box_val;
1733         char* buf;
1734         guint32 idx = 0, len = 0, dummy = 0;
1735 #ifdef ARM_FPU_FPA
1736 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1737         guint32 fpa_double [2];
1738         guint32 *fpa_p;
1739 #endif
1740 #endif
1741         
1742         p = buf = g_malloc (64);
1743         if (!val) {
1744                 *ret_type = MONO_TYPE_CLASS;
1745                 len = 4;
1746                 box_val = (char*)&dummy;
1747         } else {
1748                 box_val = ((char*)val) + sizeof (MonoObject);
1749                 *ret_type = val->vtable->klass->byval_arg.type;
1750         }
1751 handle_enum:
1752         switch (*ret_type) {
1753         case MONO_TYPE_BOOLEAN:
1754         case MONO_TYPE_U1:
1755         case MONO_TYPE_I1:
1756                 len = 1;
1757                 break;
1758         case MONO_TYPE_CHAR:
1759         case MONO_TYPE_U2:
1760         case MONO_TYPE_I2:
1761                 len = 2;
1762                 break;
1763         case MONO_TYPE_U4:
1764         case MONO_TYPE_I4:
1765         case MONO_TYPE_R4:
1766                 len = 4;
1767                 break;
1768         case MONO_TYPE_U8:
1769         case MONO_TYPE_I8:
1770                 len = 8;
1771                 break;
1772         case MONO_TYPE_R8:
1773                 len = 8;
1774 #ifdef ARM_FPU_FPA
1775 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1776                 fpa_p = (guint32*)box_val;
1777                 fpa_double [0] = fpa_p [1];
1778                 fpa_double [1] = fpa_p [0];
1779                 box_val = (char*)fpa_double;
1780 #endif
1781 #endif
1782                 break;
1783         case MONO_TYPE_VALUETYPE: {
1784                 MonoClass *klass = val->vtable->klass;
1785                 
1786                 if (klass->enumtype) {
1787                         *ret_type = mono_class_enum_basetype (klass)->type;
1788                         goto handle_enum;
1789                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1790                         len = 8;
1791                 } else 
1792                         g_error ("we can't encode valuetypes, we should have never reached this line");
1793                 break;
1794         }
1795         case MONO_TYPE_CLASS:
1796                 break;
1797         case MONO_TYPE_STRING: {
1798                 MonoString *str = (MonoString*)val;
1799                 /* there is no signature */
1800                 len = str->length * 2;
1801                 mono_metadata_encode_value (len, b, &b);
1802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1803                 {
1804                         char *swapped = g_malloc (2 * mono_string_length (str));
1805                         const char *p = (const char*)mono_string_chars (str);
1806
1807                         swap_with_size (swapped, p, 2, mono_string_length (str));
1808                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1809                         g_free (swapped);
1810                 }
1811 #else
1812                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1813 #endif
1814
1815                 g_free (buf);
1816                 return idx;
1817         }
1818         case MONO_TYPE_GENERICINST:
1819                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1820                 goto handle_enum;
1821         default:
1822                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1823         }
1824
1825         /* there is no signature */
1826         mono_metadata_encode_value (len, b, &b);
1827 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1828         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1829         swap_with_size (blob_size, box_val, len, 1);
1830         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1831 #else
1832         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1833 #endif
1834
1835         g_free (buf);
1836         return idx;
1837 }
1838
1839 static guint32
1840 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1841         char *str;
1842         SigBuffer buf;
1843         guint32 idx, len;
1844
1845         sigbuffer_init (&buf, 32);
1846
1847         sigbuffer_add_value (&buf, minfo->type);
1848
1849         switch (minfo->type) {
1850         case MONO_NATIVE_BYVALTSTR:
1851         case MONO_NATIVE_BYVALARRAY:
1852                 sigbuffer_add_value (&buf, minfo->count);
1853                 break;
1854         case MONO_NATIVE_LPARRAY:
1855                 if (minfo->eltype || minfo->has_size) {
1856                         sigbuffer_add_value (&buf, minfo->eltype);
1857                         if (minfo->has_size) {
1858                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1859                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1860
1861                                 /* LAMESPEC: ElemMult is undocumented */
1862                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1863                         }
1864                 }
1865                 break;
1866         case MONO_NATIVE_SAFEARRAY:
1867                 if (minfo->eltype)
1868                         sigbuffer_add_value (&buf, minfo->eltype);
1869                 break;
1870         case MONO_NATIVE_CUSTOM:
1871                 if (minfo->guid) {
1872                         str = mono_string_to_utf8 (minfo->guid);
1873                         len = strlen (str);
1874                         sigbuffer_add_value (&buf, len);
1875                         sigbuffer_add_mem (&buf, str, len);
1876                         g_free (str);
1877                 } else {
1878                         sigbuffer_add_value (&buf, 0);
1879                 }
1880                 /* native type name */
1881                 sigbuffer_add_value (&buf, 0);
1882                 /* custom marshaler type name */
1883                 if (minfo->marshaltype || minfo->marshaltyperef) {
1884                         if (minfo->marshaltyperef)
1885                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1886                         else
1887                                 str = mono_string_to_utf8 (minfo->marshaltype);
1888                         len = strlen (str);
1889                         sigbuffer_add_value (&buf, len);
1890                         sigbuffer_add_mem (&buf, str, len);
1891                         g_free (str);
1892                 } else {
1893                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1894                         sigbuffer_add_value (&buf, 0);
1895                 }
1896                 if (minfo->mcookie) {
1897                         str = mono_string_to_utf8 (minfo->mcookie);
1898                         len = strlen (str);
1899                         sigbuffer_add_value (&buf, len);
1900                         sigbuffer_add_mem (&buf, str, len);
1901                         g_free (str);
1902                 } else {
1903                         sigbuffer_add_value (&buf, 0);
1904                 }
1905                 break;
1906         default:
1907                 break;
1908         }
1909         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1910         sigbuffer_free (&buf);
1911         return idx;
1912 }
1913
1914 static void
1915 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1916 {
1917         MonoDynamicTable *table;
1918         guint32 *values;
1919
1920         /* maybe this fixup should be done in the C# code */
1921         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1922                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1923         table = &assembly->tables [MONO_TABLE_FIELD];
1924         fb->table_idx = table->next_idx ++;
1925         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1926         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1927         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1928         values [MONO_FIELD_FLAGS] = fb->attrs;
1929         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1930
1931         if (fb->offset != -1) {
1932                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1933                 table->rows ++;
1934                 alloc_table (table, table->rows);
1935                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1936                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1937                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1938         }
1939         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1940                 guint32 field_type = 0;
1941                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1942                 table->rows ++;
1943                 alloc_table (table, table->rows);
1944                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1945                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1946                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1947                 values [MONO_CONSTANT_TYPE] = field_type;
1948                 values [MONO_CONSTANT_PADDING] = 0;
1949         }
1950         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1951                 guint32 rva_idx;
1952                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1953                 table->rows ++;
1954                 alloc_table (table, table->rows);
1955                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1956                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1957                 /*
1958                  * We store it in the code section because it's simpler for now.
1959                  */
1960                 if (fb->rva_data) {
1961                         if (mono_array_length (fb->rva_data) >= 10)
1962                                 stream_data_align (&assembly->code);
1963                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1964                 } else
1965                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1966                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1967         }
1968         if (fb->marshal_info) {
1969                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1970                 table->rows ++;
1971                 alloc_table (table, table->rows);
1972                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1973                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1974                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1975         }
1976 }
1977
1978 static guint32
1979 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1980 {
1981         SigBuffer buf;
1982         guint32 nparams = 0;
1983         MonoReflectionMethodBuilder *mb = fb->get_method;
1984         MonoReflectionMethodBuilder *smb = fb->set_method;
1985         guint32 idx, i;
1986
1987         if (mb && mb->parameters)
1988                 nparams = mono_array_length (mb->parameters);
1989         if (!mb && smb && smb->parameters)
1990                 nparams = mono_array_length (smb->parameters) - 1;
1991         sigbuffer_init (&buf, 32);
1992         if (fb->call_conv & 0x20)
1993                 sigbuffer_add_byte (&buf, 0x28);
1994         else
1995                 sigbuffer_add_byte (&buf, 0x08);
1996         sigbuffer_add_value (&buf, nparams);
1997         if (mb) {
1998                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1999                 for (i = 0; i < nparams; ++i) {
2000                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2001                         encode_reflection_type (assembly, pt, &buf);
2002                 }
2003         } else if (smb && smb->parameters) {
2004                 /* the property type is the last param */
2005                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2006                 for (i = 0; i < nparams; ++i) {
2007                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2008                         encode_reflection_type (assembly, pt, &buf);
2009                 }
2010         } else {
2011                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2012         }
2013
2014         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2015         sigbuffer_free (&buf);
2016         return idx;
2017 }
2018
2019 static void
2020 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2021 {
2022         MonoDynamicTable *table;
2023         guint32 *values;
2024         guint num_methods = 0;
2025         guint32 semaidx;
2026
2027         /* 
2028          * we need to set things in the following tables:
2029          * PROPERTYMAP (info already filled in _get_type_info ())
2030          * PROPERTY    (rows already preallocated in _get_type_info ())
2031          * METHOD      (method info already done with the generic method code)
2032          * METHODSEMANTICS
2033          * CONSTANT
2034          */
2035         table = &assembly->tables [MONO_TABLE_PROPERTY];
2036         pb->table_idx = table->next_idx ++;
2037         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2038         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2039         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2040         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2041
2042         /* FIXME: we still don't handle 'other' methods */
2043         if (pb->get_method) num_methods ++;
2044         if (pb->set_method) num_methods ++;
2045
2046         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2047         table->rows += num_methods;
2048         alloc_table (table, table->rows);
2049
2050         if (pb->get_method) {
2051                 semaidx = table->next_idx ++;
2052                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2053                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2054                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2055                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2056         }
2057         if (pb->set_method) {
2058                 semaidx = table->next_idx ++;
2059                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2061                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2062                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2063         }
2064         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2065                 guint32 field_type = 0;
2066                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2067                 table->rows ++;
2068                 alloc_table (table, table->rows);
2069                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2070                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2071                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2072                 values [MONO_CONSTANT_TYPE] = field_type;
2073                 values [MONO_CONSTANT_PADDING] = 0;
2074         }
2075 }
2076
2077 static void
2078 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2079 {
2080         MonoDynamicTable *table;
2081         guint32 *values;
2082         guint num_methods = 0;
2083         guint32 semaidx;
2084
2085         /* 
2086          * we need to set things in the following tables:
2087          * EVENTMAP (info already filled in _get_type_info ())
2088          * EVENT    (rows already preallocated in _get_type_info ())
2089          * METHOD      (method info already done with the generic method code)
2090          * METHODSEMANTICS
2091          */
2092         table = &assembly->tables [MONO_TABLE_EVENT];
2093         eb->table_idx = table->next_idx ++;
2094         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2095         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2096         values [MONO_EVENT_FLAGS] = eb->attrs;
2097         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2098
2099         /*
2100          * FIXME: we still don't handle 'other' methods 
2101          */
2102         if (eb->add_method) num_methods ++;
2103         if (eb->remove_method) num_methods ++;
2104         if (eb->raise_method) num_methods ++;
2105
2106         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2107         table->rows += num_methods;
2108         alloc_table (table, table->rows);
2109
2110         if (eb->add_method) {
2111                 semaidx = table->next_idx ++;
2112                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2113                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2114                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2115                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2116         }
2117         if (eb->remove_method) {
2118                 semaidx = table->next_idx ++;
2119                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2120                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2121                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2122                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2123         }
2124         if (eb->raise_method) {
2125                 semaidx = table->next_idx ++;
2126                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2127                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2128                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2129                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2130         }
2131 }
2132
2133 static void
2134 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2135 {
2136         MonoDynamicTable *table;
2137         guint32 num_constraints, i;
2138         guint32 *values;
2139         guint32 table_idx;
2140
2141         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2142         num_constraints = gparam->iface_constraints ?
2143                 mono_array_length (gparam->iface_constraints) : 0;
2144         table->rows += num_constraints;
2145         if (gparam->base_type)
2146                 table->rows++;
2147         alloc_table (table, table->rows);
2148
2149         if (gparam->base_type) {
2150                 table_idx = table->next_idx ++;
2151                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2152
2153                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2154                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2155                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2156         }
2157
2158         for (i = 0; i < num_constraints; i++) {
2159                 MonoReflectionType *constraint = mono_array_get (
2160                         gparam->iface_constraints, gpointer, i);
2161
2162                 table_idx = table->next_idx ++;
2163                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2164
2165                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2166                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2167                         assembly, mono_reflection_type_get_handle (constraint));
2168         }
2169 }
2170
2171 static void
2172 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2173 {
2174         GenericParamTableEntry *entry;
2175
2176         /*
2177          * The GenericParam table must be sorted according to the `owner' field.
2178          * We need to do this sorting prior to writing the GenericParamConstraint
2179          * table, since we have to use the final GenericParam table indices there
2180          * and they must also be sorted.
2181          */
2182
2183         entry = g_new0 (GenericParamTableEntry, 1);
2184         entry->owner = owner;
2185         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2186         MOVING_GC_REGISTER (&entry->gparam);
2187         entry->gparam = gparam;
2188         
2189         g_ptr_array_add (assembly->gen_params, entry);
2190 }
2191
2192 static void
2193 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2194 {
2195         MonoDynamicTable *table;
2196         MonoGenericParam *param;
2197         guint32 *values;
2198         guint32 table_idx;
2199
2200         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2201         table_idx = table->next_idx ++;
2202         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2203
2204         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2205
2206         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2207         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2208         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2209         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2210
2211         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2212
2213         encode_constraints (entry->gparam, table_idx, assembly);
2214 }
2215
2216 static guint32
2217 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2218 {
2219         MonoDynamicTable *table;
2220         guint32 token;
2221         guint32 *values;
2222         guint32 cols [MONO_ASSEMBLY_SIZE];
2223         const char *pubkey;
2224         guint32 publen;
2225
2226         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2227                 return token;
2228
2229         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2230                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2231                 token = table->next_idx ++;
2232                 table->rows ++;
2233                 alloc_table (table, table->rows);
2234                 values = table->values + token * MONO_MODULEREF_SIZE;
2235                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2236
2237                 token <<= MONO_RESOLTION_SCOPE_BITS;
2238                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2239                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2240
2241                 return token;
2242         }
2243         
2244         if (image->assembly->dynamic)
2245                 /* FIXME: */
2246                 memset (cols, 0, sizeof (cols));
2247         else {
2248                 /* image->assembly->image is the manifest module */
2249                 image = image->assembly->image;
2250                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2251         }
2252
2253         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2254         token = table->next_idx ++;
2255         table->rows ++;
2256         alloc_table (table, table->rows);
2257         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2258         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2259         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2260         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2261         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2262         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2263         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2264         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2265         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2266
2267         if (strcmp ("", image->assembly->aname.culture)) {
2268                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2269                                 image->assembly->aname.culture);
2270         }
2271
2272         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2273                 guchar pubtoken [9];
2274                 pubtoken [0] = 8;
2275                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2276                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2277         } else {
2278                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2279         }
2280         token <<= MONO_RESOLTION_SCOPE_BITS;
2281         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2282         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2283         return token;
2284 }
2285
2286 static guint32
2287 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2288 {
2289         MonoDynamicTable *table;
2290         guint32 *values;
2291         guint32 token;
2292         SigBuffer buf;
2293
2294         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2295                 return token;
2296
2297         sigbuffer_init (&buf, 32);
2298         switch (type->type) {
2299         case MONO_TYPE_FNPTR:
2300         case MONO_TYPE_PTR:
2301         case MONO_TYPE_SZARRAY:
2302         case MONO_TYPE_ARRAY:
2303         case MONO_TYPE_VAR:
2304         case MONO_TYPE_MVAR:
2305         case MONO_TYPE_GENERICINST:
2306                 encode_type (assembly, type, &buf);
2307                 break;
2308         case MONO_TYPE_CLASS:
2309         case MONO_TYPE_VALUETYPE: {
2310                 MonoClass *k = mono_class_from_mono_type (type);
2311                 if (!k || !k->generic_container) {
2312                         sigbuffer_free (&buf);
2313                         return 0;
2314                 }
2315                 encode_type (assembly, type, &buf);
2316                 break;
2317         }
2318         default:
2319                 sigbuffer_free (&buf);
2320                 return 0;
2321         }
2322
2323         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2324         if (assembly->save) {
2325                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2326                 alloc_table (table, table->rows + 1);
2327                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2328                 values [MONO_TYPESPEC_SIGNATURE] = token;
2329         }
2330         sigbuffer_free (&buf);
2331
2332         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2333         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2334         table->next_idx ++;
2335         return token;
2336 }
2337
2338 static guint32
2339 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2340 {
2341         MonoDynamicTable *table;
2342         guint32 *values;
2343         guint32 token, scope, enclosing;
2344         MonoClass *klass;
2345
2346         /* if the type requires a typespec, we must try that first*/
2347         if (try_typespec && (token = create_typespec (assembly, type)))
2348                 return token;
2349         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2350         if (token)
2351                 return token;
2352         klass = mono_class_from_mono_type (type);
2353         if (!klass)
2354                 klass = mono_class_from_mono_type (type);
2355
2356         /*
2357          * If it's in the same module and not a generic type parameter:
2358          */
2359         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2360                         (type->type != MONO_TYPE_MVAR)) {
2361                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2362                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2363                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2364                 return token;
2365         }
2366
2367         if (klass->nested_in) {
2368                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2369                 /* get the typeref idx of the enclosing type */
2370                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2371                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2372         } else {
2373                 scope = resolution_scope_from_image (assembly, klass->image);
2374         }
2375         table = &assembly->tables [MONO_TABLE_TYPEREF];
2376         if (assembly->save) {
2377                 alloc_table (table, table->rows + 1);
2378                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2379                 values [MONO_TYPEREF_SCOPE] = scope;
2380                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2381                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2382         }
2383         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2384         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2385         table->next_idx ++;
2386         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2387         return token;
2388 }
2389
2390 /*
2391  * Despite the name, we handle also TypeSpec (with the above helper).
2392  */
2393 static guint32
2394 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2395 {
2396         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2397 }
2398
2399 #ifndef DISABLE_REFLECTION_EMIT
2400 static guint32
2401 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2402 {
2403         MonoDynamicTable *table;
2404         guint32 *values;
2405         guint32 token, pclass;
2406
2407         switch (parent & MONO_TYPEDEFORREF_MASK) {
2408         case MONO_TYPEDEFORREF_TYPEREF:
2409                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2410                 break;
2411         case MONO_TYPEDEFORREF_TYPESPEC:
2412                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2413                 break;
2414         case MONO_TYPEDEFORREF_TYPEDEF:
2415                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2416                 break;
2417         default:
2418                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2419                 return 0;
2420         }
2421         /* extract the index */
2422         parent >>= MONO_TYPEDEFORREF_BITS;
2423
2424         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2425
2426         if (assembly->save) {
2427                 alloc_table (table, table->rows + 1);
2428                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2429                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2430                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2431                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2432         }
2433
2434         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2435         table->next_idx ++;
2436
2437         return token;
2438 }
2439
2440 /*
2441  * Insert a memberef row into the metadata: the token that point to the memberref
2442  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2443  * mono_image_get_fieldref_token()).
2444  * The sig param is an index to an already built signature.
2445  */
2446 static guint32
2447 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2448 {
2449         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2450         return mono_image_add_memberef_row (assembly, parent, name, sig);
2451 }
2452
2453
2454 static guint32
2455 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2456 {
2457         guint32 token;
2458         MonoMethodSignature *sig;
2459         
2460         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2461
2462         if (create_typespec) {
2463                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2464                 if (token)
2465                         return token;
2466         } 
2467
2468         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2469         if (token && !create_typespec)
2470                 return token;
2471
2472         g_assert (!method->is_inflated);
2473         if (!token) {
2474                 /*
2475                  * A methodref signature can't contain an unmanaged calling convention.
2476                  */
2477                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2478                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2479                         sig->call_convention = MONO_CALL_DEFAULT;
2480                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2481                         method->name,  method_encode_signature (assembly, sig));
2482                 g_free (sig);
2483                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2484         }
2485
2486         if (create_typespec) {
2487                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2488                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2489                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2490
2491                 if (assembly->save) {
2492                         guint32 *values;
2493
2494                         alloc_table (table, table->rows + 1);
2495                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2496                         values [MONO_METHODSPEC_METHOD] = token;
2497                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2498                 }
2499
2500                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2501                 table->next_idx ++;
2502                 /*methodspec and memberef tokens are diferent, */
2503                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2504                 return token;
2505         }
2506         return token;
2507 }
2508
2509 static guint32
2510 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2511 {
2512         guint32 token, parent, sig;
2513         ReflectionMethodBuilder rmb;
2514         char *name;
2515         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2516         
2517         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2518         if (token)
2519                 return token;
2520
2521         name = mono_string_to_utf8 (method->name);
2522         reflection_methodbuilder_from_method_builder (&rmb, method);
2523
2524         /*
2525          * A methodref signature can't contain an unmanaged calling convention.
2526          * Since some flags are encoded as part of call_conv, we need to check against it.
2527         */
2528         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2529                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2530
2531         sig = method_builder_encode_signature (assembly, &rmb);
2532
2533         if (tb->generic_params)
2534                 parent = create_generic_typespec (assembly, tb);
2535         else
2536                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2537
2538         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2539
2540         g_free (name);
2541         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2542         return token;
2543 }
2544
2545 static guint32
2546 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2547                                      const gchar *name, guint32 sig)
2548 {
2549         MonoDynamicTable *table;
2550         guint32 token;
2551         guint32 *values;
2552         
2553         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2554
2555         if (assembly->save) {
2556                 alloc_table (table, table->rows + 1);
2557                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2558                 values [MONO_MEMBERREF_CLASS] = original;
2559                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2560                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2561         }
2562
2563         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2564         table->next_idx ++;
2565
2566         return token;
2567 }
2568
2569 static guint32
2570 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2571 {
2572         SigBuffer buf;
2573         int i;
2574         guint32 nparams = mono_array_length (mb->generic_params);
2575         guint32 idx;
2576
2577         if (!assembly->save)
2578                 return 0;
2579
2580         sigbuffer_init (&buf, 32);
2581
2582         sigbuffer_add_value (&buf, 0xa);
2583         sigbuffer_add_value (&buf, nparams);
2584
2585         for (i = 0; i < nparams; i++) {
2586                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2587                 sigbuffer_add_value (&buf, i);
2588         }
2589
2590         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2591         sigbuffer_free (&buf);
2592         return idx;
2593 }
2594
2595 static guint32
2596 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2597 {
2598         MonoDynamicTable *table;
2599         guint32 *values;
2600         guint32 token, mtoken = 0;
2601
2602         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2603         if (token)
2604                 return token;
2605
2606         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2607
2608         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2609         switch (mono_metadata_token_table (mtoken)) {
2610         case MONO_TABLE_MEMBERREF:
2611                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2612                 break;
2613         case MONO_TABLE_METHOD:
2614                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2615                 break;
2616         default:
2617                 g_assert_not_reached ();
2618         }
2619
2620         if (assembly->save) {
2621                 alloc_table (table, table->rows + 1);
2622                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2623                 values [MONO_METHODSPEC_METHOD] = mtoken;
2624                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2625         }
2626
2627         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2628         table->next_idx ++;
2629
2630         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2631         return token;
2632 }
2633
2634 static guint32
2635 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2636 {
2637         guint32 token;
2638
2639         if (mb->generic_params && create_methodspec) 
2640                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2641
2642         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2643         if (token)
2644                 return token;
2645
2646         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2647         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2648         return token;
2649 }
2650
2651 static guint32
2652 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2653 {
2654         guint32 token, parent, sig;
2655         ReflectionMethodBuilder rmb;
2656         char *name;
2657         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2658         
2659         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2660         if (token)
2661                 return token;
2662
2663         g_assert (tb->generic_params);
2664
2665         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2666
2667         parent = create_generic_typespec (assembly, tb);
2668         name = mono_string_to_utf8 (rmb.name);
2669         sig = method_builder_encode_signature (assembly, &rmb);
2670
2671         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2672
2673         g_free (name);
2674         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2675         return token;
2676 }
2677 #endif
2678
2679 static gboolean
2680 is_field_on_inst (MonoClassField *field)
2681 {
2682         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2683 }
2684
2685 /*
2686  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2687  */
2688 static MonoType*
2689 get_field_on_inst_generic_type (MonoClassField *field)
2690 {
2691         MonoClass *class, *gtd;
2692         MonoDynamicGenericClass *dgclass;
2693         int field_index;
2694
2695         g_assert (is_field_on_inst (field));
2696
2697         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2698
2699         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2700                 field_index = field - dgclass->fields;
2701                 return dgclass->field_generic_types [field_index];              
2702         }
2703
2704         class = field->parent;
2705         gtd = class->generic_class->container_class;
2706
2707         if (field >= class->fields && field - class->fields < class->field.count) {
2708                 field_index = field - class->fields;
2709                 return gtd->fields [field_index].type;
2710         }
2711
2712         g_assert_not_reached ();
2713         return 0;
2714 }
2715
2716 #ifndef DISABLE_REFLECTION_EMIT
2717 static guint32
2718 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2719 {
2720         MonoType *type;
2721         guint32 token;
2722
2723         g_assert (field);
2724         g_assert (field->parent);
2725
2726         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2727         if (token)
2728                 return token;
2729
2730         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2731                 int index = field - field->parent->fields;
2732                 type = field->parent->generic_class->container_class->fields [index].type;
2733         } else {
2734                 if (is_field_on_inst (field))
2735                         type = get_field_on_inst_generic_type (field);
2736                 else
2737                         type = field->type;
2738         }
2739         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2740                                                                                         mono_field_get_name (field),
2741                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2742         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2743         return token;
2744 }
2745
2746 static guint32
2747 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2748 {
2749         guint32 token;
2750         MonoClass *klass;
2751         MonoGenericClass *gclass;
2752         MonoDynamicGenericClass *dgclass;
2753         MonoType *type;
2754         char *name;
2755
2756         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2757         if (token)
2758                 return token;
2759         if (is_sre_field_builder (mono_object_class (f->fb))) {
2760                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2761                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2762                 klass = mono_class_from_mono_type (type);
2763                 gclass = type->data.generic_class;
2764                 g_assert (gclass->is_dynamic);
2765                 dgclass = (MonoDynamicGenericClass *) gclass;
2766
2767                 name = mono_string_to_utf8 (fb->name);
2768                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2769                                                                                                 field_encode_signature (assembly, fb));
2770                 g_free (name);          
2771         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2772                 guint32 sig;
2773                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2774
2775                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2776                 klass = mono_class_from_mono_type (type);
2777
2778                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2779                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2780         } else {
2781                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2782                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2783         }
2784
2785         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2786         return token;
2787 }
2788
2789 static guint32
2790 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2791 {
2792         guint32 sig, token;
2793         MonoClass *klass;
2794         MonoGenericClass *gclass;
2795         MonoType *type;
2796
2797         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2798
2799         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2800         if (token)
2801                 return token;
2802
2803         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2804                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2805                 MonoDynamicGenericClass *dgclass;
2806                 ReflectionMethodBuilder rmb;
2807                 char *name;
2808
2809                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2810                 klass = mono_class_from_mono_type (type);
2811
2812                 gclass = type->data.generic_class;
2813                 g_assert (gclass->is_dynamic);
2814                 dgclass = (MonoDynamicGenericClass *) gclass;
2815
2816                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2817
2818                 name = mono_string_to_utf8 (rmb.name);
2819
2820                 sig = method_builder_encode_signature (assembly, &rmb);
2821
2822                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2823                 g_free (name);
2824         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2825                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2826
2827                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2828                 klass = mono_class_from_mono_type (type);
2829
2830                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2831                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2832         } else {
2833                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2834                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2835         }
2836
2837
2838         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2839         return token;
2840 }
2841
2842 static MonoMethod*
2843 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2844 {
2845         MonoClass *klass;
2846         MonoGenericContext tmp_context;
2847         MonoType **type_argv;
2848         MonoGenericInst *ginst;
2849         MonoMethod *method, *inflated;
2850         int count, i;
2851
2852         method = inflate_method (m->inst, (MonoObject*)m->mb);
2853
2854         klass = method->klass;
2855
2856         if (m->method_args == NULL)
2857                 return method;
2858
2859         if (method->is_inflated)
2860                 method = ((MonoMethodInflated *) method)->declaring;
2861
2862         count = mono_array_length (m->method_args);
2863
2864         type_argv = g_new0 (MonoType *, count);
2865         for (i = 0; i < count; i++) {
2866                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2867                 type_argv [i] = mono_reflection_type_get_handle (garg);
2868         }
2869         ginst = mono_metadata_get_generic_inst (count, type_argv);
2870         g_free (type_argv);
2871
2872         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2873         tmp_context.method_inst = ginst;
2874
2875         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2876         return inflated;
2877 }
2878
2879 static guint32
2880 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2881 {
2882         guint32 sig, token = 0;
2883         MonoType *type;
2884         MonoClass *klass;
2885
2886         if (m->method_args) {
2887                 MonoMethod *inflated;
2888
2889                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2890                 if (create_methodspec)
2891                         token = mono_image_get_methodspec_token (assembly, inflated);
2892                 else
2893                         token = mono_image_get_inflated_method_token (assembly, inflated);
2894                 return token;
2895         }
2896
2897         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2898         if (token)
2899                 return token;
2900
2901         if (is_sre_method_builder (mono_object_class (m->mb))) {
2902                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2903                 MonoGenericClass *gclass;
2904                 ReflectionMethodBuilder rmb;
2905                 char *name;
2906
2907                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2908                 klass = mono_class_from_mono_type (type);
2909                 gclass = type->data.generic_class;
2910                 g_assert (gclass->is_dynamic);
2911
2912                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2913
2914                 name = mono_string_to_utf8 (rmb.name);
2915
2916                 sig = method_builder_encode_signature (assembly, &rmb);
2917
2918                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2919                 g_free (name);          
2920         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2921                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2922
2923                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2924                 klass = mono_class_from_mono_type (type);
2925
2926                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2927                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2928         } else {
2929                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2930                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2931         }
2932
2933         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2934         return token;
2935 }
2936
2937 static guint32
2938 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2939 {
2940         SigBuffer buf;
2941         int i;
2942         guint32 nparams = context->method_inst->type_argc;
2943         guint32 idx;
2944
2945         if (!assembly->save)
2946                 return 0;
2947
2948         sigbuffer_init (&buf, 32);
2949         /*
2950          * FIXME: vararg, explicit_this, differenc call_conv values...
2951          */
2952         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2953         sigbuffer_add_value (&buf, nparams);
2954
2955         for (i = 0; i < nparams; i++)
2956                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2957
2958         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2959         sigbuffer_free (&buf);
2960         return idx;
2961 }
2962
2963 static guint32
2964 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2965 {
2966         MonoDynamicTable *table;
2967         guint32 *values;
2968         guint32 token, mtoken = 0, sig;
2969         MonoMethodInflated *imethod;
2970         MonoMethod *declaring;
2971
2972         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2973
2974         g_assert (method->is_inflated);
2975         imethod = (MonoMethodInflated *) method;
2976         declaring = imethod->declaring;
2977
2978         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2979         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2980
2981         if (!mono_method_signature (declaring)->generic_param_count)
2982                 return mtoken;
2983
2984         switch (mono_metadata_token_table (mtoken)) {
2985         case MONO_TABLE_MEMBERREF:
2986                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2987                 break;
2988         case MONO_TABLE_METHOD:
2989                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2990                 break;
2991         default:
2992                 g_assert_not_reached ();
2993         }
2994
2995         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2996
2997         if (assembly->save) {
2998                 alloc_table (table, table->rows + 1);
2999                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3000                 values [MONO_METHODSPEC_METHOD] = mtoken;
3001                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3002         }
3003
3004         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3005         table->next_idx ++;
3006
3007         return token;
3008 }
3009
3010 static guint32
3011 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3012 {
3013         MonoMethodInflated *imethod;
3014         guint32 token;
3015         
3016         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3017         if (token)
3018                 return token;
3019
3020         g_assert (method->is_inflated);
3021         imethod = (MonoMethodInflated *) method;
3022
3023         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3024                 token = method_encode_methodspec (assembly, method);
3025         } else {
3026                 guint32 sig = method_encode_signature (
3027                         assembly, mono_method_signature (imethod->declaring));
3028                 token = mono_image_get_memberref_token (
3029                         assembly, &method->klass->byval_arg, method->name, sig);
3030         }
3031
3032         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3033         return token;
3034 }
3035
3036 static guint32
3037 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3038 {
3039         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3040         guint32 sig, token;
3041
3042         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3043         token = mono_image_get_memberref_token (
3044                 assembly, &m->klass->byval_arg, m->name, sig);
3045
3046         return token;
3047 }
3048
3049 static guint32
3050 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3051 {
3052         MonoDynamicTable *table;
3053         MonoClass *klass;
3054         MonoType *type;
3055         guint32 *values;
3056         guint32 token;
3057         SigBuffer buf;
3058         int count, i;
3059
3060         /*
3061          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3062          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3063          * Because of this, we must not insert it into the `typeref' hash table.
3064          */
3065         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3066         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3067         if (token)
3068                 return token;
3069
3070         sigbuffer_init (&buf, 32);
3071
3072         g_assert (tb->generic_params);
3073         klass = mono_class_from_mono_type (type);
3074
3075         if (tb->generic_container)
3076                 mono_reflection_create_generic_class (tb);
3077
3078         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3079         g_assert (klass->generic_container);
3080         sigbuffer_add_value (&buf, klass->byval_arg.type);
3081         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3082
3083         count = mono_array_length (tb->generic_params);
3084         sigbuffer_add_value (&buf, count);
3085         for (i = 0; i < count; i++) {
3086                 MonoReflectionGenericParam *gparam;
3087
3088                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3089
3090                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3091         }
3092
3093         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3094
3095         if (assembly->save) {
3096                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3097                 alloc_table (table, table->rows + 1);
3098                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3099                 values [MONO_TYPESPEC_SIGNATURE] = token;
3100         }
3101         sigbuffer_free (&buf);
3102
3103         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3104         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3105         table->next_idx ++;
3106         return token;
3107 }
3108
3109 /*
3110  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3111  */
3112 static MonoType*
3113 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3114 {
3115         int i, count, len, pos;
3116         MonoType *t;
3117
3118         count = 0;
3119         if (modreq)
3120                 count += mono_array_length (modreq);
3121         if (modopt)
3122                 count += mono_array_length (modopt);
3123
3124         if (count == 0)
3125                 return mono_metadata_type_dup (NULL, type);
3126
3127         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3128         t = g_malloc (len);
3129         memcpy (t, type, MONO_SIZEOF_TYPE);
3130
3131         t->num_mods = count;
3132         pos = 0;
3133         if (modreq) {
3134                 for (i = 0; i < mono_array_length (modreq); ++i) {
3135                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3136                         t->modifiers [pos].required = 1;
3137                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3138                         pos ++;
3139                 }
3140         }
3141         if (modopt) {
3142                 for (i = 0; i < mono_array_length (modopt); ++i) {
3143                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3144                         t->modifiers [pos].required = 0;
3145                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3146                         pos ++;
3147                 }
3148         }
3149
3150         return t;
3151 }
3152
3153 static guint32
3154 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3155 {
3156         MonoDynamicTable *table;
3157         MonoClass *klass;
3158         MonoType *custom = NULL;
3159         guint32 *values;
3160         guint32 token, pclass, parent, sig;
3161         gchar *name;
3162
3163         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3164         if (token)
3165                 return token;
3166
3167         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3168         name = mono_string_to_utf8 (fb->name);
3169
3170         /* fb->type does not include the custom modifiers */
3171         /* FIXME: We should do this in one place when a fieldbuilder is created */
3172         if (fb->modreq || fb->modopt) {
3173                 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3174                 sig = fieldref_encode_signature (assembly, NULL, custom);
3175                 g_free (custom);
3176         } else {
3177                 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3178         }
3179
3180         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3181         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3182         
3183         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3184         parent >>= MONO_TYPEDEFORREF_BITS;
3185
3186         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3187
3188         if (assembly->save) {
3189                 alloc_table (table, table->rows + 1);
3190                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3191                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3192                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3193                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3194         }
3195
3196         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3197         table->next_idx ++;
3198         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3199         g_free (name);
3200         return token;
3201 }
3202
3203 static guint32
3204 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3205 {
3206         SigBuffer buf;
3207         guint32 nargs;
3208         guint32 size;
3209         guint32 i, idx;
3210
3211         if (!assembly->save)
3212                 return 0;
3213
3214         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3215         g_assert (helper->type == 2);
3216
3217         if (helper->arguments)
3218                 nargs = mono_array_length (helper->arguments);
3219         else
3220                 nargs = 0;
3221
3222         size = 10 + (nargs * 10);
3223         
3224         sigbuffer_init (&buf, 32);
3225
3226         /* Encode calling convention */
3227         /* Change Any to Standard */
3228         if ((helper->call_conv & 0x03) == 0x03)
3229                 helper->call_conv = 0x01;
3230         /* explicit_this implies has_this */
3231         if (helper->call_conv & 0x40)
3232                 helper->call_conv &= 0x20;
3233
3234         if (helper->call_conv == 0) { /* Unmanaged */
3235                 idx = helper->unmanaged_call_conv - 1;
3236         } else {
3237                 /* Managed */
3238                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3239                 if (helper->call_conv & 0x02) /* varargs */
3240                         idx += 0x05;
3241         }
3242
3243         sigbuffer_add_byte (&buf, idx);
3244         sigbuffer_add_value (&buf, nargs);
3245         encode_reflection_type (assembly, helper->return_type, &buf);
3246         for (i = 0; i < nargs; ++i) {
3247                 MonoArray *modreqs = NULL;
3248                 MonoArray *modopts = NULL;
3249                 MonoReflectionType *pt;
3250
3251                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3252                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3253                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3254                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3255
3256                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3257                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3258                 encode_reflection_type (assembly, pt, &buf);
3259         }
3260         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3261         sigbuffer_free (&buf);
3262
3263         return idx;
3264 }
3265
3266 static guint32 
3267 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3268 {
3269         guint32 idx;
3270         MonoDynamicTable *table;
3271         guint32 *values;
3272
3273         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3274         idx = table->next_idx ++;
3275         table->rows ++;
3276         alloc_table (table, table->rows);
3277         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3278
3279         values [MONO_STAND_ALONE_SIGNATURE] =
3280                 mono_reflection_encode_sighelper (assembly, helper);
3281
3282         return idx;
3283 }
3284
3285 static int
3286 reflection_cc_to_file (int call_conv) {
3287         switch (call_conv & 0x3) {
3288         case 0:
3289         case 1: return MONO_CALL_DEFAULT;
3290         case 2: return MONO_CALL_VARARG;
3291         default:
3292                 g_assert_not_reached ();
3293         }
3294         return 0;
3295 }
3296 #endif /* !DISABLE_REFLECTION_EMIT */
3297
3298 typedef struct {
3299         MonoType *parent;
3300         MonoMethodSignature *sig;
3301         char *name;
3302         guint32 token;
3303 } ArrayMethod;
3304
3305 #ifndef DISABLE_REFLECTION_EMIT
3306 static guint32
3307 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3308 {
3309         guint32 nparams, i;
3310         GList *tmp;
3311         char *name;
3312         MonoMethodSignature *sig;
3313         ArrayMethod *am;
3314         MonoType *mtype;
3315
3316         name = mono_string_to_utf8 (m->name);
3317         nparams = mono_array_length (m->parameters);
3318         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3319         sig->hasthis = 1;
3320         sig->sentinelpos = -1;
3321         sig->call_convention = reflection_cc_to_file (m->call_conv);
3322         sig->param_count = nparams;
3323         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3324         mtype = mono_reflection_type_get_handle (m->parent);
3325         for (i = 0; i < nparams; ++i)
3326                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3327
3328         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3329                 am = tmp->data;
3330                 if (strcmp (name, am->name) == 0 && 
3331                                 mono_metadata_type_equal (am->parent, mtype) &&
3332                                 mono_metadata_signature_equal (am->sig, sig)) {
3333                         g_free (name);
3334                         g_free (sig);
3335                         m->table_idx = am->token & 0xffffff;
3336                         return am->token;
3337                 }
3338         }
3339         am = g_new0 (ArrayMethod, 1);
3340         am->name = name;
3341         am->sig = sig;
3342         am->parent = mtype;
3343         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3344                 method_encode_signature (assembly, sig));
3345         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3346         m->table_idx = am->token & 0xffffff;
3347         return am->token;
3348 }
3349
3350 /*
3351  * Insert into the metadata tables all the info about the TypeBuilder tb.
3352  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3353  */
3354 static void
3355 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3356 {
3357         MonoDynamicTable *table;
3358         guint *values;
3359         int i, is_object = 0, is_system = 0;
3360         char *n;
3361
3362         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3363         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3364         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3365         n = mono_string_to_utf8 (tb->name);
3366         if (strcmp (n, "Object") == 0)
3367                 is_object++;
3368         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3369         g_free (n);
3370         n = mono_string_to_utf8 (tb->nspace);
3371         if (strcmp (n, "System") == 0)
3372                 is_system++;
3373         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3374         g_free (n);
3375         if (tb->parent && !(is_system && is_object) && 
3376                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3377                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3378         } else {
3379                 values [MONO_TYPEDEF_EXTENDS] = 0;
3380         }
3381         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3382         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3383
3384         /*
3385          * if we have explicitlayout or sequentiallayouts, output data in the
3386          * ClassLayout table.
3387          */
3388         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3389                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3390                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3391                 table->rows++;
3392                 alloc_table (table, table->rows);
3393                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3394                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3395                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3396                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3397         }
3398
3399         /* handle interfaces */
3400         if (tb->interfaces) {
3401                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3402                 i = table->rows;
3403                 table->rows += mono_array_length (tb->interfaces);
3404                 alloc_table (table, table->rows);
3405                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3406                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3407                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3408                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3409                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3410                         values += MONO_INTERFACEIMPL_SIZE;
3411                 }
3412         }
3413
3414         /* handle fields */
3415         if (tb->fields) {
3416                 table = &assembly->tables [MONO_TABLE_FIELD];
3417                 table->rows += tb->num_fields;
3418                 alloc_table (table, table->rows);
3419                 for (i = 0; i < tb->num_fields; ++i)
3420                         mono_image_get_field_info (
3421                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3422         }
3423
3424         /* handle constructors */
3425         if (tb->ctors) {
3426                 table = &assembly->tables [MONO_TABLE_METHOD];
3427                 table->rows += mono_array_length (tb->ctors);
3428                 alloc_table (table, table->rows);
3429                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3430                         mono_image_get_ctor_info (domain,
3431                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3432         }
3433
3434         /* handle methods */
3435         if (tb->methods) {
3436                 table = &assembly->tables [MONO_TABLE_METHOD];
3437                 table->rows += tb->num_methods;
3438                 alloc_table (table, table->rows);
3439                 for (i = 0; i < tb->num_methods; ++i)
3440                         mono_image_get_method_info (
3441                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3442         }
3443
3444         /* Do the same with properties etc.. */
3445         if (tb->events && mono_array_length (tb->events)) {
3446                 table = &assembly->tables [MONO_TABLE_EVENT];
3447                 table->rows += mono_array_length (tb->events);
3448                 alloc_table (table, table->rows);
3449                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3450                 table->rows ++;
3451                 alloc_table (table, table->rows);
3452                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3453                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3454                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3455                 for (i = 0; i < mono_array_length (tb->events); ++i)
3456                         mono_image_get_event_info (
3457                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3458         }
3459         if (tb->properties && mono_array_length (tb->properties)) {
3460                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3461                 table->rows += mono_array_length (tb->properties);
3462                 alloc_table (table, table->rows);
3463                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3464                 table->rows ++;
3465                 alloc_table (table, table->rows);
3466                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3467                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3468                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3469                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3470                         mono_image_get_property_info (
3471                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3472         }
3473
3474         /* handle generic parameters */
3475         if (tb->generic_params) {
3476                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3477                 table->rows += mono_array_length (tb->generic_params);
3478                 alloc_table (table, table->rows);
3479                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3480                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3481
3482                         mono_image_get_generic_param_info (
3483                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3484                 }
3485         }
3486
3487         mono_image_add_decl_security (assembly, 
3488                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3489
3490         if (tb->subtypes) {
3491                 MonoDynamicTable *ntable;
3492                 
3493                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3494                 ntable->rows += mono_array_length (tb->subtypes);
3495                 alloc_table (ntable, ntable->rows);
3496                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3497
3498                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3499                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3500
3501                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3502                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3503                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3504                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3505                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3506                                 ntable->next_idx, ntable->rows);*/
3507                         values += MONO_NESTED_CLASS_SIZE;
3508                         ntable->next_idx++;
3509                 }
3510         }
3511 }
3512 #endif
3513
3514 static void
3515 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3516 {
3517         int i;
3518
3519         mono_ptr_array_append (*types, type);
3520
3521         if (!type->subtypes)
3522                 return;
3523
3524         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3525                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3526                 collect_types (types, subtype);
3527         }
3528 }
3529
3530 static gint
3531 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3532 {
3533         if ((*type1)->table_idx < (*type2)->table_idx)
3534                 return -1;
3535         else
3536                 if ((*type1)->table_idx > (*type2)->table_idx)
3537                         return 1;
3538         else
3539                 return 0;
3540 }
3541
3542 static void
3543 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3544         int i;
3545
3546         if (!pinfo)
3547                 return;
3548         for (i = 0; i < mono_array_length (pinfo); ++i) {
3549                 MonoReflectionParamBuilder *pb;
3550                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3551                 if (!pb)
3552                         continue;
3553                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3554         }
3555 }
3556
3557 static void
3558 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3559         int i;
3560         
3561         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3562         if (tb->fields) {
3563                 for (i = 0; i < tb->num_fields; ++i) {
3564                         MonoReflectionFieldBuilder* fb;
3565                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3566                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3567                 }
3568         }
3569         if (tb->events) {
3570                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3571                         MonoReflectionEventBuilder* eb;
3572                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3573                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3574                 }
3575         }
3576         if (tb->properties) {
3577                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3578                         MonoReflectionPropertyBuilder* pb;
3579                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3580                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3581                 }
3582         }
3583         if (tb->ctors) {
3584                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3585                         MonoReflectionCtorBuilder* cb;
3586                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3587                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3588                         params_add_cattrs (assembly, cb->pinfo);
3589                 }
3590         }
3591
3592         if (tb->methods) {
3593                 for (i = 0; i < tb->num_methods; ++i) {
3594                         MonoReflectionMethodBuilder* mb;
3595                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3596                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3597                         params_add_cattrs (assembly, mb->pinfo);
3598                 }
3599         }
3600
3601         if (tb->subtypes) {
3602                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3603                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3604         }
3605 }
3606
3607 static void
3608 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3609 {
3610         int i;
3611         
3612         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3613
3614         if (moduleb->global_methods) {
3615                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3616                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3617                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3618                         params_add_cattrs (assembly, mb->pinfo);
3619                 }
3620         }
3621
3622         if (moduleb->global_fields) {
3623                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3624                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3625                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3626                 }
3627         }
3628         
3629         if (moduleb->types) {
3630                 for (i = 0; i < moduleb->num_types; ++i)
3631                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3632         }
3633 }
3634
3635 static void
3636 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3637 {
3638         MonoDynamicTable *table;
3639         guint32 *values;
3640         char blob_size [6];
3641         guchar hash [20];
3642         char *b = blob_size;
3643         char *dir, *path;
3644
3645         table = &assembly->tables [MONO_TABLE_FILE];
3646         table->rows++;
3647         alloc_table (table, table->rows);
3648         values = table->values + table->next_idx * MONO_FILE_SIZE;
3649         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3650         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3651         if (module->image->dynamic) {
3652                 /* This depends on the fact that the main module is emitted last */
3653                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3654                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3655         } else {
3656                 dir = NULL;
3657                 path = g_strdup (module->image->name);
3658         }
3659         mono_sha1_get_digest_from_file (path, hash);
3660         g_free (dir);
3661         g_free (path);
3662         mono_metadata_encode_value (20, b, &b);
3663         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3664         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3665         table->next_idx ++;
3666 }
3667
3668 static void
3669 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3670 {
3671         MonoDynamicTable *table;
3672         int i;
3673
3674         table = &assembly->tables [MONO_TABLE_MODULE];
3675         mb->table_idx = table->next_idx ++;
3676         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3677         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3678         i /= 16;
3679         ++i;
3680         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3681         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3682         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3683         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3684 }
3685
3686 static guint32
3687 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3688         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3689 {
3690         MonoDynamicTable *table;
3691         guint32 *values;
3692         guint32 visib, res;
3693
3694         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3695         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3696                 return 0;
3697
3698         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3699         table->rows++;
3700         alloc_table (table, table->rows);
3701         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3702
3703         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3704         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3705         if (klass->nested_in)
3706                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3707         else
3708                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3709         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3710         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3711
3712         res = table->next_idx;
3713
3714         table->next_idx ++;
3715
3716         /* Emit nested types */
3717         if (klass->ext && klass->ext->nested_classes) {
3718                 GList *tmp;
3719
3720                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3721                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3722         }
3723
3724         return res;
3725 }
3726
3727 static void
3728 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3729         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3730 {
3731         MonoClass *klass;
3732         guint32 idx, i;
3733
3734         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3735
3736         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3737
3738         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3739                                                                                                    parent_index, assembly);
3740
3741         /* 
3742          * Emit nested types
3743          * We need to do this ourselves since klass->nested_classes is not set up.
3744          */
3745         if (tb->subtypes) {
3746                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3747                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3748         }
3749 }
3750
3751 static void
3752 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3753         guint32 module_index, MonoDynamicImage *assembly)
3754 {
3755         MonoImage *image = module->image;
3756         MonoTableInfo  *t;
3757         guint32 i;
3758
3759         t = &image->tables [MONO_TABLE_TYPEDEF];
3760
3761         for (i = 0; i < t->rows; ++i) {
3762                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3763
3764                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3765                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3766         }
3767 }
3768
3769 static void
3770 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3771 {
3772         MonoDynamicTable *table;
3773         guint32 *values;
3774         guint32 scope, scope_idx, impl, current_idx;
3775         gboolean forwarder = TRUE;
3776         gpointer iter = NULL;
3777         MonoClass *nested;
3778
3779         if (klass->nested_in) {
3780                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3781                 forwarder = FALSE;
3782         } else {
3783                 scope = resolution_scope_from_image (assembly, klass->image);
3784                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3785                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3786                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3787         }
3788
3789         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3790
3791         table->rows++;
3792         alloc_table (table, table->rows);
3793         current_idx = table->next_idx;
3794         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3795
3796         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3797         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3798         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3799         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3800         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3801
3802         table->next_idx++;
3803
3804         while ((nested = mono_class_get_nested_types (klass, &iter)))
3805                 add_exported_type (assemblyb, assembly, nested, current_idx);
3806 }
3807
3808 static void
3809 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3810 {
3811         MonoClass *klass;
3812         int i;
3813
3814         if (!assemblyb->type_forwarders)
3815                 return;
3816
3817         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3818                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3819                 MonoType *type;
3820                 if (!t)
3821                         continue;
3822
3823                 type = mono_reflection_type_get_handle (t);
3824                 g_assert (type);
3825
3826                 klass = mono_class_from_mono_type (type);
3827
3828                 add_exported_type (assemblyb, assembly, klass, 0);
3829         }
3830 }
3831
3832 #define align_pointer(base,p)\
3833         do {\
3834                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3835                 if (__diff & 3)\
3836                         (p) += 4 - (__diff & 3);\
3837         } while (0)
3838
3839 static int
3840 compare_constants (const void *a, const void *b)
3841 {
3842         const guint32 *a_values = a;
3843         const guint32 *b_values = b;
3844         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3845 }
3846
3847 static int
3848 compare_semantics (const void *a, const void *b)
3849 {
3850         const guint32 *a_values = a;
3851         const guint32 *b_values = b;
3852         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3853         if (assoc)
3854                 return assoc;
3855         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3856 }
3857
3858 static int
3859 compare_custom_attrs (const void *a, const void *b)
3860 {
3861         const guint32 *a_values = a;
3862         const guint32 *b_values = b;
3863
3864         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3865 }
3866
3867 static int
3868 compare_field_marshal (const void *a, const void *b)
3869 {
3870         const guint32 *a_values = a;
3871         const guint32 *b_values = b;
3872
3873         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3874 }
3875
3876 static int
3877 compare_nested (const void *a, const void *b)
3878 {
3879         const guint32 *a_values = a;
3880         const guint32 *b_values = b;
3881
3882         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3883 }
3884
3885 static int
3886 compare_genericparam (const void *a, const void *b)
3887 {
3888         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3889         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3890
3891         if ((*b_entry)->owner == (*a_entry)->owner)
3892                 return 
3893                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3894                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3895         else
3896                 return (*a_entry)->owner - (*b_entry)->owner;
3897 }
3898
3899 static int
3900 compare_declsecurity_attrs (const void *a, const void *b)
3901 {
3902         const guint32 *a_values = a;
3903         const guint32 *b_values = b;
3904
3905         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3906 }
3907
3908 static int
3909 compare_interface_impl (const void *a, const void *b)
3910 {
3911         const guint32 *a_values = a;
3912         const guint32 *b_values = b;
3913
3914         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3915         if (klass)
3916                 return klass;
3917
3918         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3919 }
3920
3921 static void
3922 pad_heap (MonoDynamicStream *sh)
3923 {
3924         if (sh->index & 3) {
3925                 int sz = 4 - (sh->index & 3);
3926                 memset (sh->data + sh->index, 0, sz);
3927                 sh->index += sz;
3928         }
3929 }
3930
3931 struct StreamDesc {
3932         const char *name;
3933         MonoDynamicStream *stream;
3934 };
3935
3936 /*
3937  * build_compressed_metadata() fills in the blob of data that represents the 
3938  * raw metadata as it will be saved in the PE file. The five streams are output 
3939  * and the metadata tables are comnpressed from the guint32 array representation, 
3940  * to the compressed on-disk format.
3941  */
3942 static void
3943 build_compressed_metadata (MonoDynamicImage *assembly)
3944 {
3945         MonoDynamicTable *table;
3946         int i;
3947         guint64 valid_mask = 0;
3948         guint64 sorted_mask;
3949         guint32 heapt_size = 0;
3950         guint32 meta_size = 256; /* allow for header and other stuff */
3951         guint32 table_offset;
3952         guint32 ntables = 0;
3953         guint64 *int64val;
3954         guint32 *int32val;
3955         guint16 *int16val;
3956         MonoImage *meta;
3957         unsigned char *p;
3958         struct StreamDesc stream_desc [5];
3959
3960         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3961         for (i = 0; i < assembly->gen_params->len; i++){
3962                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3963                 write_generic_param_entry (assembly, entry);
3964         }
3965
3966         stream_desc [0].name  = "#~";
3967         stream_desc [0].stream = &assembly->tstream;
3968         stream_desc [1].name  = "#Strings";
3969         stream_desc [1].stream = &assembly->sheap;
3970         stream_desc [2].name  = "#US";
3971         stream_desc [2].stream = &assembly->us;
3972         stream_desc [3].name  = "#Blob";
3973         stream_desc [3].stream = &assembly->blob;
3974         stream_desc [4].name  = "#GUID";
3975         stream_desc [4].stream = &assembly->guid;
3976         
3977         /* tables that are sorted */
3978         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3979                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3980                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3981                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3982                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3983                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3984                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3985         
3986         /* Compute table sizes */
3987         /* the MonoImage has already been created in mono_image_basic_init() */
3988         meta = &assembly->image;
3989
3990         /* sizes should be multiple of 4 */
3991         pad_heap (&assembly->blob);
3992         pad_heap (&assembly->guid);
3993         pad_heap (&assembly->sheap);
3994         pad_heap (&assembly->us);
3995
3996         /* Setup the info used by compute_sizes () */
3997         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3998         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3999         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4000
4001         meta_size += assembly->blob.index;
4002         meta_size += assembly->guid.index;
4003         meta_size += assembly->sheap.index;
4004         meta_size += assembly->us.index;
4005
4006         for (i=0; i < MONO_TABLE_NUM; ++i)
4007                 meta->tables [i].rows = assembly->tables [i].rows;
4008         
4009         for (i = 0; i < MONO_TABLE_NUM; i++){
4010                 if (meta->tables [i].rows == 0)
4011                         continue;
4012                 valid_mask |= (guint64)1 << i;
4013                 ntables ++;
4014                 meta->tables [i].row_size = mono_metadata_compute_size (
4015                         meta, i, &meta->tables [i].size_bitfield);
4016                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4017         }
4018         heapt_size += 24; /* #~ header size */
4019         heapt_size += ntables * 4;
4020         /* make multiple of 4 */
4021         heapt_size += 3;
4022         heapt_size &= ~3;
4023         meta_size += heapt_size;
4024         meta->raw_metadata = g_malloc0 (meta_size);
4025         p = (unsigned char*)meta->raw_metadata;
4026         /* the metadata signature */
4027         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4028         /* version numbers and 4 bytes reserved */
4029         int16val = (guint16*)p;
4030         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4031         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4032         p += 8;
4033         /* version string */
4034         int32val = (guint32*)p;
4035         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4036         p += 4;
4037         memcpy (p, meta->version, strlen (meta->version));
4038         p += GUINT32_FROM_LE (*int32val);
4039         align_pointer (meta->raw_metadata, p);
4040         int16val = (guint16*)p;
4041         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4042         *int16val = GUINT16_TO_LE (5); /* number of streams */
4043         p += 4;
4044
4045         /*
4046          * write the stream info.
4047          */
4048         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4049         table_offset += 3; table_offset &= ~3;
4050
4051         assembly->tstream.index = heapt_size;
4052         for (i = 0; i < 5; ++i) {
4053                 int32val = (guint32*)p;
4054                 stream_desc [i].stream->offset = table_offset;
4055                 *int32val++ = GUINT32_TO_LE (table_offset);
4056                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4057                 table_offset += GUINT32_FROM_LE (*int32val);
4058                 table_offset += 3; table_offset &= ~3;
4059                 p += 8;
4060                 strcpy ((char*)p, stream_desc [i].name);
4061                 p += strlen (stream_desc [i].name) + 1;
4062                 align_pointer (meta->raw_metadata, p);
4063         }
4064         /* 
4065          * now copy the data, the table stream header and contents goes first.
4066          */
4067         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4068         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4069         int32val = (guint32*)p;
4070         *int32val = GUINT32_TO_LE (0); /* reserved */
4071         p += 4;
4072
4073         *p++ = 2; /* version */
4074         *p++ = 0;
4075
4076         if (meta->idx_string_wide)
4077                 *p |= 0x01;
4078         if (meta->idx_guid_wide)
4079                 *p |= 0x02;
4080         if (meta->idx_blob_wide)
4081                 *p |= 0x04;
4082         ++p;
4083         *p++ = 1; /* reserved */
4084         int64val = (guint64*)p;
4085         *int64val++ = GUINT64_TO_LE (valid_mask);
4086         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4087         p += 16;
4088         int32val = (guint32*)p;
4089         for (i = 0; i < MONO_TABLE_NUM; i++){
4090                 if (meta->tables [i].rows == 0)
4091                         continue;
4092                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4093         }
4094         p = (unsigned char*)int32val;
4095
4096         /* sort the tables that still need sorting */
4097         table = &assembly->tables [MONO_TABLE_CONSTANT];
4098         if (table->rows)
4099                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4100         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4101         if (table->rows)
4102                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4103         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4104         if (table->rows)
4105                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4106         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4107         if (table->rows)
4108                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4109         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4110         if (table->rows)
4111                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4112         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4113         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4114         if (table->rows)
4115                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4116         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4117         if (table->rows)
4118                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4119
4120         /* compress the tables */
4121         for (i = 0; i < MONO_TABLE_NUM; i++){
4122                 int row, col;
4123                 guint32 *values;
4124                 guint32 bitfield = meta->tables [i].size_bitfield;
4125                 if (!meta->tables [i].rows)
4126                         continue;
4127                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4128                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4129                 meta->tables [i].base = (char*)p;
4130                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4131                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4132                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4133                                 switch (mono_metadata_table_size (bitfield, col)) {
4134                                 case 1:
4135                                         *p++ = values [col];
4136                                         break;
4137                                 case 2:
4138                                         *p++ = values [col] & 0xff;
4139                                         *p++ = (values [col] >> 8) & 0xff;
4140                                         break;
4141                                 case 4:
4142                                         *p++ = values [col] & 0xff;
4143                                         *p++ = (values [col] >> 8) & 0xff;
4144                                         *p++ = (values [col] >> 16) & 0xff;
4145                                         *p++ = (values [col] >> 24) & 0xff;
4146                                         break;
4147                                 default:
4148                                         g_assert_not_reached ();
4149                                 }
4150                         }
4151                 }
4152                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4153         }
4154         
4155         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4156         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4157         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4158         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4159         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4160
4161         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4162 }
4163
4164 /*
4165  * Some tables in metadata need to be sorted according to some criteria, but
4166  * when methods and fields are first created with reflection, they may be assigned a token
4167  * that doesn't correspond to the final token they will get assigned after the sorting.
4168  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4169  * with the reflection objects that represent them. Once all the tables are set up, the 
4170  * reflection objects will contains the correct table index. fixup_method() will fixup the
4171  * tokens for the method with ILGenerator @ilgen.
4172  */
4173 static void
4174 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4175 {
4176         guint32 code_idx = GPOINTER_TO_UINT (value);
4177         MonoReflectionILTokenInfo *iltoken;
4178         MonoReflectionFieldBuilder *field;
4179         MonoReflectionCtorBuilder *ctor;
4180         MonoReflectionMethodBuilder *method;
4181         MonoReflectionTypeBuilder *tb;
4182         MonoReflectionArrayMethod *am;
4183         guint32 i, idx = 0;
4184         unsigned char *target;
4185
4186         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4187                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4188                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4189                 switch (target [3]) {
4190                 case MONO_TABLE_FIELD:
4191                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4192                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4193                                 idx = field->table_idx;
4194                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4195                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4196                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4197                         } else {
4198                                 g_assert_not_reached ();
4199                         }
4200                         break;
4201                 case MONO_TABLE_METHOD:
4202                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4203                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4204                                 idx = method->table_idx;
4205                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4206                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4207                                 idx = ctor->table_idx;
4208                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4209                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4210                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4211                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4212                         } else {
4213                                 g_assert_not_reached ();
4214                         }
4215                         break;
4216                 case MONO_TABLE_TYPEDEF:
4217                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4218                                 g_assert_not_reached ();
4219                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4220                         idx = tb->table_idx;
4221                         break;
4222                 case MONO_TABLE_MEMBERREF:
4223                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4224                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4225                                 idx = am->table_idx;
4226                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4227                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4228                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4229                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4230                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4231                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4232                                 continue;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4234                                 continue;
4235                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4236                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4237                                 g_assert (is_field_on_inst (f));
4238                                 continue;
4239                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4240                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4241                                 continue;
4242                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4243                                 continue;
4244                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4245                                 continue;
4246                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4247                                 continue;
4248                         } else {
4249                                 g_assert_not_reached ();
4250                         }
4251                         break;
4252                 case MONO_TABLE_METHODSPEC:
4253                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4254                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4255                                 g_assert (mono_method_signature (m)->generic_param_count);
4256                                 continue;
4257                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4258                                 continue;
4259                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4260                                 continue;
4261                         } else {
4262                                 g_assert_not_reached ();
4263                         }
4264                         break;
4265                 default:
4266                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4267                 }
4268                 target [0] = idx & 0xff;
4269                 target [1] = (idx >> 8) & 0xff;
4270                 target [2] = (idx >> 16) & 0xff;
4271         }
4272 }
4273
4274 /*
4275  * fixup_cattrs:
4276  *
4277  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4278  * value is not known when the table is emitted.
4279  */
4280 static void
4281 fixup_cattrs (MonoDynamicImage *assembly)
4282 {
4283         MonoDynamicTable *table;
4284         guint32 *values;
4285         guint32 type, i, idx, token;
4286         MonoObject *ctor;
4287
4288         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4289
4290         for (i = 0; i < table->rows; ++i) {
4291                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4292
4293                 type = values [MONO_CUSTOM_ATTR_TYPE];
4294                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4295                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4296                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4297                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4298                         g_assert (ctor);
4299
4300                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4301                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4302                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4303                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4304                         }
4305                 }
4306         }
4307 }
4308
4309 static void
4310 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4311 {
4312         MonoDynamicTable *table;
4313         guint32 *values;
4314
4315         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4316         table->rows++;
4317         alloc_table (table, table->rows);
4318         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4319         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4320         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4321         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4322         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4323         table->next_idx++;
4324 }
4325
4326 static void
4327 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4328 {
4329         MonoDynamicTable *table;
4330         guint32 *values;
4331         char blob_size [6];
4332         guchar hash [20];
4333         char *b = blob_size;
4334         char *name, *sname;
4335         guint32 idx, offset;
4336
4337         if (rsrc->filename) {
4338                 name = mono_string_to_utf8 (rsrc->filename);
4339                 sname = g_path_get_basename (name);
4340         
4341                 table = &assembly->tables [MONO_TABLE_FILE];
4342                 table->rows++;
4343                 alloc_table (table, table->rows);
4344                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4345                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4346                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4347                 g_free (sname);
4348
4349                 mono_sha1_get_digest_from_file (name, hash);
4350                 mono_metadata_encode_value (20, b, &b);
4351                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4352                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4353                 g_free (name);
4354                 idx = table->next_idx++;
4355                 rsrc->offset = 0;
4356                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4357         } else {
4358                 char sizebuf [4];
4359                 char *data;
4360                 guint len;
4361                 if (rsrc->data) {
4362                         data = mono_array_addr (rsrc->data, char, 0);
4363                         len = mono_array_length (rsrc->data);
4364                 } else {
4365                         data = NULL;
4366                         len = 0;
4367                 }
4368                 offset = len;
4369                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4370                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4371                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4372                 mono_image_add_stream_data (&assembly->resources, data, len);
4373
4374                 if (!mb->is_main)
4375                         /* 
4376                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4377                          * the main module, but that needs to reference the FILE table
4378                          * which isn't emitted yet.
4379                          */
4380                         return;
4381                 else
4382                         idx = 0;
4383         }
4384
4385         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4386 }
4387
4388 static void
4389 set_version_from_string (MonoString *version, guint32 *values)
4390 {
4391         gchar *ver, *p, *str;
4392         guint32 i;
4393         
4394         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4395         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4396         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4397         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4398         if (!version)
4399                 return;
4400         ver = str = mono_string_to_utf8 (version);
4401         for (i = 0; i < 4; ++i) {
4402                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4403                 switch (*p) {
4404                 case '.':
4405                         p++;
4406                         break;
4407                 case '*':
4408                         /* handle Revision and Build */
4409                         p++;
4410                         break;
4411                 }
4412                 ver = p;
4413         }
4414         g_free (str);
4415 }
4416
4417 static guint32
4418 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4419         gsize len;
4420         guint32 token = 0;
4421         char blob_size [6];
4422         char *b = blob_size;
4423
4424         if (!pkey)
4425                 return token;
4426
4427         len = mono_array_length (pkey);
4428         mono_metadata_encode_value (len, b, &b);
4429         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4430         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4431
4432         assembly->public_key = g_malloc (len);
4433         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4434         assembly->public_key_len = len;
4435
4436         /* Special case: check for ECMA key (16 bytes) */
4437         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4438                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4439                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4440         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4441                 /* minimum key size (in 2.0) is 384 bits */
4442                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4443         } else {
4444                 /* FIXME - verifier */
4445                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4446                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4447         }
4448         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4449
4450         return token;
4451 }
4452
4453 static void
4454 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4455 {
4456         MonoDynamicTable *table;
4457         MonoDynamicImage *assembly;
4458         MonoReflectionAssemblyBuilder *assemblyb;
4459         MonoDomain *domain;
4460         guint32 *values;
4461         int i;
4462         guint32 module_index;
4463
4464         assemblyb = moduleb->assemblyb;
4465         assembly = moduleb->dynamic_image;
4466         domain = mono_object_domain (assemblyb);
4467
4468         /* Emit ASSEMBLY table */
4469         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4470         alloc_table (table, 1);
4471         values = table->values + MONO_ASSEMBLY_SIZE;
4472         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4473         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4474         if (assemblyb->culture) {
4475                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4476         } else {
4477                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4478         }
4479         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4480         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4481         set_version_from_string (assemblyb->version, values);
4482
4483         /* Emit FILE + EXPORTED_TYPE table */
4484         module_index = 0;
4485         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4486                 int j;
4487                 MonoReflectionModuleBuilder *file_module = 
4488                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4489                 if (file_module != moduleb) {
4490                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4491                         module_index ++;
4492                         if (file_module->types) {
4493                                 for (j = 0; j < file_module->num_types; ++j) {
4494                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4495                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4496                                 }
4497                         }
4498                 }
4499         }
4500         if (assemblyb->loaded_modules) {
4501                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4502                         MonoReflectionModule *file_module = 
4503                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4504                         mono_image_fill_file_table (domain, file_module, assembly);
4505                         module_index ++;
4506                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4507                 }
4508         }
4509         if (assemblyb->type_forwarders)
4510                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4511
4512         /* Emit MANIFESTRESOURCE 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                 /* The table for the main module is emitted later */
4519                 if (file_module != moduleb) {
4520                         module_index ++;
4521                         if (file_module->resources) {
4522                                 int len = mono_array_length (file_module->resources);
4523                                 for (j = 0; j < len; ++j) {
4524                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4525                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4526                                 }
4527                         }
4528                 }
4529         }               
4530 }
4531
4532 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4533
4534 /*
4535  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4536  * for the modulebuilder @moduleb.
4537  * At the end of the process, method and field tokens are fixed up and the 
4538  * on-disk compressed metadata representation is created.
4539  */
4540 void
4541 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4542 {
4543         MonoDynamicTable *table;
4544         MonoDynamicImage *assembly;
4545         MonoReflectionAssemblyBuilder *assemblyb;
4546         MonoDomain *domain;
4547         MonoPtrArray types;
4548         guint32 *values;
4549         int i, j;
4550
4551         assemblyb = moduleb->assemblyb;
4552         assembly = moduleb->dynamic_image;
4553         domain = mono_object_domain (assemblyb);
4554
4555         if (assembly->text_rva)
4556                 return;
4557
4558         assembly->text_rva = START_TEXT_RVA;
4559
4560         if (moduleb->is_main) {
4561                 mono_image_emit_manifest (moduleb);
4562         }
4563
4564         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4565         table->rows = 1; /* .<Module> */
4566         table->next_idx++;
4567         alloc_table (table, table->rows);
4568         /*
4569          * Set the first entry.
4570          */
4571         values = table->values + table->columns;
4572         values [MONO_TYPEDEF_FLAGS] = 0;
4573         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4574         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4575         values [MONO_TYPEDEF_EXTENDS] = 0;
4576         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4577         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4578
4579         /* 
4580          * handle global methods 
4581          * FIXME: test what to do when global methods are defined in multiple modules.
4582          */
4583         if (moduleb->global_methods) {
4584                 table = &assembly->tables [MONO_TABLE_METHOD];
4585                 table->rows += mono_array_length (moduleb->global_methods);
4586                 alloc_table (table, table->rows);
4587                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4588                         mono_image_get_method_info (
4589                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4590         }
4591         if (moduleb->global_fields) {
4592                 table = &assembly->tables [MONO_TABLE_FIELD];
4593                 table->rows += mono_array_length (moduleb->global_fields);
4594                 alloc_table (table, table->rows);
4595                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4596                         mono_image_get_field_info (
4597                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4598         }
4599
4600         table = &assembly->tables [MONO_TABLE_MODULE];
4601         alloc_table (table, 1);
4602         mono_image_fill_module_table (domain, moduleb, assembly);
4603
4604         /* Collect all types into a list sorted by their table_idx */
4605         mono_ptr_array_init (types, moduleb->num_types);
4606
4607         if (moduleb->types)
4608                 for (i = 0; i < moduleb->num_types; ++i) {
4609                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4610                         collect_types (&types, type);
4611                 }
4612
4613         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4614         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4615         table->rows += mono_ptr_array_size (types);
4616         alloc_table (table, table->rows);
4617
4618         /*
4619          * Emit type names + namespaces at one place inside the string heap,
4620          * so load_class_names () needs to touch fewer pages.
4621          */
4622         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4623                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4624                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4625         }
4626         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4627                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4628                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4629         }
4630
4631         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4632                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4633                 mono_image_get_type_info (domain, type, assembly);
4634         }
4635
4636         /* 
4637          * table->rows is already set above and in mono_image_fill_module_table.
4638          */
4639         /* add all the custom attributes at the end, once all the indexes are stable */
4640         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4641
4642         /* CAS assembly permissions */
4643         if (assemblyb->permissions_minimum)
4644                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4645         if (assemblyb->permissions_optional)
4646                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4647         if (assemblyb->permissions_refused)
4648                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4649
4650         module_add_cattrs (assembly, moduleb);
4651
4652         /* fixup tokens */
4653         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4654
4655         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4656          * the final tokens and don't need another fixup pass. */
4657
4658         if (moduleb->global_methods) {
4659                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4660                         MonoReflectionMethodBuilder *mb = mono_array_get (
4661                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4662                         mono_image_add_methodimpl (assembly, mb);
4663                 }
4664         }
4665
4666         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4668                 if (type->methods) {
4669                         for (j = 0; j < type->num_methods; ++j) {
4670                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4671                                         type->methods, MonoReflectionMethodBuilder*, j);
4672
4673                                 mono_image_add_methodimpl (assembly, mb);
4674                         }
4675                 }
4676         }
4677
4678         mono_ptr_array_destroy (types);
4679
4680         fixup_cattrs (assembly);
4681 }
4682
4683 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4684
4685 void
4686 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4687 {
4688         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4689 }
4690
4691 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4692
4693
4694 typedef struct {
4695         guint32 import_lookup_table;
4696         guint32 timestamp;
4697         guint32 forwarder;
4698         guint32 name_rva;
4699         guint32 import_address_table_rva;
4700 } MonoIDT;
4701
4702 typedef struct {
4703         guint32 name_rva;
4704         guint32 flags;
4705 } MonoILT;
4706
4707 #ifndef DISABLE_REFLECTION_EMIT
4708
4709 /*
4710  * mono_image_insert_string:
4711  * @module: module builder object
4712  * @str: a string
4713  *
4714  * Insert @str into the user string stream of @module.
4715  */
4716 guint32
4717 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4718 {
4719         MonoDynamicImage *assembly;
4720         guint32 idx;
4721         char buf [16];
4722         char *b = buf;
4723         
4724         MONO_ARCH_SAVE_REGS;
4725
4726         if (!module->dynamic_image)
4727                 mono_image_module_basic_init (module);
4728
4729         assembly = module->dynamic_image;
4730         
4731         if (assembly->save) {
4732                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4733                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4735         {
4736                 char *swapped = g_malloc (2 * mono_string_length (str));
4737                 const char *p = (const char*)mono_string_chars (str);
4738
4739                 swap_with_size (swapped, p, 2, mono_string_length (str));
4740                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4741                 g_free (swapped);
4742         }
4743 #else
4744                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4745 #endif
4746                 mono_image_add_stream_data (&assembly->us, "", 1);
4747         } else {
4748                 idx = assembly->us.index ++;
4749         }
4750
4751         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4752
4753         return MONO_TOKEN_STRING | idx;
4754 }
4755
4756 guint32
4757 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4758 {
4759         MonoClass *klass;
4760         guint32 token = 0;
4761         MonoMethodSignature *sig;
4762
4763         klass = obj->vtable->klass;
4764         if (strcmp (klass->name, "MonoMethod") == 0) {
4765                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4766                 MonoMethodSignature *old;
4767                 guint32 sig_token, parent;
4768                 int nargs, i;
4769
4770                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4771
4772                 nargs = mono_array_length (opt_param_types);
4773                 old = mono_method_signature (method);
4774                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4775
4776                 sig->hasthis = old->hasthis;
4777                 sig->explicit_this = old->explicit_this;
4778                 sig->call_convention = old->call_convention;
4779                 sig->generic_param_count = old->generic_param_count;
4780                 sig->param_count = old->param_count + nargs;
4781                 sig->sentinelpos = old->param_count;
4782                 sig->ret = old->ret;
4783
4784                 for (i = 0; i < old->param_count; i++)
4785                         sig->params [i] = old->params [i];
4786
4787                 for (i = 0; i < nargs; i++) {
4788                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4789                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4790                 }
4791
4792                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4793                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4794                 parent >>= MONO_TYPEDEFORREF_BITS;
4795
4796                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4797                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4798
4799                 sig_token = method_encode_signature (assembly, sig);
4800                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4801         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4802                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4803                 ReflectionMethodBuilder rmb;
4804                 guint32 parent, sig_token;
4805                 int nopt_args, nparams, ngparams, i;
4806                 char *name;
4807
4808                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4809                 rmb.opt_types = opt_param_types;
4810                 nopt_args = mono_array_length (opt_param_types);
4811
4812                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4813                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4814                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4815
4816                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4817                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4818                 sig->call_convention = rmb.call_conv;
4819                 sig->generic_param_count = ngparams;
4820                 sig->param_count = nparams + nopt_args;
4821                 sig->sentinelpos = nparams;
4822                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4823
4824                 for (i = 0; i < nparams; i++) {
4825                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4826                         sig->params [i] = mono_reflection_type_get_handle (rt);
4827                 }
4828
4829                 for (i = 0; i < nopt_args; i++) {
4830                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4831                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4832                 }
4833
4834                 sig_token = method_builder_encode_signature (assembly, &rmb);
4835
4836                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4837                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4838
4839                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4840                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4841
4842                 name = mono_string_to_utf8 (rmb.name);
4843                 token = mono_image_get_varargs_method_token (
4844                         assembly, parent, name, sig_token);
4845                 g_free (name);
4846         } else {
4847                 g_error ("requested method token for %s\n", klass->name);
4848         }
4849
4850         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4851         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4852         return token;
4853 }
4854
4855 /*
4856  * mono_image_create_token:
4857  * @assembly: a dynamic assembly
4858  * @obj:
4859  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4860  *
4861  * Get a token to insert in the IL code stream for the given MemberInfo.
4862  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4863  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4864  * entry.
4865  */
4866 guint32
4867 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4868                                                  gboolean create_methodspec, gboolean register_token)
4869 {
4870         MonoClass *klass;
4871         guint32 token = 0;
4872
4873         klass = obj->vtable->klass;
4874
4875         /* Check for user defined reflection objects */
4876         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4877         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4878                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4879
4880         if (strcmp (klass->name, "MethodBuilder") == 0) {
4881                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4882                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4883
4884                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4885                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4886                 else
4887                         token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4888                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4889         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4890                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4891                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4892
4893                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4894                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4895                 else
4896                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4897                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4898         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4899                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4900                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4901                 if (tb->generic_params) {
4902                         token = mono_image_get_generic_field_token (assembly, fb);
4903                 } else {
4904                         if ((tb->module->dynamic_image == assembly)) {
4905                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4906                         } else {
4907                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4908                         }
4909                 }
4910         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4911                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4912                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4913         } else if (strcmp (klass->name, "MonoType") == 0) {
4914                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4915                 MonoClass *mc = mono_class_from_mono_type (type);
4916                 if (!mono_class_init (mc))
4917                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
4918
4919                 token = mono_metadata_token_from_dor (
4920                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4921         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4922                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4923                 token = mono_metadata_token_from_dor (
4924                         mono_image_typedef_or_ref (assembly, type));
4925         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4926                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4927                 token = mono_metadata_token_from_dor (
4928                         mono_image_typedef_or_ref (assembly, type));
4929         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4930                    strcmp (klass->name, "MonoMethod") == 0 ||
4931                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4932                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4933                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4934                 if (m->method->is_inflated) {
4935                         if (create_methodspec)
4936                                 token = mono_image_get_methodspec_token (assembly, m->method);
4937                         else
4938                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4939                 } else if ((m->method->klass->image == &assembly->image) &&
4940                          !m->method->klass->generic_class) {
4941                         static guint32 method_table_idx = 0xffffff;
4942                         if (m->method->klass->wastypebuilder) {
4943                                 /* we use the same token as the one that was assigned
4944                                  * to the Methodbuilder.
4945                                  * FIXME: do the equivalent for Fields.
4946                                  */
4947                                 token = m->method->token;
4948                         } else {
4949                                 /*
4950                                  * Each token should have a unique index, but the indexes are
4951                                  * assigned by managed code, so we don't know about them. An
4952                                  * easy solution is to count backwards...
4953                                  */
4954                                 method_table_idx --;
4955                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4956                         }
4957                 } else {
4958                         token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4959                 }
4960                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4961         } else if (strcmp (klass->name, "MonoField") == 0) {
4962                 MonoReflectionField *f = (MonoReflectionField *)obj;
4963                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4964                         static guint32 field_table_idx = 0xffffff;
4965                         field_table_idx --;
4966                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4967                 } else {
4968                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
4969                 }
4970                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4971         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4972                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4973                 token = mono_image_get_array_token (assembly, m);
4974         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4975                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4976                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4977         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4978                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979                 token = mono_metadata_token_from_dor (
4980                         mono_image_typedef_or_ref (assembly, type));
4981         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4982                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4983                 token = mono_image_get_field_on_inst_token (assembly, f);
4984         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4985                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4986                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4987         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4988                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4989                 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4990         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4991                 MonoReflectionType *type = (MonoReflectionType *)obj;
4992                 token = mono_metadata_token_from_dor (
4993                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4994         } else {
4995                 g_error ("requested token for %s\n", klass->name);
4996         }
4997
4998         if (register_token)
4999                 mono_image_register_token (assembly, token, obj);
5000
5001         return token;
5002 }
5003
5004 /*
5005  * mono_image_register_token:
5006  *
5007  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5008  * the Module.ResolveXXXToken () methods to work.
5009  */
5010 void
5011 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5012 {
5013         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5014         if (prev) {
5015                 /* There could be multiple MethodInfo objects with the same token */
5016                 //g_assert (prev == obj);
5017         } else {
5018                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5019         }
5020 }
5021
5022 static MonoDynamicImage*
5023 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5024 {
5025         static const guchar entrycode [16] = {0xff, 0x25, 0};
5026         MonoDynamicImage *image;
5027         int i;
5028
5029         const char *version;
5030
5031         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5032                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5033         else
5034                 version = mono_get_runtime_info ()->runtime_version;
5035
5036 #if HAVE_BOEHM_GC
5037         /* The MonoGHashTable's need GC tracking */
5038         image = GC_MALLOC (sizeof (MonoDynamicImage));
5039 #else
5040         image = g_new0 (MonoDynamicImage, 1);
5041 #endif
5042         
5043         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5044         
5045         /*g_print ("created image %p\n", image);*/
5046         /* keep in sync with image.c */
5047         image->image.name = assembly_name;
5048         image->image.assembly_name = image->image.name; /* they may be different */
5049         image->image.module_name = module_name;
5050         image->image.version = g_strdup (version);
5051         image->image.md_version_major = 1;
5052         image->image.md_version_minor = 1;
5053         image->image.dynamic = TRUE;
5054
5055         image->image.references = g_new0 (MonoAssembly*, 1);
5056         image->image.references [0] = NULL;
5057
5058         mono_image_init (&image->image);
5059
5060         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5061         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5062         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5063         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5064         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5065         image->handleref = g_hash_table_new (NULL, NULL);
5066         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5067         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5068         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5069         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5070         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5071         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5072         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5073         image->gen_params = g_ptr_array_new ();
5074
5075         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5076         string_heap_init (&image->sheap);
5077         mono_image_add_stream_data (&image->us, "", 1);
5078         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5079         /* import tables... */
5080         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5081         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5082         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5083         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5084         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5085         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5086         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5087         stream_data_align (&image->code);
5088
5089         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5090
5091         for (i=0; i < MONO_TABLE_NUM; ++i) {
5092                 image->tables [i].next_idx = 1;
5093                 image->tables [i].columns = table_sizes [i];
5094         }
5095
5096         image->image.assembly = (MonoAssembly*)assembly;
5097         image->run = assembly->run;
5098         image->save = assembly->save;
5099         image->pe_kind = 0x1; /* ILOnly */
5100         image->machine = 0x14c; /* I386 */
5101         
5102         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5103
5104         return image;
5105 }
5106 #endif
5107
5108 static void
5109 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5110 {
5111         g_free (key);
5112 }
5113
5114 void
5115 mono_dynamic_image_free (MonoDynamicImage *image)
5116 {
5117         MonoDynamicImage *di = image;
5118         GList *list;
5119         int i;
5120
5121         if (di->methodspec)
5122                 mono_g_hash_table_destroy (di->methodspec);
5123         if (di->typespec)
5124                 g_hash_table_destroy (di->typespec);
5125         if (di->typeref)
5126                 g_hash_table_destroy (di->typeref);
5127         if (di->handleref)
5128                 g_hash_table_destroy (di->handleref);
5129         if (di->handleref_managed)
5130                 mono_g_hash_table_destroy (di->handleref_managed);
5131         if (di->tokens)
5132                 mono_g_hash_table_destroy (di->tokens);
5133         if (di->generic_def_objects)
5134                 mono_g_hash_table_destroy (di->generic_def_objects);
5135         if (di->blob_cache) {
5136                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5137                 g_hash_table_destroy (di->blob_cache);
5138         }
5139         if (di->standalonesig_cache)
5140                 g_hash_table_destroy (di->standalonesig_cache);
5141         for (list = di->array_methods; list; list = list->next) {
5142                 ArrayMethod *am = (ArrayMethod *)list->data;
5143                 g_free (am->sig);
5144                 g_free (am->name);
5145                 g_free (am);
5146         }
5147         g_list_free (di->array_methods);
5148         if (di->gen_params) {
5149                 for (i = 0; i < di->gen_params->len; i++) {
5150                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5151                         if (entry->gparam->type.type) {
5152                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5153                                 g_free ((char*)mono_generic_param_info (param)->name);
5154                                 g_free (param);
5155                         }
5156                         mono_gc_deregister_root ((char*) &entry->gparam);
5157                         g_free (entry);
5158                 }
5159                 g_ptr_array_free (di->gen_params, TRUE);
5160         }
5161         if (di->token_fixups)
5162                 mono_g_hash_table_destroy (di->token_fixups);
5163         if (di->method_to_table_idx)
5164                 g_hash_table_destroy (di->method_to_table_idx);
5165         if (di->field_to_table_idx)
5166                 g_hash_table_destroy (di->field_to_table_idx);
5167         if (di->method_aux_hash)
5168                 g_hash_table_destroy (di->method_aux_hash);
5169         if (di->vararg_aux_hash)
5170                 g_hash_table_destroy (di->vararg_aux_hash);
5171         g_free (di->strong_name);
5172         g_free (di->win32_res);
5173         if (di->public_key)
5174                 g_free (di->public_key);
5175
5176         /*g_print ("string heap destroy for image %p\n", di);*/
5177         mono_dynamic_stream_reset (&di->sheap);
5178         mono_dynamic_stream_reset (&di->code);
5179         mono_dynamic_stream_reset (&di->resources);
5180         mono_dynamic_stream_reset (&di->us);
5181         mono_dynamic_stream_reset (&di->blob);
5182         mono_dynamic_stream_reset (&di->tstream);
5183         mono_dynamic_stream_reset (&di->guid);
5184         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5185                 g_free (di->tables [i].values);
5186         }
5187 }       
5188
5189 #ifndef DISABLE_REFLECTION_EMIT
5190
5191 /*
5192  * mono_image_basic_init:
5193  * @assembly: an assembly builder object
5194  *
5195  * Create the MonoImage that represents the assembly builder and setup some
5196  * of the helper hash table and the basic metadata streams.
5197  */
5198 void
5199 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5200 {
5201         MonoDynamicAssembly *assembly;
5202         MonoDynamicImage *image;
5203         MonoDomain *domain = mono_object_domain (assemblyb);
5204         
5205         MONO_ARCH_SAVE_REGS;
5206
5207         if (assemblyb->dynamic_assembly)
5208                 return;
5209
5210 #if HAVE_BOEHM_GC
5211         /* assembly->assembly.image might be GC allocated */
5212         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5213 #else
5214         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5215 #endif
5216
5217         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5218         
5219         assembly->assembly.ref_count = 1;
5220         assembly->assembly.dynamic = TRUE;
5221         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5222         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5223         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5224         if (assemblyb->culture)
5225                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5226         else
5227                 assembly->assembly.aname.culture = g_strdup ("");
5228
5229         if (assemblyb->version) {
5230                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5231                         char **version = g_strsplit (vstr, ".", 4);
5232                         char **parts = version;
5233                         assembly->assembly.aname.major = atoi (*parts++);
5234                         assembly->assembly.aname.minor = atoi (*parts++);
5235                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5236                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5237
5238                         g_strfreev (version);
5239                         g_free (vstr);
5240         } else {
5241                         assembly->assembly.aname.major = 0;
5242                         assembly->assembly.aname.minor = 0;
5243                         assembly->assembly.aname.build = 0;
5244                         assembly->assembly.aname.revision = 0;
5245         }
5246
5247         assembly->run = assemblyb->access != 2;
5248         assembly->save = assemblyb->access != 1;
5249         assembly->domain = domain;
5250
5251         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5252         image->initial_image = TRUE;
5253         assembly->assembly.aname.name = image->image.name;
5254         assembly->assembly.image = &image->image;
5255         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5256                 /* -1 to correct for the trailing NULL byte */
5257                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5258                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5259                 }
5260                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5261         }
5262
5263         mono_domain_assemblies_lock (domain);
5264         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5265         mono_domain_assemblies_unlock (domain);
5266
5267         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5268         
5269         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5270         
5271         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5272 }
5273
5274 #endif /* !DISABLE_REFLECTION_EMIT */
5275
5276 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5277
5278 static int
5279 calc_section_size (MonoDynamicImage *assembly)
5280 {
5281         int nsections = 0;
5282
5283         /* alignment constraints */
5284         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5285         g_assert ((assembly->code.index % 4) == 0);
5286         assembly->meta_size += 3;
5287         assembly->meta_size &= ~3;
5288         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5289         g_assert ((assembly->resources.index % 4) == 0);
5290
5291         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5292         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5293         nsections++;
5294
5295         if (assembly->win32_res) {
5296                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5297
5298                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5299                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5300                 nsections++;
5301         }
5302
5303         assembly->sections [MONO_SECTION_RELOC].size = 12;
5304         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5305         nsections++;
5306
5307         return nsections;
5308 }
5309
5310 typedef struct {
5311         guint32 id;
5312         guint32 offset;
5313         GSList *children;
5314         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5315 } ResTreeNode;
5316
5317 static int
5318 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5319 {
5320         ResTreeNode *t1 = (ResTreeNode*)a;
5321         ResTreeNode *t2 = (ResTreeNode*)b;
5322
5323         return t1->id - t2->id;
5324 }
5325
5326 /*
5327  * resource_tree_create:
5328  *
5329  *  Organize the resources into a resource tree.
5330  */
5331 static ResTreeNode *
5332 resource_tree_create (MonoArray *win32_resources)
5333 {
5334         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5335         GSList *l;
5336         int i;
5337
5338         tree = g_new0 (ResTreeNode, 1);
5339         
5340         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5341                 MonoReflectionWin32Resource *win32_res =
5342                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5343
5344                 /* Create node */
5345
5346                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5347                 lang_node = g_new0 (ResTreeNode, 1);
5348                 lang_node->id = win32_res->lang_id;
5349                 lang_node->win32_res = win32_res;
5350
5351                 /* Create type node if neccesary */
5352                 type_node = NULL;
5353                 for (l = tree->children; l; l = l->next)
5354                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5355                                 type_node = (ResTreeNode*)l->data;
5356                                 break;
5357                         }
5358
5359                 if (!type_node) {
5360                         type_node = g_new0 (ResTreeNode, 1);
5361                         type_node->id = win32_res->res_type;
5362
5363                         /* 
5364                          * The resource types have to be sorted otherwise
5365                          * Windows Explorer can't display the version information.
5366                          */
5367                         tree->children = g_slist_insert_sorted (tree->children, 
5368                                 type_node, resource_tree_compare_by_id);
5369                 }
5370
5371                 /* Create res node if neccesary */
5372                 res_node = NULL;
5373                 for (l = type_node->children; l; l = l->next)
5374                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5375                                 res_node = (ResTreeNode*)l->data;
5376                                 break;
5377                         }
5378
5379                 if (!res_node) {
5380                         res_node = g_new0 (ResTreeNode, 1);
5381                         res_node->id = win32_res->res_id;
5382                         type_node->children = g_slist_append (type_node->children, res_node);
5383                 }
5384
5385                 res_node->children = g_slist_append (res_node->children, lang_node);
5386         }
5387
5388         return tree;
5389 }
5390
5391 /*
5392  * resource_tree_encode:
5393  * 
5394  *   Encode the resource tree into the format used in the PE file.
5395  */
5396 static void
5397 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5398 {
5399         char *entries;
5400         MonoPEResourceDir dir;
5401         MonoPEResourceDirEntry dir_entry;
5402         MonoPEResourceDataEntry data_entry;
5403         GSList *l;
5404         guint32 res_id_entries;
5405
5406         /*
5407          * For the format of the resource directory, see the article
5408          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5409          * Matt Pietrek
5410          */
5411
5412         memset (&dir, 0, sizeof (dir));
5413         memset (&dir_entry, 0, sizeof (dir_entry));
5414         memset (&data_entry, 0, sizeof (data_entry));
5415
5416         g_assert (sizeof (dir) == 16);
5417         g_assert (sizeof (dir_entry) == 8);
5418         g_assert (sizeof (data_entry) == 16);
5419
5420         node->offset = p - begin;
5421
5422         /* IMAGE_RESOURCE_DIRECTORY */
5423         res_id_entries = g_slist_length (node->children);
5424         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5425
5426         memcpy (p, &dir, sizeof (dir));
5427         p += sizeof (dir);
5428
5429         /* Reserve space for entries */
5430         entries = p;
5431         p += sizeof (dir_entry) * res_id_entries;
5432
5433         /* Write children */
5434         for (l = node->children; l; l = l->next) {
5435                 ResTreeNode *child = (ResTreeNode*)l->data;
5436
5437                 if (child->win32_res) {
5438                         guint32 size;
5439
5440                         child->offset = p - begin;
5441
5442                         /* IMAGE_RESOURCE_DATA_ENTRY */
5443                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5444                         size = mono_array_length (child->win32_res->res_data);
5445                         data_entry.rde_size = GUINT32_TO_LE (size);
5446
5447                         memcpy (p, &data_entry, sizeof (data_entry));
5448                         p += sizeof (data_entry);
5449
5450                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5451                         p += size;
5452                 } else {
5453                         resource_tree_encode (child, begin, p, &p);
5454                 }
5455         }
5456
5457         /* IMAGE_RESOURCE_ENTRY */
5458         for (l = node->children; l; l = l->next) {
5459                 ResTreeNode *child = (ResTreeNode*)l->data;
5460
5461                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5462                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5463
5464                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5465                 entries += sizeof (dir_entry);
5466         }
5467
5468         *endbuf = p;
5469 }
5470
5471 static void
5472 resource_tree_free (ResTreeNode * node)
5473 {
5474         GSList * list;
5475         for (list = node->children; list; list = list->next)
5476                 resource_tree_free ((ResTreeNode*)list->data);
5477         g_slist_free(node->children);
5478         g_free (node);
5479 }
5480
5481 static void
5482 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5483 {
5484         char *buf;
5485         char *p;
5486         guint32 size, i;
5487         MonoReflectionWin32Resource *win32_res;
5488         ResTreeNode *tree;
5489
5490         if (!assemblyb->win32_resources)
5491                 return;
5492
5493         /*
5494          * Resources are stored in a three level tree inside the PE file.
5495          * - level one contains a node for each type of resource
5496          * - level two contains a node for each resource
5497          * - level three contains a node for each instance of a resource for a
5498          *   specific language.
5499          */
5500
5501         tree = resource_tree_create (assemblyb->win32_resources);
5502
5503         /* Estimate the size of the encoded tree */
5504         size = 0;
5505         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5506                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5507                 size += mono_array_length (win32_res->res_data);
5508         }
5509         /* Directory structure */
5510         size += mono_array_length (assemblyb->win32_resources) * 256;
5511         p = buf = g_malloc (size);
5512
5513         resource_tree_encode (tree, p, p, &p);
5514
5515         g_assert (p - buf <= size);
5516
5517         assembly->win32_res = g_malloc (p - buf);
5518         assembly->win32_res_size = p - buf;
5519         memcpy (assembly->win32_res, buf, p - buf);
5520
5521         g_free (buf);
5522         resource_tree_free (tree);
5523 }
5524
5525 static void
5526 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5527 {
5528         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5529         int i;
5530
5531         p += sizeof (MonoPEResourceDir);
5532         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5533                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5534                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5535                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5536                         fixup_resource_directory (res_section, child, rva);
5537                 } else {
5538                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5539                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5540                 }
5541
5542                 p += sizeof (MonoPEResourceDirEntry);
5543         }
5544 }
5545
5546 static void
5547 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5548 {
5549         guint32 dummy;
5550         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5551                 g_error ("WriteFile returned %d\n", GetLastError ());
5552 }
5553
5554 /*
5555  * mono_image_create_pefile:
5556  * @mb: a module builder object
5557  * 
5558  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5559  * assembly->pefile where it can be easily retrieved later in chunks.
5560  */
5561 void
5562 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5563 {
5564         MonoMSDOSHeader *msdos;
5565         MonoDotNetHeader *header;
5566         MonoSectionTable *section;
5567         MonoCLIHeader *cli_header;
5568         guint32 size, image_size, virtual_base, text_offset;
5569         guint32 header_start, section_start, file_offset, virtual_offset;
5570         MonoDynamicImage *assembly;
5571         MonoReflectionAssemblyBuilder *assemblyb;
5572         MonoDynamicStream pefile_stream = {0};
5573         MonoDynamicStream *pefile = &pefile_stream;
5574         int i, nsections;
5575         guint32 *rva, value;
5576         guchar *p;
5577         static const unsigned char msheader[] = {
5578                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5579                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5580                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5581                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5582                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5583                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5584                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5585                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5586         };
5587
5588         assemblyb = mb->assemblyb;
5589
5590         mono_image_basic_init (assemblyb);
5591         assembly = mb->dynamic_image;
5592
5593         assembly->pe_kind = assemblyb->pe_kind;
5594         assembly->machine = assemblyb->machine;
5595         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5596         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5597         
5598         mono_image_build_metadata (mb);
5599
5600         if (mb->is_main && assemblyb->resources) {
5601                 int len = mono_array_length (assemblyb->resources);
5602                 for (i = 0; i < len; ++i)
5603                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5604         }
5605
5606         if (mb->resources) {
5607                 int len = mono_array_length (mb->resources);
5608                 for (i = 0; i < len; ++i)
5609                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5610         }
5611
5612         build_compressed_metadata (assembly);
5613
5614         if (mb->is_main)
5615                 assembly_add_win32_resources (assembly, assemblyb);
5616
5617         nsections = calc_section_size (assembly);
5618         
5619         /* The DOS header and stub */
5620         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5621         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5622
5623         /* the dotnet header */
5624         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5625
5626         /* the section tables */
5627         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5628
5629         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5630         virtual_offset = VIRT_ALIGN;
5631         image_size = 0;
5632
5633         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5634                 if (!assembly->sections [i].size)
5635                         continue;
5636                 /* align offsets */
5637                 file_offset += FILE_ALIGN - 1;
5638                 file_offset &= ~(FILE_ALIGN - 1);
5639                 virtual_offset += VIRT_ALIGN - 1;
5640                 virtual_offset &= ~(VIRT_ALIGN - 1);
5641
5642                 assembly->sections [i].offset = file_offset;
5643                 assembly->sections [i].rva = virtual_offset;
5644
5645                 file_offset += assembly->sections [i].size;
5646                 virtual_offset += assembly->sections [i].size;
5647                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5648         }
5649
5650         file_offset += FILE_ALIGN - 1;
5651         file_offset &= ~(FILE_ALIGN - 1);
5652
5653         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5654
5655         /* back-patch info */
5656         msdos = (MonoMSDOSHeader*)pefile->data;
5657         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5658
5659         header = (MonoDotNetHeader*)(pefile->data + header_start);
5660         header->pesig [0] = 'P';
5661         header->pesig [1] = 'E';
5662         
5663         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5664         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5665         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5666         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5667         if (assemblyb->pekind == 1) {
5668                 /* it's a dll */
5669                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5670         } else {
5671                 /* it's an exe */
5672                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5673         }
5674
5675         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5676
5677         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5678         header->pe.pe_major = 6;
5679         header->pe.pe_minor = 0;
5680         size = assembly->sections [MONO_SECTION_TEXT].size;
5681         size += FILE_ALIGN - 1;
5682         size &= ~(FILE_ALIGN - 1);
5683         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5684         size = assembly->sections [MONO_SECTION_RSRC].size;
5685         size += FILE_ALIGN - 1;
5686         size &= ~(FILE_ALIGN - 1);
5687         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5688         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5689         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5690         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5691         /* pe_rva_entry_point always at the beginning of the text section */
5692         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5693
5694         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5695         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5696         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5697         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5698         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5699         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5700         size = section_start;
5701         size += FILE_ALIGN - 1;
5702         size &= ~(FILE_ALIGN - 1);
5703         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5704         size = image_size;
5705         size += VIRT_ALIGN - 1;
5706         size &= ~(VIRT_ALIGN - 1);
5707         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5708
5709         /*
5710         // Translate the PEFileKind value to the value expected by the Windows loader
5711         */
5712         {
5713                 short kind;
5714
5715                 /*
5716                 // PEFileKinds.Dll == 1
5717                 // PEFileKinds.ConsoleApplication == 2
5718                 // PEFileKinds.WindowApplication == 3
5719                 //
5720                 // need to get:
5721                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5722                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5723                 */
5724                 if (assemblyb->pekind == 3)
5725                         kind = 2;
5726                 else
5727                         kind = 3;
5728                 
5729                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5730         }    
5731         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5732         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5733         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5734         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5735         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5736         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5737
5738         /* fill data directory entries */
5739
5740         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5741         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5742
5743         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5744         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5745
5746         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5747         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5748         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5749         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5750         /* patch entrypoint name */
5751         if (assemblyb->pekind == 1)
5752                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5753         else
5754                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5755         /* patch imported function RVA name */
5756         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5757         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5758
5759         /* the import table */
5760         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5761         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5762         /* patch imported dll RVA name and other entries in the dir */
5763         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5764         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5765         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5766         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5767         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5768         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5769
5770         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5771         value = (assembly->text_rva + assembly->imp_names_offset);
5772         *p++ = (value) & 0xff;
5773         *p++ = (value >> 8) & (0xff);
5774         *p++ = (value >> 16) & (0xff);
5775         *p++ = (value >> 24) & (0xff);
5776
5777         /* the CLI header info */
5778         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5779         cli_header->ch_size = GUINT32_FROM_LE (72);
5780         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5781         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5782         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5783         if (assemblyb->entry_point) {
5784                 guint32 table_idx = 0;
5785                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5786                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5787                         table_idx = methodb->table_idx;
5788                 } else {
5789                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5790                 }
5791                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5792         } else {
5793                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5794         }
5795         /* The embedded managed resources */
5796         text_offset = assembly->text_rva + assembly->code.index;
5797         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5798         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5799         text_offset += assembly->resources.index;
5800         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5801         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5802         text_offset += assembly->meta_size;
5803         if (assembly->strong_name_size) {
5804                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5805                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5806                 text_offset += assembly->strong_name_size;
5807         }
5808
5809         /* write the section tables and section content */
5810         section = (MonoSectionTable*)(pefile->data + section_start);
5811         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5812                 static const char section_names [][7] = {
5813                         ".text", ".rsrc", ".reloc"
5814                 };
5815                 if (!assembly->sections [i].size)
5816                         continue;
5817                 strcpy (section->st_name, section_names [i]);
5818                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5819                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5820                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5821                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5822                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5823                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5824                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5825                 section ++;
5826         }
5827         
5828         checked_write_file (file, pefile->data, pefile->index);
5829         
5830         mono_dynamic_stream_reset (pefile);
5831         
5832         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5833                 if (!assembly->sections [i].size)
5834                         continue;
5835                 
5836                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5837                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5838                 
5839                 switch (i) {
5840                 case MONO_SECTION_TEXT:
5841                         /* patch entry point */
5842                         p = (guchar*)(assembly->code.data + 2);
5843                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5844                         *p++ = (value) & 0xff;
5845                         *p++ = (value >> 8) & 0xff;
5846                         *p++ = (value >> 16) & 0xff;
5847                         *p++ = (value >> 24) & 0xff;
5848                 
5849                         checked_write_file (file, assembly->code.data, assembly->code.index);
5850                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5851                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5852                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5853                                 
5854
5855                         g_free (assembly->image.raw_metadata);
5856                         break;
5857                 case MONO_SECTION_RELOC: {
5858                         struct {
5859                                 guint32 page_rva;
5860                                 guint32 block_size;
5861                                 guint16 type_and_offset;
5862                                 guint16 term;
5863                         } reloc;
5864                         
5865                         g_assert (sizeof (reloc) == 12);
5866                         
5867                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5868                         reloc.block_size = GUINT32_FROM_LE (12);
5869                         
5870                         /* 
5871                          * the entrypoint is always at the start of the text section 
5872                          * 3 is IMAGE_REL_BASED_HIGHLOW
5873                          * 2 is patch_size_rva - text_rva
5874                          */
5875                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5876                         reloc.term = 0;
5877                         
5878                         checked_write_file (file, &reloc, sizeof (reloc));
5879                         
5880                         break;
5881                 }
5882                 case MONO_SECTION_RSRC:
5883                         if (assembly->win32_res) {
5884
5885                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5886                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5887                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5888                         }
5889                         break;
5890                 default:
5891                         g_assert_not_reached ();
5892                 }
5893         }
5894         
5895         /* check that the file is properly padded */
5896         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5897                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5898         if (! SetEndOfFile (file))
5899                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5900         
5901         mono_dynamic_stream_reset (&assembly->code);
5902         mono_dynamic_stream_reset (&assembly->us);
5903         mono_dynamic_stream_reset (&assembly->blob);
5904         mono_dynamic_stream_reset (&assembly->guid);
5905         mono_dynamic_stream_reset (&assembly->sheap);
5906
5907         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5908         g_hash_table_destroy (assembly->blob_cache);
5909         assembly->blob_cache = NULL;
5910 }
5911
5912 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5913
5914 void
5915 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5916 {
5917         g_assert_not_reached ();
5918 }
5919
5920 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5921
5922 #ifndef DISABLE_REFLECTION_EMIT
5923
5924 MonoReflectionModule *
5925 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5926 {
5927         char *name;
5928         MonoImage *image;
5929         MonoImageOpenStatus status;
5930         MonoDynamicAssembly *assembly;
5931         guint32 module_count;
5932         MonoImage **new_modules;
5933         gboolean *new_modules_loaded;
5934         
5935         name = mono_string_to_utf8 (fileName);
5936
5937         image = mono_image_open (name, &status);
5938         if (!image) {
5939                 MonoException *exc;
5940                 if (status == MONO_IMAGE_ERROR_ERRNO)
5941                         exc = mono_get_exception_file_not_found (fileName);
5942                 else
5943                         exc = mono_get_exception_bad_image_format (name);
5944                 g_free (name);
5945                 mono_raise_exception (exc);
5946         }
5947
5948         g_free (name);
5949
5950         assembly = ab->dynamic_assembly;
5951         image->assembly = (MonoAssembly*)assembly;
5952
5953         module_count = image->assembly->image->module_count;
5954         new_modules = g_new0 (MonoImage *, module_count + 1);
5955         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5956
5957         if (image->assembly->image->modules)
5958                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5959         if (image->assembly->image->modules_loaded)
5960                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5961         new_modules [module_count] = image;
5962         new_modules_loaded [module_count] = TRUE;
5963         mono_image_addref (image);
5964
5965         g_free (image->assembly->image->modules);
5966         image->assembly->image->modules = new_modules;
5967         image->assembly->image->modules_loaded = new_modules_loaded;
5968         image->assembly->image->module_count ++;
5969
5970         mono_assembly_load_references (image, &status);
5971         if (status) {
5972                 mono_image_close (image);
5973                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5974         }
5975
5976         return mono_module_get_object (mono_domain_get (), image);
5977 }
5978
5979 #endif /* DISABLE_REFLECTION_EMIT */
5980
5981 /*
5982  * We need to return always the same object for MethodInfo, FieldInfo etc..
5983  * but we need to consider the reflected type.
5984  * type uses a different hash, since it uses custom hash/equal functions.
5985  */
5986
5987 typedef struct {
5988         gpointer item;
5989         MonoClass *refclass;
5990 } ReflectedEntry;
5991
5992 static gboolean
5993 reflected_equal (gconstpointer a, gconstpointer b) {
5994         const ReflectedEntry *ea = a;
5995         const ReflectedEntry *eb = b;
5996
5997         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5998 }
5999
6000 static guint
6001 reflected_hash (gconstpointer a) {
6002         const ReflectedEntry *ea = a;
6003         return mono_aligned_addr_hash (ea->item);
6004 }
6005
6006 #define CHECK_OBJECT(t,p,k)     \
6007         do {    \
6008                 t _obj; \
6009                 ReflectedEntry e;       \
6010                 e.item = (p);   \
6011                 e.refclass = (k);       \
6012                 mono_domain_lock (domain);      \
6013                 if (!domain->refobject_hash)    \
6014                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6015                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6016                         mono_domain_unlock (domain);    \
6017                         return _obj;    \
6018                 }       \
6019         mono_domain_unlock (domain); \
6020         } while (0)
6021
6022 #ifdef HAVE_BOEHM_GC
6023 /* ReflectedEntry doesn't need to be GC tracked */
6024 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6025 #define FREE_REFENTRY(entry) g_free ((entry))
6026 #define REFENTRY_REQUIRES_CLEANUP
6027 #else
6028 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6029 /* FIXME: */
6030 #define FREE_REFENTRY(entry)
6031 #endif
6032
6033 #define CACHE_OBJECT(t,p,o,k)   \
6034         do {    \
6035                 t _obj; \
6036         ReflectedEntry pe; \
6037         pe.item = (p); \
6038         pe.refclass = (k); \
6039         mono_domain_lock (domain); \
6040                 if (!domain->refobject_hash)    \
6041                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6042         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6043         if (!_obj) { \
6044                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6045                     e->item = (p);      \
6046                     e->refclass = (k);  \
6047                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6048             _obj = o; \
6049         } \
6050                 mono_domain_unlock (domain);    \
6051         return _obj; \
6052         } while (0)
6053
6054 static void
6055 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6056 {
6057         mono_domain_lock (domain);
6058         if (domain->refobject_hash) {
6059         ReflectedEntry pe;
6060                 gpointer orig_pe, orig_value;
6061
6062                 pe.item = o;
6063                 pe.refclass = klass;
6064                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6065                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6066                         FREE_REFENTRY (orig_pe);
6067                 }
6068         }
6069         mono_domain_unlock (domain);
6070 }
6071
6072 #ifdef REFENTRY_REQUIRES_CLEANUP
6073 static void
6074 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6075 {
6076         FREE_REFENTRY (key);
6077 }
6078 #endif
6079
6080 void
6081 mono_reflection_cleanup_domain (MonoDomain *domain)
6082 {
6083         if (domain->refobject_hash) {
6084 /*let's avoid scanning the whole hashtable if not needed*/
6085 #ifdef REFENTRY_REQUIRES_CLEANUP
6086                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6087 #endif
6088                 mono_g_hash_table_destroy (domain->refobject_hash);
6089                 domain->refobject_hash = NULL;
6090         }
6091 }
6092
6093 #ifndef DISABLE_REFLECTION_EMIT
6094 static gpointer
6095 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6096 {
6097         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6098 }
6099
6100 static gpointer
6101 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6102 {
6103         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6104 }
6105
6106 void
6107 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6108 {
6109         MonoDynamicImage *image = moduleb->dynamic_image;
6110         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6111         if (!image) {
6112                 MonoError error;
6113                 int module_count;
6114                 MonoImage **new_modules;
6115                 MonoImage *ass;
6116                 char *name, *fqname;
6117                 /*
6118                  * FIXME: we already created an image in mono_image_basic_init (), but
6119                  * we don't know which module it belongs to, since that is only 
6120                  * determined at assembly save time.
6121                  */
6122                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6123                 name = mono_string_to_utf8 (ab->name);
6124                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6125                 if (!mono_error_ok (&error)) {
6126                         g_free (name);
6127                         mono_error_raise_exception (&error);
6128                 }
6129                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6130
6131                 moduleb->module.image = &image->image;
6132                 moduleb->dynamic_image = image;
6133                 register_module (mono_object_domain (moduleb), moduleb, image);
6134
6135                 /* register the module with the assembly */
6136                 ass = ab->dynamic_assembly->assembly.image;
6137                 module_count = ass->module_count;
6138                 new_modules = g_new0 (MonoImage *, module_count + 1);
6139
6140                 if (ass->modules)
6141                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6142                 new_modules [module_count] = &image->image;
6143                 mono_image_addref (&image->image);
6144
6145                 g_free (ass->modules);
6146                 ass->modules = new_modules;
6147                 ass->module_count ++;
6148         }
6149 }
6150
6151 void
6152 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6153 {
6154         MonoDynamicImage *image = moduleb->dynamic_image;
6155
6156         g_assert (type->type);
6157         image->wrappers_type = mono_class_from_mono_type (type->type);
6158 }
6159
6160 #endif
6161
6162 /*
6163  * mono_assembly_get_object:
6164  * @domain: an app domain
6165  * @assembly: an assembly
6166  *
6167  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6168  */
6169 MonoReflectionAssembly*
6170 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6171 {
6172         static MonoClass *assembly_type;
6173         MonoReflectionAssembly *res;
6174         
6175         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6176         if (!assembly_type) {
6177                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6178                 if (class == NULL)
6179                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6180                 g_assert (class);
6181                 assembly_type = class;
6182         }
6183         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6184         res->assembly = assembly;
6185
6186         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6187 }
6188
6189
6190
6191 MonoReflectionModule*   
6192 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6193 {
6194         static MonoClass *module_type;
6195         MonoReflectionModule *res;
6196         char* basename;
6197         
6198         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6199         if (!module_type) {
6200                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6201                 if (class == NULL)
6202                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6203                 g_assert (class);
6204                 module_type = class;
6205         }
6206         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6207
6208         res->image = image;
6209         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6210
6211         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6212         basename = g_path_get_basename (image->name);
6213         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6214         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6215         
6216         g_free (basename);
6217
6218         if (image->assembly->image == image) {
6219                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6220         } else {
6221                 int i;
6222                 res->token = 0;
6223                 if (image->assembly->image->modules) {
6224                         for (i = 0; i < image->assembly->image->module_count; i++) {
6225                                 if (image->assembly->image->modules [i] == image)
6226                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6227                         }
6228                         g_assert (res->token);
6229                 }
6230         }
6231
6232         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6233 }
6234
6235 MonoReflectionModule*   
6236 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6237 {
6238         static MonoClass *module_type;
6239         MonoReflectionModule *res;
6240         MonoTableInfo *table;
6241         guint32 cols [MONO_FILE_SIZE];
6242         const char *name;
6243         guint32 i, name_idx;
6244         const char *val;
6245         
6246         if (!module_type) {
6247                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6248                 if (class == NULL)
6249                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6250                 g_assert (class);
6251                 module_type = class;
6252         }
6253         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6254
6255         table = &image->tables [MONO_TABLE_FILE];
6256         g_assert (table_index < table->rows);
6257         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6258
6259         res->image = NULL;
6260         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6261         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6262
6263         /* Check whenever the row has a corresponding row in the moduleref table */
6264         table = &image->tables [MONO_TABLE_MODULEREF];
6265         for (i = 0; i < table->rows; ++i) {
6266                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6267                 val = mono_metadata_string_heap (image, name_idx);
6268                 if (strcmp (val, name) == 0)
6269                         res->image = image->modules [i];
6270         }
6271
6272         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6273         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6274         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6275         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6276         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6277
6278         return res;
6279 }
6280
6281 static gboolean
6282 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6283 {
6284         if ((t1->type != t2->type) ||
6285             (t1->byref != t2->byref))
6286                 return FALSE;
6287
6288         switch (t1->type) {
6289         case MONO_TYPE_VOID:
6290         case MONO_TYPE_BOOLEAN:
6291         case MONO_TYPE_CHAR:
6292         case MONO_TYPE_I1:
6293         case MONO_TYPE_U1:
6294         case MONO_TYPE_I2:
6295         case MONO_TYPE_U2:
6296         case MONO_TYPE_I4:
6297         case MONO_TYPE_U4:
6298         case MONO_TYPE_I8:
6299         case MONO_TYPE_U8:
6300         case MONO_TYPE_R4:
6301         case MONO_TYPE_R8:
6302         case MONO_TYPE_STRING:
6303         case MONO_TYPE_I:
6304         case MONO_TYPE_U:
6305         case MONO_TYPE_OBJECT:
6306         case MONO_TYPE_TYPEDBYREF:
6307                 return TRUE;
6308         case MONO_TYPE_VALUETYPE:
6309         case MONO_TYPE_CLASS:
6310         case MONO_TYPE_SZARRAY:
6311                 return t1->data.klass == t2->data.klass;
6312         case MONO_TYPE_PTR:
6313                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6314         case MONO_TYPE_ARRAY:
6315                 if (t1->data.array->rank != t2->data.array->rank)
6316                         return FALSE;
6317                 return t1->data.array->eklass == t2->data.array->eklass;
6318         case MONO_TYPE_GENERICINST: {
6319                 int i;
6320                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6321                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6322                 if (i1->type_argc != i2->type_argc)
6323                         return FALSE;
6324                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6325                                                &t2->data.generic_class->container_class->byval_arg))
6326                         return FALSE;
6327                 /* FIXME: we should probably just compare the instance pointers directly.  */
6328                 for (i = 0; i < i1->type_argc; ++i) {
6329                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6330                                 return FALSE;
6331                 }
6332                 return TRUE;
6333         }
6334         case MONO_TYPE_VAR:
6335         case MONO_TYPE_MVAR:
6336                 return t1->data.generic_param == t2->data.generic_param;
6337         default:
6338                 g_error ("implement type compare for %0x!", t1->type);
6339                 return FALSE;
6340         }
6341
6342         return FALSE;
6343 }
6344
6345 static guint
6346 mymono_metadata_type_hash (MonoType *t1)
6347 {
6348         guint hash;
6349
6350         hash = t1->type;
6351
6352         hash |= t1->byref << 6; /* do not collide with t1->type values */
6353         switch (t1->type) {
6354         case MONO_TYPE_VALUETYPE:
6355         case MONO_TYPE_CLASS:
6356         case MONO_TYPE_SZARRAY:
6357                 /* check if the distribution is good enough */
6358                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6359         case MONO_TYPE_PTR:
6360                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6361         case MONO_TYPE_GENERICINST: {
6362                 int i;
6363                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6364                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6365                 hash *= 13;
6366                 for (i = 0; i < inst->type_argc; ++i) {
6367                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6368                         hash *= 13;
6369                 }
6370                 return hash;
6371         }
6372         }
6373         return hash;
6374 }
6375
6376 static gboolean
6377 verify_safe_for_managed_space (MonoType *type)
6378 {
6379         switch (type->type) {
6380 #ifdef DEBUG_HARDER
6381         case MONO_TYPE_ARRAY:
6382                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6383         case MONO_TYPE_PTR:
6384                 return verify_safe_for_managed_space (type->data.type);
6385         case MONO_TYPE_SZARRAY:
6386                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6387         case MONO_TYPE_GENERICINST: {
6388                 MonoGenericInst *inst = type->data.generic_class->inst;
6389                 int i;
6390                 if (!inst->is_open)
6391                         break;
6392                 for (i = 0; i < inst->type_argc; ++i)
6393                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6394                                 return FALSE;
6395                 break;
6396         }
6397 #endif
6398         case MONO_TYPE_VAR:
6399         case MONO_TYPE_MVAR:
6400                 return TRUE;
6401         }
6402         return TRUE;
6403 }
6404
6405 static MonoType*
6406 mono_type_normalize (MonoType *type)
6407 {
6408         int i;
6409         MonoGenericClass *gclass;
6410         MonoGenericInst *ginst;
6411         MonoClass *gtd;
6412         MonoGenericContainer *gcontainer;
6413         MonoType **argv = NULL;
6414         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6415
6416         if (type->type != MONO_TYPE_GENERICINST)
6417                 return type;
6418
6419         gclass = type->data.generic_class;
6420         ginst = gclass->context.class_inst;
6421         if (!ginst->is_open)
6422                 return type;
6423
6424         gtd = gclass->container_class;
6425         gcontainer = gtd->generic_container;
6426         argv = g_newa (MonoType*, ginst->type_argc);
6427
6428         for (i = 0; i < ginst->type_argc; ++i) {
6429                 MonoType *t = ginst->type_argv [i], *norm;
6430                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6431                         is_denorm_gtd = FALSE;
6432                 norm = mono_type_normalize (t);
6433                 argv [i] = norm;
6434                 if (norm != t)
6435                         requires_rebind = TRUE;
6436         }
6437
6438         if (is_denorm_gtd)
6439                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6440
6441         if (requires_rebind) {
6442                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6443                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6444         }
6445
6446         return type;
6447 }
6448 /*
6449  * mono_type_get_object:
6450  * @domain: an app domain
6451  * @type: a type
6452  *
6453  * Return an System.MonoType object representing the type @type.
6454  */
6455 MonoReflectionType*
6456 mono_type_get_object (MonoDomain *domain, MonoType *type)
6457 {
6458         MonoType *norm_type;
6459         MonoReflectionType *res;
6460         MonoClass *klass = mono_class_from_mono_type (type);
6461
6462         /*we must avoid using @type as it might have come
6463          * from a mono_metadata_type_dup and the caller
6464          * expects that is can be freed.
6465          * Using the right type from 
6466          */
6467         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6468
6469         /* void is very common */
6470         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6471                 return (MonoReflectionType*)domain->typeof_void;
6472
6473         /*
6474          * If the vtable of the given class was already created, we can use
6475          * the MonoType from there and avoid all locking and hash table lookups.
6476          * 
6477          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6478          * that the resulting object is different.   
6479          */
6480         if (type == &klass->byval_arg && !klass->image->dynamic) {
6481                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6482                 if (vtable && vtable->type)
6483                         return vtable->type;
6484         }
6485
6486         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6487         mono_domain_lock (domain);
6488         if (!domain->type_hash)
6489                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6490                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6491         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6492                 mono_domain_unlock (domain);
6493                 mono_loader_unlock ();
6494                 return res;
6495         }
6496
6497         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6498          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6499          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6500          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6501          * artifact of how generics are encoded and should be transparent to managed code so we
6502          * need to weed out this diference when retrieving managed System.Type objects.
6503          */
6504         norm_type = mono_type_normalize (type);
6505         if (norm_type != type) {
6506                 res = mono_type_get_object (domain, norm_type);
6507                 mono_g_hash_table_insert (domain->type_hash, type, res);
6508                 mono_domain_unlock (domain);
6509                 mono_loader_unlock ();
6510                 return res;
6511         }
6512
6513         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6514         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6515                 g_assert (0);
6516
6517         if (!verify_safe_for_managed_space (type)) {
6518                 mono_domain_unlock (domain);
6519                 mono_loader_unlock ();
6520                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6521         }
6522
6523         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6524                 gboolean is_type_done = TRUE;
6525                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6526                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6527                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6528                 */
6529                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6530                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6531
6532                         if (gparam->owner && gparam->owner->is_method) {
6533                                 MonoMethod *method = gparam->owner->owner.method;
6534                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6535                                         is_type_done = FALSE;
6536                         } else if (gparam->owner && !gparam->owner->is_method) {
6537                                 MonoClass *klass = gparam->owner->owner.klass;
6538                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6539                                         is_type_done = FALSE;
6540                         }
6541                 } 
6542
6543                 /* g_assert_not_reached (); */
6544                 /* should this be considered an error condition? */
6545                 if (is_type_done && !type->byref) {
6546                         mono_domain_unlock (domain);
6547                         mono_loader_unlock ();
6548                         return mono_class_get_ref_info (klass);
6549                 }
6550         }
6551 #ifdef HAVE_SGEN_GC
6552         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6553 #else
6554         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6555 #endif
6556         res->type = type;
6557         mono_g_hash_table_insert (domain->type_hash, type, res);
6558
6559         if (type->type == MONO_TYPE_VOID)
6560                 domain->typeof_void = (MonoObject*)res;
6561
6562         mono_domain_unlock (domain);
6563         mono_loader_unlock ();
6564         return res;
6565 }
6566
6567 /*
6568  * mono_method_get_object:
6569  * @domain: an app domain
6570  * @method: a method
6571  * @refclass: the reflected type (can be NULL)
6572  *
6573  * Return an System.Reflection.MonoMethod object representing the method @method.
6574  */
6575 MonoReflectionMethod*
6576 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6577 {
6578         /*
6579          * We use the same C representation for methods and constructors, but the type 
6580          * name in C# is different.
6581          */
6582         static MonoClass *System_Reflection_MonoMethod = NULL;
6583         static MonoClass *System_Reflection_MonoCMethod = NULL;
6584         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6585         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6586         MonoClass *klass;
6587         MonoReflectionMethod *ret;
6588
6589         if (method->is_inflated) {
6590                 MonoReflectionGenericMethod *gret;
6591
6592                 refclass = method->klass;
6593                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6594                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6595                         if (!System_Reflection_MonoGenericCMethod)
6596                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6597                         klass = System_Reflection_MonoGenericCMethod;
6598                 } else {
6599                         if (!System_Reflection_MonoGenericMethod)
6600                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6601                         klass = System_Reflection_MonoGenericMethod;
6602                 }
6603                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6604                 gret->method.method = method;
6605                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6606                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6607                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6608         }
6609
6610         if (!refclass)
6611                 refclass = method->klass;
6612
6613         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6614         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6615                 if (!System_Reflection_MonoCMethod)
6616                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6617                 klass = System_Reflection_MonoCMethod;
6618         }
6619         else {
6620                 if (!System_Reflection_MonoMethod)
6621                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6622                 klass = System_Reflection_MonoMethod;
6623         }
6624         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6625         ret->method = method;
6626         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6627         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6628 }
6629
6630 /*
6631  * mono_method_clear_object:
6632  *
6633  *   Clear the cached reflection objects for the dynamic method METHOD.
6634  */
6635 void
6636 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6637 {
6638         MonoClass *klass;
6639         g_assert (method->dynamic);
6640
6641         klass = method->klass;
6642         while (klass) {
6643                 clear_cached_object (domain, method, klass);
6644                 klass = klass->parent;
6645         }
6646         /* Added by mono_param_get_objects () */
6647         clear_cached_object (domain, &(method->signature), NULL);
6648         klass = method->klass;
6649         while (klass) {
6650                 clear_cached_object (domain, &(method->signature), klass);
6651                 klass = klass->parent;
6652         }
6653 }
6654
6655 /*
6656  * mono_field_get_object:
6657  * @domain: an app domain
6658  * @klass: a type
6659  * @field: a field
6660  *
6661  * Return an System.Reflection.MonoField object representing the field @field
6662  * in class @klass.
6663  */
6664 MonoReflectionField*
6665 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6666 {
6667         MonoReflectionField *res;
6668         static MonoClass *monofield_klass;
6669
6670         CHECK_OBJECT (MonoReflectionField *, field, klass);
6671         if (!monofield_klass)
6672                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6673         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6674         res->klass = klass;
6675         res->field = field;
6676         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6677         if (is_field_on_inst (field))
6678                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6679         else
6680                 res->attrs = field->type->attrs;
6681         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6682         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6683 }
6684
6685 /*
6686  * mono_property_get_object:
6687  * @domain: an app domain
6688  * @klass: a type
6689  * @property: a property
6690  *
6691  * Return an System.Reflection.MonoProperty object representing the property @property
6692  * in class @klass.
6693  */
6694 MonoReflectionProperty*
6695 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6696 {
6697         MonoReflectionProperty *res;
6698         static MonoClass *monoproperty_klass;
6699
6700         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6701         if (!monoproperty_klass)
6702                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6703         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6704         res->klass = klass;
6705         res->property = property;
6706         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6707 }
6708
6709 /*
6710  * mono_event_get_object:
6711  * @domain: an app domain
6712  * @klass: a type
6713  * @event: a event
6714  *
6715  * Return an System.Reflection.MonoEvent object representing the event @event
6716  * in class @klass.
6717  */
6718 MonoReflectionEvent*
6719 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6720 {
6721         MonoReflectionEvent *res;
6722         MonoReflectionMonoEvent *mono_event;
6723         static MonoClass *monoevent_klass;
6724
6725         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6726         if (!monoevent_klass)
6727                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6728         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6729         mono_event->klass = klass;
6730         mono_event->event = event;
6731         res = (MonoReflectionEvent*)mono_event;
6732         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6733 }
6734
6735 /**
6736  * mono_get_reflection_missing_object:
6737  * @domain: Domain where the object lives
6738  *
6739  * Returns the System.Reflection.Missing.Value singleton object
6740  * (of type System.Reflection.Missing).
6741  *
6742  * Used as the value for ParameterInfo.DefaultValue when Optional
6743  * is present
6744  */
6745 static MonoObject *
6746 mono_get_reflection_missing_object (MonoDomain *domain)
6747 {
6748         MonoObject *obj;
6749         static MonoClassField *missing_value_field = NULL;
6750         
6751         if (!missing_value_field) {
6752                 MonoClass *missing_klass;
6753                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6754                 mono_class_init (missing_klass);
6755                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6756                 g_assert (missing_value_field);
6757         }
6758         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6759         g_assert (obj);
6760         return obj;
6761 }
6762
6763 static MonoObject*
6764 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6765 {
6766         if (!*dbnull)
6767                 *dbnull = mono_get_dbnull_object (domain);
6768         return *dbnull;
6769 }
6770
6771 static MonoObject*
6772 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6773 {
6774         if (!*reflection_missing)
6775                 *reflection_missing = mono_get_reflection_missing_object (domain);
6776         return *reflection_missing;
6777 }
6778
6779 /*
6780  * mono_param_get_objects:
6781  * @domain: an app domain
6782  * @method: a method
6783  *
6784  * Return an System.Reflection.ParameterInfo array object representing the parameters
6785  * in the method @method.
6786  */
6787 MonoArray*
6788 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6789 {
6790         static MonoClass *System_Reflection_ParameterInfo;
6791         static MonoClass *System_Reflection_ParameterInfo_array;
6792         MonoArray *res = NULL;
6793         MonoReflectionMethod *member = NULL;
6794         MonoReflectionParameter *param = NULL;
6795         char **names, **blobs = NULL;
6796         guint32 *types = NULL;
6797         MonoType *type = NULL;
6798         MonoObject *dbnull = NULL;
6799         MonoObject *missing = NULL;
6800         MonoMarshalSpec **mspecs;
6801         MonoMethodSignature *sig;
6802         MonoVTable *pinfo_vtable;
6803         int i;
6804
6805         if (!System_Reflection_ParameterInfo_array) {
6806                 MonoClass *klass;
6807
6808                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6809                 mono_memory_barrier ();
6810                 System_Reflection_ParameterInfo = klass; 
6811         
6812                 klass = mono_array_class_get (klass, 1);
6813                 mono_memory_barrier ();
6814                 System_Reflection_ParameterInfo_array = klass;
6815         }
6816         
6817         if (!mono_method_signature (method)->param_count)
6818                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6819
6820         /* Note: the cache is based on the address of the signature into the method
6821          * since we already cache MethodInfos with the method as keys.
6822          */
6823         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6824
6825         sig = mono_method_signature (method);
6826         member = mono_method_get_object (domain, method, refclass);
6827         names = g_new (char *, sig->param_count);
6828         mono_method_get_param_names (method, (const char **) names);
6829
6830         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6831         mono_method_get_marshal_info (method, mspecs);
6832
6833         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6834         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6835         for (i = 0; i < sig->param_count; ++i) {
6836                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6837                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6838                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6839                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6840                 param->PositionImpl = i;
6841                 param->AttrsImpl = sig->params [i]->attrs;
6842
6843                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6844                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6845                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6846                         else
6847                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6848                 } else {
6849
6850                         if (!blobs) {
6851                                 blobs = g_new0 (char *, sig->param_count);
6852                                 types = g_new0 (guint32, sig->param_count);
6853                                 get_default_param_value_blobs (method, blobs, types); 
6854                         }
6855
6856                         /* Build MonoType for the type from the Constant Table */
6857                         if (!type)
6858                                 type = g_new0 (MonoType, 1);
6859                         type->type = types [i];
6860                         type->data.klass = NULL;
6861                         if (types [i] == MONO_TYPE_CLASS)
6862                                 type->data.klass = mono_defaults.object_class;
6863                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6864                                 /* For enums, types [i] contains the base type */
6865
6866                                         type->type = MONO_TYPE_VALUETYPE;
6867                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6868                         } else
6869                                 type->data.klass = mono_class_from_mono_type (type);
6870
6871                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6872
6873                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6874                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6875                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6876                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6877                                 else
6878                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6879                         }
6880                         
6881                 }
6882
6883                 if (mspecs [i + 1])
6884                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6885                 
6886                 mono_array_setref (res, i, param);
6887         }
6888         g_free (names);
6889         g_free (blobs);
6890         g_free (types);
6891         g_free (type);
6892
6893         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6894                 if (mspecs [i])
6895                         mono_metadata_free_marshal_spec (mspecs [i]);
6896         g_free (mspecs);
6897         
6898         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6899 }
6900
6901 MonoArray*
6902 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6903 {
6904         return mono_param_get_objects_internal (domain, method, NULL);
6905 }
6906
6907 /*
6908  * mono_method_body_get_object:
6909  * @domain: an app domain
6910  * @method: a method
6911  *
6912  * Return an System.Reflection.MethodBody object representing the method @method.
6913  */
6914 MonoReflectionMethodBody*
6915 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6916 {
6917         static MonoClass *System_Reflection_MethodBody = NULL;
6918         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6919         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6920         MonoReflectionMethodBody *ret;
6921         MonoMethodHeader *header;
6922         guint32 method_rva, local_var_sig_token;
6923     char *ptr;
6924         unsigned char format, flags;
6925         int i;
6926
6927         if (!System_Reflection_MethodBody)
6928                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6929         if (!System_Reflection_LocalVariableInfo)
6930                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6931         if (!System_Reflection_ExceptionHandlingClause)
6932                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6933
6934         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6935
6936         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6937                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6938             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6939             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6940                 return NULL;
6941         header = mono_method_get_header (method);
6942         
6943         /* Obtain local vars signature token */
6944         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6945         ptr = mono_image_rva_map (method->klass->image, method_rva);
6946         flags = *(const unsigned char *) ptr;
6947         format = flags & METHOD_HEADER_FORMAT_MASK;
6948         switch (format){
6949         case METHOD_HEADER_TINY_FORMAT:
6950                 local_var_sig_token = 0;
6951                 break;
6952         case METHOD_HEADER_FAT_FORMAT:
6953                 ptr += 2;
6954                 ptr += 2;
6955                 ptr += 4;
6956                 local_var_sig_token = read32 (ptr);
6957                 break;
6958         default:
6959                 g_assert_not_reached ();
6960         }
6961
6962         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6963
6964         ret->init_locals = header->init_locals;
6965         ret->max_stack = header->max_stack;
6966         ret->local_var_sig_token = local_var_sig_token;
6967         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6968         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6969
6970         /* Locals */
6971         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6972         for (i = 0; i < header->num_locals; ++i) {
6973                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6974                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6975                 info->is_pinned = header->locals [i]->pinned;
6976                 info->local_index = i;
6977                 mono_array_setref (ret->locals, i, info);
6978         }
6979
6980         /* Exceptions */
6981         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6982         for (i = 0; i < header->num_clauses; ++i) {
6983                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6984                 MonoExceptionClause *clause = &header->clauses [i];
6985
6986                 info->flags = clause->flags;
6987                 info->try_offset = clause->try_offset;
6988                 info->try_length = clause->try_len;
6989                 info->handler_offset = clause->handler_offset;
6990                 info->handler_length = clause->handler_len;
6991                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6992                         info->filter_offset = clause->data.filter_offset;
6993                 else if (clause->data.catch_class)
6994                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6995
6996                 mono_array_setref (ret->clauses, i, info);
6997         }
6998
6999         mono_metadata_free_mh (header);
7000         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7001         return ret;
7002 }
7003
7004 /**
7005  * mono_get_dbnull_object:
7006  * @domain: Domain where the object lives
7007  *
7008  * Returns the System.DBNull.Value singleton object
7009  *
7010  * Used as the value for ParameterInfo.DefaultValue 
7011  */
7012 MonoObject *
7013 mono_get_dbnull_object (MonoDomain *domain)
7014 {
7015         MonoObject *obj;
7016         static MonoClassField *dbnull_value_field = NULL;
7017         
7018         if (!dbnull_value_field) {
7019                 MonoClass *dbnull_klass;
7020                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7021                 mono_class_init (dbnull_klass);
7022                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7023                 g_assert (dbnull_value_field);
7024         }
7025         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7026         g_assert (obj);
7027         return obj;
7028 }
7029
7030 static void
7031 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7032 {
7033         guint32 param_index, i, lastp, crow = 0;
7034         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7035         gint32 idx;
7036
7037         MonoClass *klass = method->klass;
7038         MonoImage *image = klass->image;
7039         MonoMethodSignature *methodsig = mono_method_signature (method);
7040
7041         MonoTableInfo *constt;
7042         MonoTableInfo *methodt;
7043         MonoTableInfo *paramt;
7044
7045         if (!methodsig->param_count)
7046                 return;
7047
7048         mono_class_init (klass);
7049
7050         if (klass->image->dynamic) {
7051                 MonoReflectionMethodAux *aux;
7052                 if (method->is_inflated)
7053                         method = ((MonoMethodInflated*)method)->declaring;
7054                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7055                 if (aux && aux->param_defaults) {
7056                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7057                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7058                 }
7059                 return;
7060         }
7061
7062         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7063         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7064         constt = &image->tables [MONO_TABLE_CONSTANT];
7065
7066         idx = mono_method_get_index (method) - 1;
7067         g_assert (idx != -1);
7068
7069         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7070         if (idx + 1 < methodt->rows)
7071                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7072         else
7073                 lastp = paramt->rows + 1;
7074
7075         for (i = param_index; i < lastp; ++i) {
7076                 guint32 paramseq;
7077
7078                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7079                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7080
7081                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7082                         continue;
7083
7084                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7085                 if (!crow) {
7086                         continue;
7087                 }
7088         
7089                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7090                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7091                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7092         }
7093
7094         return;
7095 }
7096
7097 MonoObject *
7098 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7099 {
7100         void *retval;
7101         MonoClass *klass;
7102         MonoObject *object;
7103         MonoType *basetype = type;
7104
7105         if (!blob)
7106                 return NULL;
7107         
7108         klass = mono_class_from_mono_type (type);
7109         if (klass->valuetype) {
7110                 object = mono_object_new (domain, klass);
7111                 retval = ((gchar *) object + sizeof (MonoObject));
7112                 if (klass->enumtype)
7113                         basetype = mono_class_enum_basetype (klass);
7114         } else {
7115                 retval = &object;
7116         }
7117                         
7118         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7119                 return object;
7120         else
7121                 return NULL;
7122 }
7123
7124 static int
7125 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7126         int found_sep;
7127         char *s;
7128
7129         memset (assembly, 0, sizeof (MonoAssemblyName));
7130         assembly->name = p;
7131         assembly->culture = "";
7132         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7133
7134         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7135                 p++;
7136         found_sep = 0;
7137         while (g_ascii_isspace (*p) || *p == ',') {
7138                 *p++ = 0;
7139                 found_sep = 1;
7140                 continue;
7141         }
7142         /* failed */
7143         if (!found_sep)
7144                 return 1;
7145         while (*p) {
7146                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7147                         p += 8;
7148                         assembly->major = strtoul (p, &s, 10);
7149                         if (s == p || *s != '.')
7150                                 return 1;
7151                         p = ++s;
7152                         assembly->minor = strtoul (p, &s, 10);
7153                         if (s == p || *s != '.')
7154                                 return 1;
7155                         p = ++s;
7156                         assembly->build = strtoul (p, &s, 10);
7157                         if (s == p || *s != '.')
7158                                 return 1;
7159                         p = ++s;
7160                         assembly->revision = strtoul (p, &s, 10);
7161                         if (s == p)
7162                                 return 1;
7163                         p = s;
7164                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7165                         p += 8;
7166                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7167                                 assembly->culture = "";
7168                                 p += 7;
7169                         } else {
7170                                 assembly->culture = p;
7171                                 while (*p && *p != ',') {
7172                                         p++;
7173                                 }
7174                         }
7175                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7176                         p += 15;
7177                         if (strncmp (p, "null", 4) == 0) {
7178                                 p += 4;
7179                         } else {
7180                                 int len;
7181                                 gchar *start = p;
7182                                 while (*p && *p != ',') {
7183                                         p++;
7184                                 }
7185                                 len = (p - start + 1);
7186                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7187                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7188                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7189                         }
7190                 } else {
7191                         while (*p && *p != ',')
7192                                 p++;
7193                 }
7194                 found_sep = 0;
7195                 while (g_ascii_isspace (*p) || *p == ',') {
7196                         *p++ = 0;
7197                         found_sep = 1;
7198                         continue;
7199                 }
7200                 /* failed */
7201                 if (!found_sep)
7202                         return 1;
7203         }
7204
7205         return 0;
7206 }
7207
7208 /*
7209  * mono_reflection_parse_type:
7210  * @name: type name
7211  *
7212  * Parse a type name as accepted by the GetType () method and output the info
7213  * extracted in the info structure.
7214  * the name param will be mangled, so, make a copy before passing it to this function.
7215  * The fields in info will be valid until the memory pointed to by name is valid.
7216  *
7217  * See also mono_type_get_name () below.
7218  *
7219  * Returns: 0 on parse error.
7220  */
7221 static int
7222 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7223                              MonoTypeNameParse *info)
7224 {
7225         char *start, *p, *w, *temp, *last_point, *startn;
7226         int in_modifiers = 0;
7227         int isbyref = 0, rank, arity = 0, i;
7228
7229         start = p = w = name;
7230
7231         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7232         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7233         info->name = info->name_space = NULL;
7234         info->nested = NULL;
7235         info->modifiers = NULL;
7236         info->type_arguments = NULL;
7237
7238         /* last_point separates the namespace from the name */
7239         last_point = NULL;
7240         /* Skips spaces */
7241         while (*p == ' ') p++, start++, w++, name++;
7242
7243         while (*p) {
7244                 switch (*p) {
7245                 case '+':
7246                         *p = 0; /* NULL terminate the name */
7247                         startn = p + 1;
7248                         info->nested = g_list_append (info->nested, startn);
7249                         /* we have parsed the nesting namespace + name */
7250                         if (info->name)
7251                                 break;
7252                         if (last_point) {
7253                                 info->name_space = start;
7254                                 *last_point = 0;
7255                                 info->name = last_point + 1;
7256                         } else {
7257                                 info->name_space = (char *)"";
7258                                 info->name = start;
7259                         }
7260                         break;
7261                 case '.':
7262                         last_point = p;
7263                         break;
7264                 case '\\':
7265                         ++p;
7266                         break;
7267                 case '&':
7268                 case '*':
7269                 case '[':
7270                 case ',':
7271                 case ']':
7272                         in_modifiers = 1;
7273                         break;
7274                 case '`':
7275                         ++p;
7276                         i = strtol (p, &temp, 10);
7277                         arity += i;
7278                         if (p == temp)
7279                                 return 0;
7280                         p = temp-1;
7281                         break;
7282                 default:
7283                         break;
7284                 }
7285                 if (in_modifiers)
7286                         break;
7287                 // *w++ = *p++;
7288                 p++;
7289         }
7290         
7291         if (!info->name) {
7292                 if (last_point) {
7293                         info->name_space = start;
7294                         *last_point = 0;
7295                         info->name = last_point + 1;
7296                 } else {
7297                         info->name_space = (char *)"";
7298                         info->name = start;
7299                 }
7300         }
7301         while (*p) {
7302                 switch (*p) {
7303                 case '&':
7304                         if (isbyref) /* only one level allowed by the spec */
7305                                 return 0;
7306                         isbyref = 1;
7307                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7308                         *p++ = 0;
7309                         break;
7310                 case '*':
7311                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7312                         *p++ = 0;
7313                         break;
7314                 case '[':
7315                         if (arity != 0) {
7316                                 *p++ = 0;
7317                                 info->type_arguments = g_ptr_array_new ();
7318                                 for (i = 0; i < arity; i++) {
7319                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7320                                         gboolean fqname = FALSE;
7321
7322                                         g_ptr_array_add (info->type_arguments, subinfo);
7323
7324                                         if (*p == '[') {
7325                                                 p++;
7326                                                 fqname = TRUE;
7327                                         }
7328
7329                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7330                                                 return 0;
7331
7332                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7333                                         if (fqname && (*p != ']')) {
7334                                                 char *aname;
7335
7336                                                 if (*p != ',')
7337                                                         return 0;
7338                                                 *p++ = 0;
7339
7340                                                 aname = p;
7341                                                 while (*p && (*p != ']'))
7342                                                         p++;
7343
7344                                                 if (*p != ']')
7345                                                         return 0;
7346
7347                                                 *p++ = 0;
7348                                                 while (*aname) {
7349                                                         if (g_ascii_isspace (*aname)) {
7350                                                                 ++aname;
7351                                                                 continue;
7352                                                         }
7353                                                         break;
7354                                                 }
7355                                                 if (!*aname ||
7356                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7357                                                         return 0;
7358                                         } else if (fqname && (*p == ']')) {
7359                                                 *p++ = 0;
7360                                         }
7361
7362                                         if (i + 1 < arity) {
7363                                                 if (*p != ',')
7364                                                         return 0;
7365                                         } else {
7366                                                 if (*p != ']')
7367                                                         return 0;
7368                                         }
7369                                         *p++ = 0;
7370                                 }
7371
7372                                 arity = 0;
7373                                 break;
7374                         }
7375                         rank = 1;
7376                         *p++ = 0;
7377                         while (*p) {
7378                                 if (*p == ']')
7379                                         break;
7380                                 if (*p == ',')
7381                                         rank++;
7382                                 else if (*p == '*') /* '*' means unknown lower bound */
7383                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7384                                 else
7385                                         return 0;
7386                                 ++p;
7387                         }
7388                         if (*p++ != ']')
7389                                 return 0;
7390                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7391                         break;
7392                 case ']':
7393                         if (is_recursed)
7394                                 goto end;
7395                         return 0;
7396                 case ',':
7397                         if (is_recursed)
7398                                 goto end;
7399                         *p++ = 0;
7400                         while (*p) {
7401                                 if (g_ascii_isspace (*p)) {
7402                                         ++p;
7403                                         continue;
7404                                 }
7405                                 break;
7406                         }
7407                         if (!*p)
7408                                 return 0; /* missing assembly name */
7409                         if (!assembly_name_to_aname (&info->assembly, p))
7410                                 return 0;
7411                         break;
7412                 default:
7413                         return 0;
7414                 }
7415                 if (info->assembly.name)
7416                         break;
7417         }
7418         // *w = 0; /* terminate class name */
7419  end:
7420         if (!info->name || !*info->name)
7421                 return 0;
7422         if (endptr)
7423                 *endptr = p;
7424         /* add other consistency checks */
7425         return 1;
7426 }
7427
7428 int
7429 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7430 {
7431         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7432 }
7433
7434 static MonoType*
7435 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7436 {
7437         gboolean type_resolve = FALSE;
7438         MonoType *type;
7439         MonoImage *rootimage = image;
7440
7441         if (info->assembly.name) {
7442                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7443                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7444                         /* 
7445                          * This could happen in the AOT compiler case when the search hook is not
7446                          * installed.
7447                          */
7448                         assembly = image->assembly;
7449                 if (!assembly) {
7450                         /* then we must load the assembly ourselve - see #60439 */
7451                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7452                         if (!assembly)
7453                                 return NULL;
7454                 }
7455                 image = assembly->image;
7456         } else if (!image) {
7457                 image = mono_defaults.corlib;
7458         }
7459
7460         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7461         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7462                 image = mono_defaults.corlib;
7463                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464         }
7465
7466         return type;
7467 }
7468
7469 static MonoType*
7470 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7471 {
7472         MonoClass *klass;
7473         GList *mod;
7474         int modval;
7475         gboolean bounded = FALSE;
7476         
7477         if (!image)
7478                 image = mono_defaults.corlib;
7479
7480         if (ignorecase)
7481                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7482         else
7483                 klass = mono_class_from_name (image, info->name_space, info->name);
7484         if (!klass)
7485                 return NULL;
7486         for (mod = info->nested; mod; mod = mod->next) {
7487                 gpointer iter = NULL;
7488                 MonoClass *parent;
7489
7490                 parent = klass;
7491                 mono_class_init (parent);
7492
7493                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7494                         if (ignorecase) {
7495                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7496                                         break;
7497                         } else {
7498                                 if (strcmp (klass->name, mod->data) == 0)
7499                                         break;
7500                         }
7501                 }
7502                 if (!klass)
7503                         break;
7504         }
7505         if (!klass)
7506                 return NULL;
7507         mono_class_init (klass);
7508
7509         if (info->type_arguments) {
7510                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7511                 MonoReflectionType *the_type;
7512                 MonoType *instance;
7513                 int i;
7514
7515                 for (i = 0; i < info->type_arguments->len; i++) {
7516                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7517
7518                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7519                         if (!type_args [i]) {
7520                                 g_free (type_args);
7521                                 return NULL;
7522                         }
7523                 }
7524
7525                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7526
7527                 instance = mono_reflection_bind_generic_parameters (
7528                         the_type, info->type_arguments->len, type_args);
7529
7530                 g_free (type_args);
7531                 if (!instance)
7532                         return NULL;
7533
7534                 klass = mono_class_from_mono_type (instance);
7535         }
7536
7537         for (mod = info->modifiers; mod; mod = mod->next) {
7538                 modval = GPOINTER_TO_UINT (mod->data);
7539                 if (!modval) { /* byref: must be last modifier */
7540                         return &klass->this_arg;
7541                 } else if (modval == -1) {
7542                         klass = mono_ptr_class_get (&klass->byval_arg);
7543                 } else if (modval == -2) {
7544                         bounded = TRUE;
7545                 } else { /* array rank */
7546                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7547                 }
7548                 mono_class_init (klass);
7549         }
7550
7551         return &klass->byval_arg;
7552 }
7553
7554 /*
7555  * mono_reflection_get_type:
7556  * @image: a metadata context
7557  * @info: type description structure
7558  * @ignorecase: flag for case-insensitive string compares
7559  * @type_resolve: whenever type resolve was already tried
7560  *
7561  * Build a MonoType from the type description in @info.
7562  * 
7563  */
7564
7565 MonoType*
7566 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7567         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7568 }
7569
7570 static MonoType*
7571 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7572 {
7573         MonoReflectionAssemblyBuilder *abuilder;
7574         MonoType *type;
7575         int i;
7576
7577         g_assert (assembly->dynamic);
7578         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7579
7580         /* Enumerate all modules */
7581
7582         type = NULL;
7583         if (abuilder->modules) {
7584                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7585                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7586                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7587                         if (type)
7588                                 break;
7589                 }
7590         }
7591
7592         if (!type && abuilder->loaded_modules) {
7593                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7594                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7595                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7596                         if (type)
7597                                 break;
7598                 }
7599         }
7600
7601         return type;
7602 }
7603         
7604 MonoType*
7605 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7606 {
7607         MonoType *type;
7608         MonoReflectionAssembly *assembly;
7609         GString *fullName;
7610         GList *mod;
7611
7612         if (image && image->dynamic)
7613                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7614         else
7615                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7616         if (type)
7617                 return type;
7618         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7619                 return NULL;
7620
7621         if (type_resolve) {
7622                 if (*type_resolve) 
7623                         return NULL;
7624                 else
7625                         *type_resolve = TRUE;
7626         }
7627         
7628         /* Reconstruct the type name */
7629         fullName = g_string_new ("");
7630         if (info->name_space && (info->name_space [0] != '\0'))
7631                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7632         else
7633                 g_string_printf (fullName, "%s", info->name);
7634         for (mod = info->nested; mod; mod = mod->next)
7635                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7636
7637         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7638         if (assembly) {
7639                 if (assembly->assembly->dynamic)
7640                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7641                 else
7642                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7643                                                                                                           info, ignorecase);
7644         }
7645         g_string_free (fullName, TRUE);
7646         return type;
7647 }
7648
7649 void
7650 mono_reflection_free_type_info (MonoTypeNameParse *info)
7651 {
7652         g_list_free (info->modifiers);
7653         g_list_free (info->nested);
7654
7655         if (info->type_arguments) {
7656                 int i;
7657
7658                 for (i = 0; i < info->type_arguments->len; i++) {
7659                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7660
7661                         mono_reflection_free_type_info (subinfo);
7662                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7663                         g_free (subinfo);
7664                 }
7665
7666                 g_ptr_array_free (info->type_arguments, TRUE);
7667         }
7668 }
7669
7670 /*
7671  * mono_reflection_type_from_name:
7672  * @name: type name.
7673  * @image: a metadata context (can be NULL).
7674  *
7675  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7676  * it defaults to get the type from @image or, if @image is NULL or loading
7677  * from it fails, uses corlib.
7678  * 
7679  */
7680 MonoType*
7681 mono_reflection_type_from_name (char *name, MonoImage *image)
7682 {
7683         MonoType *type = NULL;
7684         MonoTypeNameParse info;
7685         char *tmp;
7686
7687         /* Make a copy since parse_type modifies its argument */
7688         tmp = g_strdup (name);
7689         
7690         /*g_print ("requested type %s\n", str);*/
7691         if (mono_reflection_parse_type (tmp, &info)) {
7692                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7693         }
7694
7695         g_free (tmp);
7696         mono_reflection_free_type_info (&info);
7697         return type;
7698 }
7699
7700 /*
7701  * mono_reflection_get_token:
7702  *
7703  *   Return the metadata token of OBJ which should be an object
7704  * representing a metadata element.
7705  */
7706 guint32
7707 mono_reflection_get_token (MonoObject *obj)
7708 {
7709         MonoClass *klass;
7710         guint32 token = 0;
7711
7712         klass = obj->vtable->klass;
7713
7714         if (strcmp (klass->name, "MethodBuilder") == 0) {
7715                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7716
7717                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7718         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7719                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7720
7721                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7722         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7723                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7724
7725                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7726                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7727         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7728                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7729                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7730         } else if (strcmp (klass->name, "MonoType") == 0) {
7731                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7732                 MonoClass *mc = mono_class_from_mono_type (type);
7733                 if (!mono_class_init (mc))
7734                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7735
7736                 token = mc->type_token;
7737         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7738                    strcmp (klass->name, "MonoMethod") == 0 ||
7739                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7740                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7741                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7742                 if (m->method->is_inflated) {
7743                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7744                         return inflated->declaring->token;
7745                 } else {
7746                         token = m->method->token;
7747                 }
7748         } else if (strcmp (klass->name, "MonoField") == 0) {
7749                 MonoReflectionField *f = (MonoReflectionField*)obj;
7750
7751                 if (is_field_on_inst (f->field)) {
7752                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7753                         int field_index = f->field - dgclass->fields;
7754                         MonoObject *obj;
7755
7756                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7757                         obj = dgclass->field_objects [field_index];
7758                         return mono_reflection_get_token (obj);
7759                 }
7760                 token = mono_class_get_field_token (f->field);
7761         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7762                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7763
7764                 token = mono_class_get_property_token (p->property);
7765         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7766                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7767
7768                 token = mono_class_get_event_token (p->event);
7769         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7770                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7771                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7772                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7773
7774                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7775         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7776                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7777
7778                 token = m->token;
7779         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7780                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7781         } else {
7782                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7783                 MonoException *ex = mono_get_exception_not_implemented (msg);
7784                 g_free (msg);
7785                 mono_raise_exception (ex);
7786         }
7787
7788         return token;
7789 }
7790
7791 static void*
7792 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7793 {
7794         int slen, type = t->type;
7795         MonoClass *tklass = t->data.klass;
7796
7797 handle_enum:
7798         switch (type) {
7799         case MONO_TYPE_U1:
7800         case MONO_TYPE_I1:
7801         case MONO_TYPE_BOOLEAN: {
7802                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7803                 *bval = *p;
7804                 *end = p + 1;
7805                 return bval;
7806         }
7807         case MONO_TYPE_CHAR:
7808         case MONO_TYPE_U2:
7809         case MONO_TYPE_I2: {
7810                 guint16 *val = g_malloc (sizeof (guint16));
7811                 *val = read16 (p);
7812                 *end = p + 2;
7813                 return val;
7814         }
7815 #if SIZEOF_VOID_P == 4
7816         case MONO_TYPE_U:
7817         case MONO_TYPE_I:
7818 #endif
7819         case MONO_TYPE_R4:
7820         case MONO_TYPE_U4:
7821         case MONO_TYPE_I4: {
7822                 guint32 *val = g_malloc (sizeof (guint32));
7823                 *val = read32 (p);
7824                 *end = p + 4;
7825                 return val;
7826         }
7827 #if SIZEOF_VOID_P == 8
7828         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7829         case MONO_TYPE_I:
7830 #endif
7831         case MONO_TYPE_U8:
7832         case MONO_TYPE_I8: {
7833                 guint64 *val = g_malloc (sizeof (guint64));
7834                 *val = read64 (p);
7835                 *end = p + 8;
7836                 return val;
7837         }
7838         case MONO_TYPE_R8: {
7839                 double *val = g_malloc (sizeof (double));
7840                 readr8 (p, val);
7841                 *end = p + 8;
7842                 return val;
7843         }
7844         case MONO_TYPE_VALUETYPE:
7845                 if (t->data.klass->enumtype) {
7846                         type = mono_class_enum_basetype (t->data.klass)->type;
7847                         goto handle_enum;
7848                 } else {
7849                         MonoClass *k =  t->data.klass;
7850                         
7851                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7852                                 guint64 *val = g_malloc (sizeof (guint64));
7853                                 *val = read64 (p);
7854                                 *end = p + 8;
7855                                 return val;
7856                         }
7857                 }
7858                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7859                 break;
7860                 
7861         case MONO_TYPE_STRING:
7862                 if (*p == (char)0xFF) {
7863                         *end = p + 1;
7864                         return NULL;
7865                 }
7866                 slen = mono_metadata_decode_value (p, &p);
7867                 *end = p + slen;
7868                 return mono_string_new_len (mono_domain_get (), p, slen);
7869         case MONO_TYPE_CLASS: {
7870                 char *n;
7871                 MonoType *t;
7872                 if (*p == (char)0xFF) {
7873                         *end = p + 1;
7874                         return NULL;
7875                 }
7876 handle_type:
7877                 slen = mono_metadata_decode_value (p, &p);
7878                 n = g_memdup (p, slen + 1);
7879                 n [slen] = 0;
7880                 t = mono_reflection_type_from_name (n, image);
7881                 if (!t)
7882                         g_warning ("Cannot load type '%s'", n);
7883                 g_free (n);
7884                 *end = p + slen;
7885                 if (t)
7886                         return mono_type_get_object (mono_domain_get (), t);
7887                 else
7888                         return NULL;
7889         }
7890         case MONO_TYPE_OBJECT: {
7891                 char subt = *p++;
7892                 MonoObject *obj;
7893                 MonoClass *subc = NULL;
7894                 void *val;
7895
7896                 if (subt == 0x50) {
7897                         goto handle_type;
7898                 } else if (subt == 0x0E) {
7899                         type = MONO_TYPE_STRING;
7900                         goto handle_enum;
7901                 } else if (subt == 0x1D) {
7902                         MonoType simple_type = {{0}};
7903                         int etype = *p;
7904                         p ++;
7905
7906                         if (etype == 0x51)
7907                                 /* See Partition II, Appendix B3 */
7908                                 etype = MONO_TYPE_OBJECT;
7909                         type = MONO_TYPE_SZARRAY;
7910                         simple_type.type = etype;
7911                         tklass = mono_class_from_mono_type (&simple_type);
7912                         goto handle_enum;
7913                 } else if (subt == 0x55) {
7914                         char *n;
7915                         MonoType *t;
7916                         slen = mono_metadata_decode_value (p, &p);
7917                         n = g_memdup (p, slen + 1);
7918                         n [slen] = 0;
7919                         t = mono_reflection_type_from_name (n, image);
7920                         if (!t)
7921                                 g_error ("Cannot load type '%s'", n);
7922                         g_free (n);
7923                         p += slen;
7924                         subc = mono_class_from_mono_type (t);
7925                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7926                         MonoType simple_type = {{0}};
7927                         simple_type.type = subt;
7928                         subc = mono_class_from_mono_type (&simple_type);
7929                 } else {
7930                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7931                 }
7932                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7933                 obj = mono_object_new (mono_domain_get (), subc);
7934                 g_assert (!subc->has_references);
7935                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7936                 g_free (val);
7937                 return obj;
7938         }
7939         case MONO_TYPE_SZARRAY: {
7940                 MonoArray *arr;
7941                 guint32 i, alen, basetype;
7942                 alen = read32 (p);
7943                 p += 4;
7944                 if (alen == 0xffffffff) {
7945                         *end = p;
7946                         return NULL;
7947                 }
7948                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7949                 basetype = tklass->byval_arg.type;
7950                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7951                         basetype = mono_class_enum_basetype (tklass)->type;
7952                 switch (basetype)
7953                 {
7954                         case MONO_TYPE_U1:
7955                         case MONO_TYPE_I1:
7956                         case MONO_TYPE_BOOLEAN:
7957                                 for (i = 0; i < alen; i++) {
7958                                         MonoBoolean val = *p++;
7959                                         mono_array_set (arr, MonoBoolean, i, val);
7960                                 }
7961                                 break;
7962                         case MONO_TYPE_CHAR:
7963                         case MONO_TYPE_U2:
7964                         case MONO_TYPE_I2:
7965                                 for (i = 0; i < alen; i++) {
7966                                         guint16 val = read16 (p);
7967                                         mono_array_set (arr, guint16, i, val);
7968                                         p += 2;
7969                                 }
7970                                 break;
7971                         case MONO_TYPE_R4:
7972                         case MONO_TYPE_U4:
7973                         case MONO_TYPE_I4:
7974                                 for (i = 0; i < alen; i++) {
7975                                         guint32 val = read32 (p);
7976                                         mono_array_set (arr, guint32, i, val);
7977                                         p += 4;
7978                                 }
7979                                 break;
7980                         case MONO_TYPE_R8:
7981                                 for (i = 0; i < alen; i++) {
7982                                         double val;
7983                                         readr8 (p, &val);
7984                                         mono_array_set (arr, double, i, val);
7985                                         p += 8;
7986                                 }
7987                                 break;
7988                         case MONO_TYPE_U8:
7989                         case MONO_TYPE_I8:
7990                                 for (i = 0; i < alen; i++) {
7991                                         guint64 val = read64 (p);
7992                                         mono_array_set (arr, guint64, i, val);
7993                                         p += 8;
7994                                 }
7995                                 break;
7996                         case MONO_TYPE_CLASS:
7997                         case MONO_TYPE_OBJECT:
7998                         case MONO_TYPE_STRING:
7999                                 for (i = 0; i < alen; i++) {
8000                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8001                                         mono_array_setref (arr, i, item);
8002                                 }
8003                                 break;
8004                         default:
8005                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8006                 }
8007                 *end=p;
8008                 return arr;
8009         }
8010         default:
8011                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8012         }
8013         return NULL;
8014 }
8015
8016 static MonoObject*
8017 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8018 {
8019         static MonoClass *klass;
8020         static MonoMethod *ctor;
8021         MonoObject *retval;
8022         void *params [2], *unboxed;
8023
8024         if (!klass)
8025                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8026         if (!ctor)
8027                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8028         
8029         params [0] = mono_type_get_object (mono_domain_get (), t);
8030         params [1] = val;
8031         retval = mono_object_new (mono_domain_get (), klass);
8032         unboxed = mono_object_unbox (retval);
8033         mono_runtime_invoke (ctor, unboxed, params, NULL);
8034
8035         return retval;
8036 }
8037
8038 static MonoObject*
8039 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8040 {
8041         static MonoClass *klass;
8042         static MonoMethod *ctor;
8043         MonoObject *retval;
8044         void *unboxed, *params [2];
8045
8046         if (!klass)
8047                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8048         if (!ctor)
8049                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8050
8051         params [0] = minfo;
8052         params [1] = typedarg;
8053         retval = mono_object_new (mono_domain_get (), klass);
8054         unboxed = mono_object_unbox (retval);
8055         mono_runtime_invoke (ctor, unboxed, params, NULL);
8056
8057         return retval;
8058 }
8059
8060 static gboolean
8061 type_is_reference (MonoType *type)
8062 {
8063         switch (type->type) {
8064         case MONO_TYPE_BOOLEAN:
8065         case MONO_TYPE_CHAR:
8066         case MONO_TYPE_U:
8067         case MONO_TYPE_I:
8068         case MONO_TYPE_U1:
8069         case MONO_TYPE_I1:
8070         case MONO_TYPE_U2:
8071         case MONO_TYPE_I2:
8072         case MONO_TYPE_U4:
8073         case MONO_TYPE_I4:
8074         case MONO_TYPE_U8:
8075         case MONO_TYPE_I8:
8076         case MONO_TYPE_R8:
8077         case MONO_TYPE_R4:
8078         case MONO_TYPE_VALUETYPE:
8079                 return FALSE;
8080         default:
8081                 return TRUE;
8082         }
8083 }
8084
8085 static void
8086 free_param_data (MonoMethodSignature *sig, void **params) {
8087         int i;
8088         for (i = 0; i < sig->param_count; ++i) {
8089                 if (!type_is_reference (sig->params [i]))
8090                         g_free (params [i]);
8091         }
8092 }
8093
8094 /*
8095  * Find the field index in the metadata FieldDef table.
8096  */
8097 static guint32
8098 find_field_index (MonoClass *klass, MonoClassField *field) {
8099         int i;
8100
8101         for (i = 0; i < klass->field.count; ++i) {
8102                 if (field == &klass->fields [i])
8103                         return klass->field.first + 1 + i;
8104         }
8105         return 0;
8106 }
8107
8108 /*
8109  * Find the property index in the metadata Property table.
8110  */
8111 static guint32
8112 find_property_index (MonoClass *klass, MonoProperty *property) {
8113         int i;
8114
8115         for (i = 0; i < klass->ext->property.count; ++i) {
8116                 if (property == &klass->ext->properties [i])
8117                         return klass->ext->property.first + 1 + i;
8118         }
8119         return 0;
8120 }
8121
8122 /*
8123  * Find the event index in the metadata Event table.
8124  */
8125 static guint32
8126 find_event_index (MonoClass *klass, MonoEvent *event) {
8127         int i;
8128
8129         for (i = 0; i < klass->ext->event.count; ++i) {
8130                 if (event == &klass->ext->events [i])
8131                         return klass->ext->event.first + 1 + i;
8132         }
8133         return 0;
8134 }
8135
8136 static MonoObject*
8137 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8138 {
8139         const char *p = (const char*)data;
8140         const char *named;
8141         guint32 i, j, num_named;
8142         MonoObject *attr;
8143         void *params_buf [32];
8144         void **params;
8145         MonoMethodSignature *sig;
8146
8147         mono_class_init (method->klass);
8148
8149         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8150                 return NULL;
8151
8152         if (len == 0) {
8153                 attr = mono_object_new (mono_domain_get (), method->klass);
8154                 mono_runtime_invoke (method, attr, NULL, NULL);
8155                 return attr;
8156         }
8157
8158         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8159                 return NULL;
8160
8161         /*g_print ("got attr %s\n", method->klass->name);*/
8162
8163         sig = mono_method_signature (method);
8164         if (sig->param_count < 32)
8165                 params = params_buf;
8166         else
8167                 /* Allocate using GC so it gets GC tracking */
8168                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8169
8170         /* skip prolog */
8171         p += 2;
8172         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8173                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8174         }
8175
8176         named = p;
8177         attr = mono_object_new (mono_domain_get (), method->klass);
8178         mono_runtime_invoke (method, attr, params, NULL);
8179         free_param_data (method->signature, params);
8180         num_named = read16 (named);
8181         named += 2;
8182         for (j = 0; j < num_named; j++) {
8183                 gint name_len;
8184                 char *name, named_type, data_type;
8185                 named_type = *named++;
8186                 data_type = *named++; /* type of data */
8187                 if (data_type == MONO_TYPE_SZARRAY)
8188                         data_type = *named++;
8189                 if (data_type == MONO_TYPE_ENUM) {
8190                         gint type_len;
8191                         char *type_name;
8192                         type_len = mono_metadata_decode_blob_size (named, &named);
8193                         type_name = g_malloc (type_len + 1);
8194                         memcpy (type_name, named, type_len);
8195                         type_name [type_len] = 0;
8196                         named += type_len;
8197                         /* FIXME: lookup the type and check type consistency */
8198                         g_free (type_name);
8199                 }
8200                 name_len = mono_metadata_decode_blob_size (named, &named);
8201                 name = g_malloc (name_len + 1);
8202                 memcpy (name, named, name_len);
8203                 name [name_len] = 0;
8204                 named += name_len;
8205                 if (named_type == 0x53) {
8206                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8207                         void *val = load_cattr_value (image, field->type, named, &named);
8208                         mono_field_set_value (attr, field, val);
8209                         if (!type_is_reference (field->type))
8210                                 g_free (val);
8211                 } else if (named_type == 0x54) {
8212                         MonoProperty *prop;
8213                         void *pparams [1];
8214                         MonoType *prop_type;
8215
8216                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8217                         /* can we have more that 1 arg in a custom attr named property? */
8218                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8219                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8220                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8221                         mono_property_set_value (prop, attr, pparams, NULL);
8222                         if (!type_is_reference (prop_type))
8223                                 g_free (pparams [0]);
8224                 }
8225                 g_free (name);
8226         }
8227
8228         if (params != params_buf)
8229                 mono_gc_free_fixed (params);
8230
8231         return attr;
8232 }
8233         
8234 /*
8235  * mono_reflection_create_custom_attr_data_args:
8236  *
8237  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8238  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8239  * NAMED_ARG_INFO will contain information about the named arguments.
8240  */
8241 void
8242 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)
8243 {
8244         MonoArray *typedargs, *namedargs;
8245         MonoClass *attrklass;
8246         MonoDomain *domain;
8247         const char *p = (const char*)data;
8248         const char *named;
8249         guint32 i, j, num_named;
8250         CattrNamedArg *arginfo = NULL;
8251
8252         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8253                 return;
8254
8255         mono_class_init (method->klass);
8256
8257         *typed_args = NULL;
8258         *named_args = NULL;
8259         *named_arg_info = NULL;
8260         
8261         domain = mono_domain_get ();
8262
8263         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8264                 return;
8265
8266         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8267         
8268         /* skip prolog */
8269         p += 2;
8270         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8271                 MonoObject *obj;
8272                 void *val;
8273
8274                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8275                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8276                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8277                 mono_array_setref (typedargs, i, obj);
8278
8279                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8280                         g_free (val);
8281         }
8282
8283         named = p;
8284         num_named = read16 (named);
8285         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8286         named += 2;
8287         attrklass = method->klass;
8288
8289         arginfo = g_new0 (CattrNamedArg, num_named);
8290         *named_arg_info = arginfo;
8291
8292         for (j = 0; j < num_named; j++) {
8293                 gint name_len;
8294                 char *name, named_type, data_type;
8295                 named_type = *named++;
8296                 data_type = *named++; /* type of data */
8297                 if (data_type == MONO_TYPE_SZARRAY)
8298                         data_type = *named++;
8299                 if (data_type == MONO_TYPE_ENUM) {
8300                         gint type_len;
8301                         char *type_name;
8302                         type_len = mono_metadata_decode_blob_size (named, &named);
8303                         type_name = g_malloc (type_len + 1);
8304                         memcpy (type_name, named, type_len);
8305                         type_name [type_len] = 0;
8306                         named += type_len;
8307                         /* FIXME: lookup the type and check type consistency */
8308                         g_free (type_name);
8309                 }
8310                 name_len = mono_metadata_decode_blob_size (named, &named);
8311                 name = g_malloc (name_len + 1);
8312                 memcpy (name, named, name_len);
8313                 name [name_len] = 0;
8314                 named += name_len;
8315                 if (named_type == 0x53) {
8316                         MonoObject *obj;
8317                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8318                         void *val;
8319
8320                         arginfo [j].type = field->type;
8321                         arginfo [j].field = field;
8322
8323                         val = load_cattr_value (image, field->type, named, &named);
8324                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8325                         mono_array_setref (namedargs, j, obj);
8326                         if (!type_is_reference (field->type))
8327                                 g_free (val);
8328                 } else if (named_type == 0x54) {
8329                         MonoObject *obj;
8330                         MonoType *prop_type;
8331                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8332                         void *val;
8333
8334                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8335                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8336
8337                         arginfo [j].type = prop_type;
8338                         arginfo [j].prop = prop;
8339
8340                         val = load_cattr_value (image, prop_type, named, &named);
8341                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8342                         mono_array_setref (namedargs, j, obj);
8343                         if (!type_is_reference (prop_type))
8344                                 g_free (val);
8345                 }
8346                 g_free (name);
8347         }
8348
8349         *typed_args = typedargs;
8350         *named_args = namedargs;
8351 }
8352
8353 static MonoObject*
8354 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8355 {
8356         MonoArray *typedargs, *namedargs;
8357         static MonoMethod *ctor;
8358         MonoDomain *domain;
8359         MonoObject *attr;
8360         void *params [3];
8361         CattrNamedArg *arginfo;
8362         int i;
8363
8364         mono_class_init (method->klass);
8365
8366         if (!ctor)
8367                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8368
8369         domain = mono_domain_get ();
8370         if (len == 0) {
8371                 /* This is for Attributes with no parameters */
8372                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8373                 params [0] = mono_method_get_object (domain, method, NULL);
8374                 params [1] = params [2] = NULL;
8375                 mono_runtime_invoke (method, attr, params, NULL);
8376                 return attr;
8377         }
8378
8379         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8380         if (!typedargs || !namedargs)
8381                 return NULL;
8382
8383         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8384                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8385                 MonoObject *typedarg;
8386
8387                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8388                 mono_array_setref (typedargs, i, typedarg);
8389         }
8390
8391         for (i = 0; i < mono_array_length (namedargs); ++i) {
8392                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8393                 MonoObject *typedarg, *namedarg, *minfo;
8394
8395                 if (arginfo [i].prop)
8396                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8397                 else
8398                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8399
8400                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8401                 namedarg = create_cattr_named_arg (minfo, typedarg);
8402
8403                 mono_array_setref (namedargs, i, namedarg);
8404         }
8405
8406         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8407         params [0] = mono_method_get_object (domain, method, NULL);
8408         params [1] = typedargs;
8409         params [2] = namedargs;
8410         mono_runtime_invoke (ctor, attr, params, NULL);
8411         return attr;
8412 }
8413
8414 MonoArray*
8415 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8416 {
8417         MonoArray *result;
8418         MonoObject *attr;
8419         int i;
8420
8421         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8422         for (i = 0; i < cinfo->num_attrs; ++i) {
8423                 if (!cinfo->attrs [i].ctor)
8424                         /* The cattr type is not finished yet */
8425                         /* We should include the type name but cinfo doesn't contain it */
8426                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8427                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8428                 mono_array_setref (result, i, attr);
8429         }
8430         return result;
8431 }
8432
8433 static MonoArray*
8434 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8435 {
8436         MonoArray *result;
8437         MonoObject *attr;
8438         int i, n;
8439
8440         n = 0;
8441         for (i = 0; i < cinfo->num_attrs; ++i) {
8442                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8443                         n ++;
8444         }
8445
8446         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8447         n = 0;
8448         for (i = 0; i < cinfo->num_attrs; ++i) {
8449                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8450                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8451                         mono_array_setref (result, n, attr);
8452                         n ++;
8453                 }
8454         }
8455         return result;
8456 }
8457
8458 static MonoArray*
8459 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8460 {
8461         MonoArray *result;
8462         MonoObject *attr;
8463         int i;
8464         
8465         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8466         for (i = 0; i < cinfo->num_attrs; ++i) {
8467                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8468                 mono_array_setref (result, i, attr);
8469         }
8470         return result;
8471 }
8472
8473 /**
8474  * mono_custom_attrs_from_index:
8475  *
8476  * Returns: NULL if no attributes are found or if a loading error occurs.
8477  */
8478 MonoCustomAttrInfo*
8479 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8480 {
8481         guint32 mtoken, i, len;
8482         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8483         MonoTableInfo *ca;
8484         MonoCustomAttrInfo *ainfo;
8485         GList *tmp, *list = NULL;
8486         const char *data;
8487
8488         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8489
8490         i = mono_metadata_custom_attrs_from_index (image, idx);
8491         if (!i)
8492                 return NULL;
8493         i --;
8494         while (i < ca->rows) {
8495                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8496                         break;
8497                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8498                 ++i;
8499         }
8500         len = g_list_length (list);
8501         if (!len)
8502                 return NULL;
8503         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8504         ainfo->num_attrs = len;
8505         ainfo->image = image;
8506         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8507                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8508                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8509                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8510                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8511                         mtoken |= MONO_TOKEN_METHOD_DEF;
8512                         break;
8513                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8514                         mtoken |= MONO_TOKEN_MEMBER_REF;
8515                         break;
8516                 default:
8517                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8518                         break;
8519                 }
8520                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8521                 if (!ainfo->attrs [i].ctor) {
8522                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8523                         g_list_free (list);
8524                         g_free (ainfo);
8525                         return NULL;
8526                 }
8527
8528                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8529                         /*FIXME raising an exception here doesn't make any sense*/
8530                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8531                         g_list_free (list);
8532                         g_free (ainfo);
8533                         return NULL;
8534                 }
8535                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8536                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8537                 ainfo->attrs [i].data = (guchar*)data;
8538         }
8539         g_list_free (list);
8540
8541         return ainfo;
8542 }
8543
8544 MonoCustomAttrInfo*
8545 mono_custom_attrs_from_method (MonoMethod *method)
8546 {
8547         guint32 idx;
8548
8549         /*
8550          * An instantiated method has the same cattrs as the generic method definition.
8551          *
8552          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8553          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8554          */
8555         if (method->is_inflated)
8556                 method = ((MonoMethodInflated *) method)->declaring;
8557         
8558         if (method->dynamic || method->klass->image->dynamic)
8559                 return lookup_custom_attr (method->klass->image, method);
8560
8561         if (!method->token)
8562                 /* Synthetic methods */
8563                 return NULL;
8564
8565         idx = mono_method_get_index (method);
8566         idx <<= MONO_CUSTOM_ATTR_BITS;
8567         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8568         return mono_custom_attrs_from_index (method->klass->image, idx);
8569 }
8570
8571 MonoCustomAttrInfo*
8572 mono_custom_attrs_from_class (MonoClass *klass)
8573 {
8574         guint32 idx;
8575
8576         if (klass->generic_class)
8577                 klass = klass->generic_class->container_class;
8578
8579         if (klass->image->dynamic)
8580                 return lookup_custom_attr (klass->image, klass);
8581
8582         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8583                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8584                 idx <<= MONO_CUSTOM_ATTR_BITS;
8585                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8586         } else {
8587                 idx = mono_metadata_token_index (klass->type_token);
8588                 idx <<= MONO_CUSTOM_ATTR_BITS;
8589                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8590         }
8591         return mono_custom_attrs_from_index (klass->image, idx);
8592 }
8593
8594 MonoCustomAttrInfo*
8595 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8596 {
8597         guint32 idx;
8598         
8599         if (assembly->image->dynamic)
8600                 return lookup_custom_attr (assembly->image, assembly);
8601         idx = 1; /* there is only one assembly */
8602         idx <<= MONO_CUSTOM_ATTR_BITS;
8603         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8604         return mono_custom_attrs_from_index (assembly->image, idx);
8605 }
8606
8607 static MonoCustomAttrInfo*
8608 mono_custom_attrs_from_module (MonoImage *image)
8609 {
8610         guint32 idx;
8611         
8612         if (image->dynamic)
8613                 return lookup_custom_attr (image, image);
8614         idx = 1; /* there is only one module */
8615         idx <<= MONO_CUSTOM_ATTR_BITS;
8616         idx |= MONO_CUSTOM_ATTR_MODULE;
8617         return mono_custom_attrs_from_index (image, idx);
8618 }
8619
8620 MonoCustomAttrInfo*
8621 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8622 {
8623         guint32 idx;
8624         
8625         if (klass->image->dynamic) {
8626                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8627                 return lookup_custom_attr (klass->image, property);
8628         }
8629         idx = find_property_index (klass, property);
8630         idx <<= MONO_CUSTOM_ATTR_BITS;
8631         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8632         return mono_custom_attrs_from_index (klass->image, idx);
8633 }
8634
8635 MonoCustomAttrInfo*
8636 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8637 {
8638         guint32 idx;
8639         
8640         if (klass->image->dynamic) {
8641                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8642                 return lookup_custom_attr (klass->image, event);
8643         }
8644         idx = find_event_index (klass, event);
8645         idx <<= MONO_CUSTOM_ATTR_BITS;
8646         idx |= MONO_CUSTOM_ATTR_EVENT;
8647         return mono_custom_attrs_from_index (klass->image, idx);
8648 }
8649
8650 MonoCustomAttrInfo*
8651 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8652 {
8653         guint32 idx;
8654         if (klass->image->dynamic) {
8655                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8656                 return lookup_custom_attr (klass->image, field);
8657         }
8658         idx = find_field_index (klass, field);
8659         idx <<= MONO_CUSTOM_ATTR_BITS;
8660         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8661         return mono_custom_attrs_from_index (klass->image, idx);
8662 }
8663
8664 MonoCustomAttrInfo*
8665 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8666 {
8667         MonoTableInfo *ca;
8668         guint32 i, idx, method_index;
8669         guint32 param_list, param_last, param_pos, found;
8670         MonoImage *image;
8671         MonoReflectionMethodAux *aux;
8672
8673         /*
8674          * An instantiated method has the same cattrs as the generic method definition.
8675          *
8676          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8677          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8678          */
8679         if (method->is_inflated)
8680                 method = ((MonoMethodInflated *) method)->declaring;
8681
8682         if (method->klass->image->dynamic) {
8683                 MonoCustomAttrInfo *res, *ainfo;
8684                 int size;
8685
8686                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8687                 if (!aux || !aux->param_cattr)
8688                         return NULL;
8689
8690                 /* Need to copy since it will be freed later */
8691                 ainfo = aux->param_cattr [param];
8692                 if (!ainfo)
8693                         return NULL;
8694                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8695                 res = g_malloc0 (size);
8696                 memcpy (res, ainfo, size);
8697                 return res;
8698         }
8699
8700         image = method->klass->image;
8701         method_index = mono_method_get_index (method);
8702         ca = &image->tables [MONO_TABLE_METHOD];
8703
8704         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8705         if (method_index == ca->rows) {
8706                 ca = &image->tables [MONO_TABLE_PARAM];
8707                 param_last = ca->rows + 1;
8708         } else {
8709                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8710                 ca = &image->tables [MONO_TABLE_PARAM];
8711         }
8712         found = FALSE;
8713         for (i = param_list; i < param_last; ++i) {
8714                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8715                 if (param_pos == param) {
8716                         found = TRUE;
8717                         break;
8718                 }
8719         }
8720         if (!found)
8721                 return NULL;
8722         idx = i;
8723         idx <<= MONO_CUSTOM_ATTR_BITS;
8724         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8725         return mono_custom_attrs_from_index (image, idx);
8726 }
8727
8728 gboolean
8729 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8730 {
8731         int i;
8732         MonoClass *klass;
8733         for (i = 0; i < ainfo->num_attrs; ++i) {
8734                 klass = ainfo->attrs [i].ctor->klass;
8735                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8736                         return TRUE;
8737         }
8738         return FALSE;
8739 }
8740
8741 MonoObject*
8742 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8743 {
8744         int i, attr_index;
8745         MonoClass *klass;
8746         MonoArray *attrs;
8747
8748         attr_index = -1;
8749         for (i = 0; i < ainfo->num_attrs; ++i) {
8750                 klass = ainfo->attrs [i].ctor->klass;
8751                 if (mono_class_has_parent (klass, attr_klass)) {
8752                         attr_index = i;
8753                         break;
8754                 }
8755         }
8756         if (attr_index == -1)
8757                 return NULL;
8758
8759         attrs = mono_custom_attrs_construct (ainfo);
8760         if (attrs)
8761                 return mono_array_get (attrs, MonoObject*, attr_index);
8762         else
8763                 return NULL;
8764 }
8765
8766 /*
8767  * mono_reflection_get_custom_attrs_info:
8768  * @obj: a reflection object handle
8769  *
8770  * Return the custom attribute info for attributes defined for the
8771  * reflection handle @obj. The objects.
8772  *
8773  * FIXME this function leaks like a sieve for SRE objects.
8774  */
8775 MonoCustomAttrInfo*
8776 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8777 {
8778         MonoClass *klass;
8779         MonoCustomAttrInfo *cinfo = NULL;
8780         
8781         klass = obj->vtable->klass;
8782         if (klass == mono_defaults.monotype_class) {
8783                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8784                 klass = mono_class_from_mono_type (type);
8785                 if (!mono_class_init (klass))
8786                         mono_raise_exception (mono_class_get_exception_for_failure (klass));
8787                 cinfo = mono_custom_attrs_from_class (klass);
8788         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8789                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8790                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8791         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8792                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8793                 cinfo = mono_custom_attrs_from_module (module->image);
8794         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8795                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8796                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8797         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8798                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8799                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8800         } else if (strcmp ("MonoField", klass->name) == 0) {
8801                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8802                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8803         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8804                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8805                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8806         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8807                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8808                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8809         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8810                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8811                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8812                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8813                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8814                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8815                 } else if (is_sr_mono_property (member_class)) {
8816                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8817                         MonoMethod *method;
8818                         if (!(method = prop->property->get))
8819                                 method = prop->property->set;
8820                         g_assert (method);
8821
8822                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8823                 } 
8824 #ifndef DISABLE_REFLECTION_EMIT
8825                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8826                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8827                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8828                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8829                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8830                         MonoMethod *method = NULL;
8831                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8832                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8833                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8834                                 method = ((MonoReflectionMethod *)c->cb)->method;
8835                         else
8836                                 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));
8837
8838                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8839                 } 
8840 #endif
8841                 else {
8842                         char *type_name = mono_type_get_full_name (member_class);
8843                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8844                         MonoException *ex = mono_get_exception_not_supported  (msg);
8845                         g_free (type_name);
8846                         g_free (msg);
8847                         mono_raise_exception (ex);
8848                 }
8849         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8850                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8851                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8852         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8853                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8854                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8855         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8856                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8857                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8858         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8859                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8860                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8861         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8862                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8863                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8864         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8865                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8866                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8867         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8868                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8869                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8870         } else { /* handle other types here... */
8871                 g_error ("get custom attrs not yet supported for %s", klass->name);
8872         }
8873
8874         return cinfo;
8875 }
8876
8877 /*
8878  * mono_reflection_get_custom_attrs_by_type:
8879  * @obj: a reflection object handle
8880  *
8881  * Return an array with all the custom attributes defined of the
8882  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8883  * of that type are returned. The objects are fully build. Return NULL if a loading error
8884  * occurs.
8885  */
8886 MonoArray*
8887 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8888 {
8889         MonoArray *result;
8890         MonoCustomAttrInfo *cinfo;
8891
8892         cinfo = mono_reflection_get_custom_attrs_info (obj);
8893         if (cinfo) {
8894                 if (attr_klass)
8895                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8896                 else
8897                         result = mono_custom_attrs_construct (cinfo);
8898                 if (!cinfo->cached)
8899                         mono_custom_attrs_free (cinfo);
8900         } else {
8901                 if (mono_loader_get_last_error ())
8902                         return NULL;
8903                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8904         }
8905
8906         return result;
8907 }
8908
8909 /*
8910  * mono_reflection_get_custom_attrs:
8911  * @obj: a reflection object handle
8912  *
8913  * Return an array with all the custom attributes defined of the
8914  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8915  * occurs.
8916  */
8917 MonoArray*
8918 mono_reflection_get_custom_attrs (MonoObject *obj)
8919 {
8920         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8921 }
8922
8923 /*
8924  * mono_reflection_get_custom_attrs_data:
8925  * @obj: a reflection obj handle
8926  *
8927  * Returns an array of System.Reflection.CustomAttributeData,
8928  * which include information about attributes reflected on
8929  * types loaded using the Reflection Only methods
8930  */
8931 MonoArray*
8932 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8933 {
8934         MonoArray *result;
8935         MonoCustomAttrInfo *cinfo;
8936
8937         cinfo = mono_reflection_get_custom_attrs_info (obj);
8938         if (cinfo) {
8939                 result = mono_custom_attrs_data_construct (cinfo);
8940                 if (!cinfo->cached)
8941                         mono_custom_attrs_free (cinfo);
8942         } else
8943                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8944
8945         return result;
8946 }
8947
8948 static MonoReflectionType*
8949 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8950 {
8951         static MonoMethod *method_get_underlying_system_type = NULL;
8952         MonoMethod *usertype_method;
8953
8954         if (!method_get_underlying_system_type)
8955                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8956         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8957         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8958 }
8959
8960
8961 static gboolean
8962 is_corlib_type (MonoClass *class)
8963 {
8964         return class->image == mono_defaults.corlib;
8965 }
8966
8967 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8968         static MonoClass *cached_class; \
8969         if (cached_class) \
8970                 return cached_class == _class; \
8971         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8972                 cached_class = _class; \
8973                 return TRUE; \
8974         } \
8975         return FALSE; \
8976 } while (0) \
8977
8978
8979 #ifndef DISABLE_REFLECTION_EMIT
8980 static gboolean
8981 is_sre_array (MonoClass *class)
8982 {
8983         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8984 }
8985
8986 static gboolean
8987 is_sre_byref (MonoClass *class)
8988 {
8989         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8990 }
8991
8992 static gboolean
8993 is_sre_pointer (MonoClass *class)
8994 {
8995         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8996 }
8997
8998 static gboolean
8999 is_sre_generic_instance (MonoClass *class)
9000 {
9001         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9002 }
9003
9004 static gboolean
9005 is_sre_type_builder (MonoClass *class)
9006 {
9007         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9008 }
9009
9010 static gboolean
9011 is_sre_method_builder (MonoClass *class)
9012 {
9013         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9014 }
9015
9016 static gboolean
9017 is_sre_ctor_builder (MonoClass *class)
9018 {
9019         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9020 }
9021
9022 static gboolean
9023 is_sre_field_builder (MonoClass *class)
9024 {
9025         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9026 }
9027
9028 static gboolean
9029 is_sre_method_on_tb_inst (MonoClass *class)
9030 {
9031         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9032 }
9033
9034 static gboolean
9035 is_sre_ctor_on_tb_inst (MonoClass *class)
9036 {
9037         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9038 }
9039
9040 MonoType*
9041 mono_reflection_type_get_handle (MonoReflectionType* ref)
9042 {
9043         MonoClass *class;
9044         if (!ref)
9045                 return NULL;
9046         if (ref->type)
9047                 return ref->type;
9048
9049         if (is_usertype (ref)) {
9050                 ref = mono_reflection_type_get_underlying_system_type (ref);
9051                 if (ref == NULL || is_usertype (ref))
9052                         return NULL;
9053                 if (ref->type)
9054                         return ref->type;
9055         }
9056
9057         class = mono_object_class (ref);
9058
9059         if (is_sre_array (class)) {
9060                 MonoType *res;
9061                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9062                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9063                 g_assert (base);
9064                 if (sre_array->rank == 0) //single dimentional array
9065                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9066                 else
9067                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9068                 sre_array->type.type = res;
9069                 return res;
9070         } else if (is_sre_byref (class)) {
9071                 MonoType *res;
9072                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9073                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9074                 g_assert (base);
9075                 res = &mono_class_from_mono_type (base)->this_arg;
9076                 sre_byref->type.type = res;
9077                 return res;
9078         } else if (is_sre_pointer (class)) {
9079                 MonoType *res;
9080                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9081                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9082                 g_assert (base);
9083                 res = &mono_ptr_class_get (base)->byval_arg;
9084                 sre_pointer->type.type = res;
9085                 return res;
9086         } else if (is_sre_generic_instance (class)) {
9087                 MonoType *res, **types;
9088                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9089                 int i, count;
9090
9091                 count = mono_array_length (gclass->type_arguments);
9092                 types = g_new0 (MonoType*, count);
9093                 for (i = 0; i < count; ++i) {
9094                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9095                         types [i] = mono_reflection_type_get_handle (t);
9096                         if (!types[i]) {
9097                                 g_free (types);
9098                                 return NULL;
9099                         }
9100                 }
9101
9102                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9103                 g_free (types);
9104                 g_assert (res);
9105                 gclass->type.type = res;
9106                 return res;
9107         }
9108
9109         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9110         return NULL;
9111 }
9112
9113
9114
9115 void
9116 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9117 {
9118         mono_reflection_type_get_handle (type);
9119 }
9120
9121 void
9122 mono_reflection_register_with_runtime (MonoReflectionType *type)
9123 {
9124         MonoType *res = mono_reflection_type_get_handle (type);
9125         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9126         MonoClass *class;
9127
9128         if (!res)
9129                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9130
9131         class = mono_class_from_mono_type (res);
9132
9133         mono_loader_lock (); /*same locking as mono_type_get_object*/
9134         mono_domain_lock (domain);
9135
9136         if (!class->image->dynamic) {
9137                 mono_class_setup_supertypes (class);
9138         } else {
9139                 if (!domain->type_hash)
9140                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
9141                                         (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9142                 mono_g_hash_table_insert (domain->type_hash, res, type);
9143         }
9144         mono_domain_unlock (domain);
9145         mono_loader_unlock ();
9146 }
9147
9148 /**
9149  * LOCKING: Assumes the loader lock is held.
9150  */
9151 static MonoMethodSignature*
9152 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9153         MonoMethodSignature *sig;
9154         int count, i;
9155
9156         count = parameters? mono_array_length (parameters): 0;
9157
9158         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9159         sig->param_count = count;
9160         sig->sentinelpos = -1; /* FIXME */
9161         for (i = 0; i < count; ++i)
9162                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9163         return sig;
9164 }
9165
9166 /**
9167  * LOCKING: Assumes the loader lock is held.
9168  */
9169 static MonoMethodSignature*
9170 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9171         MonoMethodSignature *sig;
9172
9173         sig = parameters_to_signature (image, ctor->parameters);
9174         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9175         sig->ret = &mono_defaults.void_class->byval_arg;
9176         return sig;
9177 }
9178
9179 /**
9180  * LOCKING: Assumes the loader lock is held.
9181  */
9182 static MonoMethodSignature*
9183 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9184         MonoMethodSignature *sig;
9185
9186         sig = parameters_to_signature (image, method->parameters);
9187         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9188         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9189         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9190         return sig;
9191 }
9192
9193 static MonoMethodSignature*
9194 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9195         MonoMethodSignature *sig;
9196
9197         sig = parameters_to_signature (NULL, method->parameters);
9198         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9199         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9200         sig->generic_param_count = 0;
9201         return sig;
9202 }
9203
9204 static void
9205 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9206 {
9207         MonoClass *klass = mono_object_class (prop);
9208         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9209                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9210                 *name = mono_string_to_utf8 (pb->name);
9211                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9212         } else {
9213                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9214                 *name = g_strdup (p->property->name);
9215                 if (p->property->get)
9216                         *type = mono_method_signature (p->property->get)->ret;
9217                 else
9218                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9219         }
9220 }
9221
9222 static void
9223 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9224 {
9225         MonoClass *klass = mono_object_class (field);
9226         if (strcmp (klass->name, "FieldBuilder") == 0) {
9227                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9228                 *name = mono_string_to_utf8 (fb->name);
9229                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9230         } else {
9231                 MonoReflectionField *f = (MonoReflectionField *)field;
9232                 *name = g_strdup (mono_field_get_name (f->field));
9233                 *type = f->field->type;
9234         }
9235 }
9236
9237 #else /* DISABLE_REFLECTION_EMIT */
9238
9239 void
9240 mono_reflection_register_with_runtime (MonoReflectionType *type)
9241 {
9242         /* This is empty */
9243 }
9244
9245 static gboolean
9246 is_sre_type_builder (MonoClass *class)
9247 {
9248         return FALSE;
9249 }
9250
9251 static gboolean
9252 is_sre_generic_instance (MonoClass *class)
9253 {
9254         return FALSE;
9255 }
9256
9257 #endif /* !DISABLE_REFLECTION_EMIT */
9258
9259
9260 static gboolean
9261 is_sr_mono_field (MonoClass *class)
9262 {
9263         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9264 }
9265
9266 static gboolean
9267 is_sr_mono_property (MonoClass *class)
9268 {
9269         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9270 }
9271
9272 static gboolean
9273 is_sr_mono_method (MonoClass *class)
9274 {
9275         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9276 }
9277
9278 static gboolean
9279 is_sr_mono_cmethod (MonoClass *class)
9280 {
9281         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9282 }
9283
9284 static gboolean
9285 is_sr_mono_generic_method (MonoClass *class)
9286 {
9287         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9288 }
9289
9290 static gboolean
9291 is_sr_mono_generic_cmethod (MonoClass *class)
9292 {
9293         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9294 }
9295
9296 gboolean
9297 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9298 {
9299         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9300 }
9301
9302 static gboolean
9303 is_usertype (MonoReflectionType *ref)
9304 {
9305         MonoClass *class = mono_object_class (ref);
9306         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9307 }
9308
9309 static MonoReflectionType*
9310 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9311 {
9312         if (!type || type->type)
9313                 return type;
9314
9315         if (is_usertype (type)) {
9316                 type = mono_reflection_type_get_underlying_system_type (type);
9317                 if (is_usertype (type))
9318                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9319         }
9320
9321         return type;
9322 }
9323 /*
9324  * Encode a value in a custom attribute stream of bytes.
9325  * The value to encode is either supplied as an object in argument val
9326  * (valuetypes are boxed), or as a pointer to the data in the
9327  * argument argval.
9328  * @type represents the type of the value
9329  * @buffer is the start of the buffer
9330  * @p the current position in the buffer
9331  * @buflen contains the size of the buffer and is used to return the new buffer size
9332  * if this needs to be realloced.
9333  * @retbuffer and @retp return the start and the position of the buffer
9334  */
9335 static void
9336 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9337 {
9338         MonoTypeEnum simple_type;
9339         
9340         if ((p-buffer) + 10 >= *buflen) {
9341                 char *newbuf;
9342                 *buflen *= 2;
9343                 newbuf = g_realloc (buffer, *buflen);
9344                 p = newbuf + (p-buffer);
9345                 buffer = newbuf;
9346         }
9347         if (!argval)
9348                 argval = ((char*)arg + sizeof (MonoObject));
9349         simple_type = type->type;
9350 handle_enum:
9351         switch (simple_type) {
9352         case MONO_TYPE_BOOLEAN:
9353         case MONO_TYPE_U1:
9354         case MONO_TYPE_I1:
9355                 *p++ = *argval;
9356                 break;
9357         case MONO_TYPE_CHAR:
9358         case MONO_TYPE_U2:
9359         case MONO_TYPE_I2:
9360                 swap_with_size (p, argval, 2, 1);
9361                 p += 2;
9362                 break;
9363         case MONO_TYPE_U4:
9364         case MONO_TYPE_I4:
9365         case MONO_TYPE_R4:
9366                 swap_with_size (p, argval, 4, 1);
9367                 p += 4;
9368                 break;
9369         case MONO_TYPE_R8:
9370 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9371                 p [0] = argval [4];
9372                 p [1] = argval [5];
9373                 p [2] = argval [6];
9374                 p [3] = argval [7];
9375                 p [4] = argval [0];
9376                 p [5] = argval [1];
9377                 p [6] = argval [2];
9378                 p [7] = argval [3];
9379 #else
9380                 swap_with_size (p, argval, 8, 1);
9381 #endif
9382                 p += 8;
9383                 break;
9384         case MONO_TYPE_U8:
9385         case MONO_TYPE_I8:
9386                 swap_with_size (p, argval, 8, 1);
9387                 p += 8;
9388                 break;
9389         case MONO_TYPE_VALUETYPE:
9390                 if (type->data.klass->enumtype) {
9391                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9392                         goto handle_enum;
9393                 } else {
9394                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9395                 }
9396                 break;
9397         case MONO_TYPE_STRING: {
9398                 char *str;
9399                 guint32 slen;
9400                 if (!arg) {
9401                         *p++ = 0xFF;
9402                         break;
9403                 }
9404                 str = mono_string_to_utf8 ((MonoString*)arg);
9405                 slen = strlen (str);
9406                 if ((p-buffer) + 10 + slen >= *buflen) {
9407                         char *newbuf;
9408                         *buflen *= 2;
9409                         *buflen += slen;
9410                         newbuf = g_realloc (buffer, *buflen);
9411                         p = newbuf + (p-buffer);
9412                         buffer = newbuf;
9413                 }
9414                 mono_metadata_encode_value (slen, p, &p);
9415                 memcpy (p, str, slen);
9416                 p += slen;
9417                 g_free (str);
9418                 break;
9419         }
9420         case MONO_TYPE_CLASS: {
9421                 char *str;
9422                 guint32 slen;
9423                 if (!arg) {
9424                         *p++ = 0xFF;
9425                         break;
9426                 }
9427 handle_type:
9428                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9429                 slen = strlen (str);
9430                 if ((p-buffer) + 10 + slen >= *buflen) {
9431                         char *newbuf;
9432                         *buflen *= 2;
9433                         *buflen += slen;
9434                         newbuf = g_realloc (buffer, *buflen);
9435                         p = newbuf + (p-buffer);
9436                         buffer = newbuf;
9437                 }
9438                 mono_metadata_encode_value (slen, p, &p);
9439                 memcpy (p, str, slen);
9440                 p += slen;
9441                 g_free (str);
9442                 break;
9443         }
9444         case MONO_TYPE_SZARRAY: {
9445                 int len, i;
9446                 MonoClass *eclass, *arg_eclass;
9447
9448                 if (!arg) {
9449                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9450                         break;
9451                 }
9452                 len = mono_array_length ((MonoArray*)arg);
9453                 *p++ = len & 0xff;
9454                 *p++ = (len >> 8) & 0xff;
9455                 *p++ = (len >> 16) & 0xff;
9456                 *p++ = (len >> 24) & 0xff;
9457                 *retp = p;
9458                 *retbuffer = buffer;
9459                 eclass = type->data.klass;
9460                 arg_eclass = mono_object_class (arg)->element_class;
9461
9462                 if (!eclass) {
9463                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9464                         eclass = mono_defaults.object_class;
9465                 }
9466                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9467                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9468                         int elsize = mono_class_array_element_size (arg_eclass);
9469                         for (i = 0; i < len; ++i) {
9470                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9471                                 elptr += elsize;
9472                         }
9473                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9474                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9475                         int elsize = mono_class_array_element_size (eclass);
9476                         for (i = 0; i < len; ++i) {
9477                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9478                                 elptr += elsize;
9479                         }
9480                 } else {
9481                         for (i = 0; i < len; ++i) {
9482                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9483                         }
9484                 }
9485                 break;
9486         }
9487         case MONO_TYPE_OBJECT: {
9488                 MonoClass *klass;
9489                 char *str;
9490                 guint32 slen;
9491
9492                 /*
9493                  * The parameter type is 'object' but the type of the actual
9494                  * argument is not. So we have to add type information to the blob
9495                  * too. This is completely undocumented in the spec.
9496                  */
9497
9498                 if (arg == NULL) {
9499                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9500                         *p++ = 0xFF;
9501                         break;
9502                 }
9503                 
9504                 klass = mono_object_class (arg);
9505
9506                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9507                         *p++ = 0x50;
9508                         goto handle_type;
9509                 } else if (klass->enumtype) {
9510                         *p++ = 0x55;
9511                 } else if (klass == mono_defaults.string_class) {
9512                         simple_type = MONO_TYPE_STRING;
9513                         *p++ = 0x0E;
9514                         goto handle_enum;
9515                 } else if (klass->rank == 1) {
9516                         *p++ = 0x1D;
9517                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9518                                 /* See Partition II, Appendix B3 */
9519                                 *p++ = 0x51;
9520                         else
9521                                 *p++ = klass->element_class->byval_arg.type;
9522                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9523                         break;
9524                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9525                         *p++ = simple_type = klass->byval_arg.type;
9526                         goto handle_enum;
9527                 } else {
9528                         g_error ("unhandled type in custom attr");
9529                 }
9530                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9531                 slen = strlen (str);
9532                 if ((p-buffer) + 10 + slen >= *buflen) {
9533                         char *newbuf;
9534                         *buflen *= 2;
9535                         *buflen += slen;
9536                         newbuf = g_realloc (buffer, *buflen);
9537                         p = newbuf + (p-buffer);
9538                         buffer = newbuf;
9539                 }
9540                 mono_metadata_encode_value (slen, p, &p);
9541                 memcpy (p, str, slen);
9542                 p += slen;
9543                 g_free (str);
9544                 simple_type = mono_class_enum_basetype (klass)->type;
9545                 goto handle_enum;
9546         }
9547         default:
9548                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9549         }
9550         *retp = p;
9551         *retbuffer = buffer;
9552 }
9553
9554 static void
9555 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9556 {
9557         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9558                 char *str = type_get_qualified_name (type, NULL);
9559                 int slen = strlen (str);
9560
9561                 *p++ = 0x55;
9562                 /*
9563                  * This seems to be optional...
9564                  * *p++ = 0x80;
9565                  */
9566                 mono_metadata_encode_value (slen, p, &p);
9567                 memcpy (p, str, slen);
9568                 p += slen;
9569                 g_free (str);
9570         } else if (type->type == MONO_TYPE_OBJECT) {
9571                 *p++ = 0x51;
9572         } else if (type->type == MONO_TYPE_CLASS) {
9573                 /* it should be a type: encode_cattr_value () has the check */
9574                 *p++ = 0x50;
9575         } else {
9576                 mono_metadata_encode_value (type->type, p, &p);
9577                 if (type->type == MONO_TYPE_SZARRAY)
9578                         /* See the examples in Partition VI, Annex B */
9579                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9580         }
9581
9582         *retp = p;
9583 }
9584
9585 #ifndef DISABLE_REFLECTION_EMIT
9586 static void
9587 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9588 {
9589         int len;
9590         /* Preallocate a large enough buffer */
9591         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9592                 char *str = type_get_qualified_name (type, NULL);
9593                 len = strlen (str);
9594                 g_free (str);
9595         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9596                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9597                 len = strlen (str);
9598                 g_free (str);
9599         } else {
9600                 len = 0;
9601         }
9602         len += strlen (name);
9603
9604         if ((p-buffer) + 20 + len >= *buflen) {
9605                 char *newbuf;
9606                 *buflen *= 2;
9607                 *buflen += len;
9608                 newbuf = g_realloc (buffer, *buflen);
9609                 p = newbuf + (p-buffer);
9610                 buffer = newbuf;
9611         }
9612
9613         encode_field_or_prop_type (type, p, &p);
9614
9615         len = strlen (name);
9616         mono_metadata_encode_value (len, p, &p);
9617         memcpy (p, name, len);
9618         p += len;
9619         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9620         *retp = p;
9621         *retbuffer = buffer;
9622 }
9623
9624 /*
9625  * mono_reflection_get_custom_attrs_blob:
9626  * @ctor: custom attribute constructor
9627  * @ctorArgs: arguments o the constructor
9628  * @properties:
9629  * @propValues:
9630  * @fields:
9631  * @fieldValues:
9632  * 
9633  * Creates the blob of data that needs to be saved in the metadata and that represents
9634  * the custom attributed described by @ctor, @ctorArgs etc.
9635  * Returns: a Byte array representing the blob of data.
9636  */
9637 MonoArray*
9638 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9639 {
9640         MonoArray *result;
9641         MonoMethodSignature *sig;
9642         MonoObject *arg;
9643         char *buffer, *p;
9644         guint32 buflen, i;
9645
9646         MONO_ARCH_SAVE_REGS;
9647
9648         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9649                 /* sig is freed later so allocate it in the heap */
9650                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9651         } else {
9652                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9653         }
9654
9655         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9656         buflen = 256;
9657         p = buffer = g_malloc (buflen);
9658         /* write the prolog */
9659         *p++ = 1;
9660         *p++ = 0;
9661         for (i = 0; i < sig->param_count; ++i) {
9662                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9663                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9664         }
9665         i = 0;
9666         if (properties)
9667                 i += mono_array_length (properties);
9668         if (fields)
9669                 i += mono_array_length (fields);
9670         *p++ = i & 0xff;
9671         *p++ = (i >> 8) & 0xff;
9672         if (properties) {
9673                 MonoObject *prop;
9674                 for (i = 0; i < mono_array_length (properties); ++i) {
9675                         MonoType *ptype;
9676                         char *pname;
9677
9678                         prop = mono_array_get (properties, gpointer, i);
9679                         get_prop_name_and_type (prop, &pname, &ptype);
9680                         *p++ = 0x54; /* PROPERTY signature */
9681                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9682                         g_free (pname);
9683                 }
9684         }
9685
9686         if (fields) {
9687                 MonoObject *field;
9688                 for (i = 0; i < mono_array_length (fields); ++i) {
9689                         MonoType *ftype;
9690                         char *fname;
9691
9692                         field = mono_array_get (fields, gpointer, i);
9693                         get_field_name_and_type (field, &fname, &ftype);
9694                         *p++ = 0x53; /* FIELD signature */
9695                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9696                         g_free (fname);
9697                 }
9698         }
9699
9700         g_assert (p - buffer <= buflen);
9701         buflen = p - buffer;
9702         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9703         p = mono_array_addr (result, char, 0);
9704         memcpy (p, buffer, buflen);
9705         g_free (buffer);
9706         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9707                 g_free (sig);
9708         return result;
9709 }
9710
9711 /*
9712  * mono_reflection_setup_internal_class:
9713  * @tb: a TypeBuilder object
9714  *
9715  * Creates a MonoClass that represents the TypeBuilder.
9716  * This is a trick that lets us simplify a lot of reflection code
9717  * (and will allow us to support Build and Run assemblies easier).
9718  */
9719 void
9720 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9721 {
9722         MonoError error;
9723         MonoClass *klass, *parent;
9724
9725         MONO_ARCH_SAVE_REGS;
9726
9727         RESOLVE_TYPE (tb->parent);
9728
9729         mono_loader_lock ();
9730
9731         if (tb->parent) {
9732                 /* check so we can compile corlib correctly */
9733                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9734                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9735                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9736                 } else {
9737                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9738                 }
9739         } else {
9740                 parent = NULL;
9741         }
9742         
9743         /* the type has already being created: it means we just have to change the parent */
9744         if (tb->type.type) {
9745                 klass = mono_class_from_mono_type (tb->type.type);
9746                 klass->parent = NULL;
9747                 /* fool mono_class_setup_parent */
9748                 klass->supertypes = NULL;
9749                 mono_class_setup_parent (klass, parent);
9750                 mono_class_setup_mono_type (klass);
9751                 mono_loader_unlock ();
9752                 return;
9753         }
9754
9755         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9756
9757         klass->image = &tb->module->dynamic_image->image;
9758
9759         klass->inited = 1; /* we lie to the runtime */
9760         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9761         if (!mono_error_ok (&error))
9762                 goto failure;
9763         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9764         if (!mono_error_ok (&error))
9765                 goto failure;
9766         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9767         klass->flags = tb->attrs;
9768         
9769         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9770
9771         klass->element_class = klass;
9772
9773         if (mono_class_get_ref_info (klass) == NULL) {
9774
9775                 mono_class_set_ref_info (klass, tb);
9776
9777                 /* Put into cache so mono_class_get () will find it.
9778                 Skip nested types as those should not be available on the global scope. */
9779                 if (!tb->nesting_type) {
9780                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9781                 } else {
9782                         klass->image->reflection_info_unregister_classes =
9783                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9784                 }
9785         } else {
9786                 g_assert (mono_class_get_ref_info (klass) == tb);
9787         }
9788
9789         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9790                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9791
9792         if (parent != NULL) {
9793                 mono_class_setup_parent (klass, parent);
9794         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9795                 const char *old_n = klass->name;
9796                 /* trick to get relative numbering right when compiling corlib */
9797                 klass->name = "BuildingObject";
9798                 mono_class_setup_parent (klass, mono_defaults.object_class);
9799                 klass->name = old_n;
9800         }
9801
9802         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9803                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9804                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9805                 klass->instance_size = sizeof (MonoObject);
9806                 klass->size_inited = 1;
9807                 mono_class_setup_vtable_general (klass, NULL, 0);
9808         }
9809
9810         mono_class_setup_mono_type (klass);
9811
9812         mono_class_setup_supertypes (klass);
9813
9814         /*
9815          * FIXME: handle interfaces.
9816          */
9817
9818         tb->type.type = &klass->byval_arg;
9819
9820         if (tb->nesting_type) {
9821                 g_assert (tb->nesting_type->type);
9822                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9823         }
9824
9825         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9826
9827         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9828         
9829         mono_loader_unlock ();
9830         return;
9831
9832 failure:
9833         mono_loader_unlock ();
9834         mono_error_raise_exception (&error);
9835 }
9836
9837 /*
9838  * mono_reflection_setup_generic_class:
9839  * @tb: a TypeBuilder object
9840  *
9841  * Setup the generic class before adding the first generic parameter.
9842  */
9843 void
9844 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9845 {
9846 }
9847
9848 /*
9849  * mono_reflection_create_generic_class:
9850  * @tb: a TypeBuilder object
9851  *
9852  * Creates the generic class after all generic parameters have been added.
9853  */
9854 void
9855 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9856 {
9857         MonoClass *klass;
9858         int count, i;
9859
9860         MONO_ARCH_SAVE_REGS;
9861
9862         klass = mono_class_from_mono_type (tb->type.type);
9863
9864         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9865
9866         if (klass->generic_container || (count == 0))
9867                 return;
9868
9869         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9870
9871         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9872
9873         klass->generic_container->owner.klass = klass;
9874         klass->generic_container->type_argc = count;
9875         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9876
9877         klass->is_generic = 1;
9878
9879         for (i = 0; i < count; i++) {
9880                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9881                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9882                 klass->generic_container->type_params [i] = *param;
9883                 /*Make sure we are a diferent type instance */
9884                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9885                 klass->generic_container->type_params [i].info.pklass = NULL;
9886                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9887
9888                 g_assert (klass->generic_container->type_params [i].param.owner);
9889         }
9890
9891         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9892 }
9893
9894 /*
9895  * mono_reflection_create_internal_class:
9896  * @tb: a TypeBuilder object
9897  *
9898  * Actually create the MonoClass that is associated with the TypeBuilder.
9899  */
9900 void
9901 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9902 {
9903         MonoClass *klass;
9904
9905         MONO_ARCH_SAVE_REGS;
9906
9907         klass = mono_class_from_mono_type (tb->type.type);
9908
9909         mono_loader_lock ();
9910         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9911                 MonoReflectionFieldBuilder *fb;
9912                 MonoClass *ec;
9913                 MonoType *enum_basetype;
9914
9915                 g_assert (tb->fields != NULL);
9916                 g_assert (mono_array_length (tb->fields) >= 1);
9917
9918                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9919
9920                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9921                         mono_loader_unlock ();
9922                         return;
9923                 }
9924
9925                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9926                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9927                 if (!klass->element_class)
9928                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9929
9930                 /*
9931                  * get the element_class from the current corlib.
9932                  */
9933                 ec = default_class_from_mono_type (enum_basetype);
9934                 klass->instance_size = ec->instance_size;
9935                 klass->size_inited = 1;
9936                 /* 
9937                  * this is almost safe to do with enums and it's needed to be able
9938                  * to create objects of the enum type (for use in SetConstant).
9939                  */
9940                 /* FIXME: Does this mean enums can't have method overrides ? */
9941                 mono_class_setup_vtable_general (klass, NULL, 0);
9942         }
9943         mono_loader_unlock ();
9944 }
9945
9946 static MonoMarshalSpec*
9947 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9948                                                                 MonoReflectionMarshal *minfo)
9949 {
9950         MonoMarshalSpec *res;
9951
9952         res = image_g_new0 (image, MonoMarshalSpec, 1);
9953         res->native = minfo->type;
9954
9955         switch (minfo->type) {
9956         case MONO_NATIVE_LPARRAY:
9957                 res->data.array_data.elem_type = minfo->eltype;
9958                 if (minfo->has_size) {
9959                         res->data.array_data.param_num = minfo->param_num;
9960                         res->data.array_data.num_elem = minfo->count;
9961                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9962                 }
9963                 else {
9964                         res->data.array_data.param_num = -1;
9965                         res->data.array_data.num_elem = -1;
9966                         res->data.array_data.elem_mult = -1;
9967                 }
9968                 break;
9969
9970         case MONO_NATIVE_BYVALTSTR:
9971         case MONO_NATIVE_BYVALARRAY:
9972                 res->data.array_data.num_elem = minfo->count;
9973                 break;
9974
9975         case MONO_NATIVE_CUSTOM:
9976                 if (minfo->marshaltyperef)
9977                         res->data.custom_data.custom_name =
9978                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9979                 if (minfo->mcookie)
9980                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9981                 break;
9982
9983         default:
9984                 break;
9985         }
9986
9987         return res;
9988 }
9989 #endif /* !DISABLE_REFLECTION_EMIT */
9990
9991 MonoReflectionMarshal*
9992 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9993                                                                                    MonoMarshalSpec *spec)
9994 {
9995         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9996         MonoReflectionMarshal *minfo;
9997         MonoType *mtype;
9998
9999         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10000                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10001                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10002                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10003         }
10004
10005         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10006         minfo->type = spec->native;
10007
10008         switch (minfo->type) {
10009         case MONO_NATIVE_LPARRAY:
10010                 minfo->eltype = spec->data.array_data.elem_type;
10011                 minfo->count = spec->data.array_data.num_elem;
10012                 minfo->param_num = spec->data.array_data.param_num;
10013                 break;
10014
10015         case MONO_NATIVE_BYVALTSTR:
10016         case MONO_NATIVE_BYVALARRAY:
10017                 minfo->count = spec->data.array_data.num_elem;
10018                 break;
10019
10020         case MONO_NATIVE_CUSTOM:
10021                 if (spec->data.custom_data.custom_name) {
10022                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10023                         if (mtype)
10024                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10025
10026                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10027                 }
10028                 if (spec->data.custom_data.cookie)
10029                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10030                 break;
10031
10032         default:
10033                 break;
10034         }
10035
10036         return minfo;
10037 }
10038
10039 #ifndef DISABLE_REFLECTION_EMIT
10040 static MonoMethod*
10041 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10042                                          ReflectionMethodBuilder *rmb,
10043                                          MonoMethodSignature *sig)
10044 {
10045         MonoError error;
10046         MonoMethod *m;
10047         MonoMethodWrapper *wrapperm;
10048         MonoMarshalSpec **specs;
10049         MonoReflectionMethodAux *method_aux;
10050         MonoImage *image;
10051         gboolean dynamic;
10052         int i;
10053
10054         mono_error_init (&error);
10055         /*
10056          * Methods created using a MethodBuilder should have their memory allocated
10057          * inside the image mempool, while dynamic methods should have their memory
10058          * malloc'd.
10059          */
10060         dynamic = rmb->refs != NULL;
10061         image = dynamic ? NULL : klass->image;
10062
10063         if (!dynamic)
10064                 g_assert (!klass->generic_class);
10065
10066         mono_loader_lock ();
10067
10068         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10069                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10070                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10071         else
10072                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10073
10074         wrapperm = (MonoMethodWrapper*)m;
10075
10076         m->dynamic = dynamic;
10077         m->slot = -1;
10078         m->flags = rmb->attrs;
10079         m->iflags = rmb->iattrs;
10080         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10081         g_assert (mono_error_ok (&error));
10082         m->klass = klass;
10083         m->signature = sig;
10084         m->sre_method = TRUE;
10085         m->skip_visibility = rmb->skip_visibility;
10086         if (rmb->table_idx)
10087                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10088
10089         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10090                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10091                         m->string_ctor = 1;
10092
10093                 m->signature->pinvoke = 1;
10094         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10095                 m->signature->pinvoke = 1;
10096
10097                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10098
10099                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10100                 g_assert (mono_error_ok (&error));
10101                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10102                 g_assert (mono_error_ok (&error));
10103                 
10104                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10105
10106                 if (klass->image->dynamic)
10107                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10108
10109                 mono_loader_unlock ();
10110
10111                 return m;
10112         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10113                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10114                 MonoMethodHeader *header;
10115                 guint32 code_size;
10116                 gint32 max_stack, i;
10117                 gint32 num_locals = 0;
10118                 gint32 num_clauses = 0;
10119                 guint8 *code;
10120
10121                 if (rmb->ilgen) {
10122                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10123                         code_size = rmb->ilgen->code_len;
10124                         max_stack = rmb->ilgen->max_stack;
10125                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10126                         if (rmb->ilgen->ex_handlers)
10127                                 num_clauses = method_count_clauses (rmb->ilgen);
10128                 } else {
10129                         if (rmb->code) {
10130                                 code = mono_array_addr (rmb->code, guint8, 0);
10131                                 code_size = mono_array_length (rmb->code);
10132                                 /* we probably need to run a verifier on the code... */
10133                                 max_stack = 8; 
10134                         }
10135                         else {
10136                                 code = NULL;
10137                                 code_size = 0;
10138                                 max_stack = 8;
10139                         }
10140                 }
10141
10142                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10143                 header->code_size = code_size;
10144                 header->code = image_g_malloc (image, code_size);
10145                 memcpy ((char*)header->code, code, code_size);
10146                 header->max_stack = max_stack;
10147                 header->init_locals = rmb->init_locals;
10148                 header->num_locals = num_locals;
10149
10150                 for (i = 0; i < num_locals; ++i) {
10151                         MonoReflectionLocalBuilder *lb = 
10152                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10153
10154                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10155                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10156                 }
10157
10158                 header->num_clauses = num_clauses;
10159                 if (num_clauses) {
10160                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10161                                  rmb->ilgen, num_clauses);
10162                 }
10163
10164                 wrapperm->header = header;
10165         }
10166
10167         if (rmb->generic_params) {
10168                 int count = mono_array_length (rmb->generic_params);
10169                 MonoGenericContainer *container = rmb->generic_container;
10170
10171                 g_assert (container);
10172
10173                 container->type_argc = count;
10174                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10175                 container->owner.method = m;
10176
10177                 m->is_generic = TRUE;
10178                 mono_method_set_generic_container (m, container);
10179
10180                 for (i = 0; i < count; i++) {
10181                         MonoReflectionGenericParam *gp =
10182                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10183                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10184                         container->type_params [i] = *param;
10185                 }
10186
10187                 if (klass->generic_container) {
10188                         container->parent = klass->generic_container;
10189                         container->context.class_inst = klass->generic_container->context.class_inst;
10190                 }
10191                 container->context.method_inst = mono_get_shared_generic_inst (container);
10192         }
10193
10194         if (rmb->refs) {
10195                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10196                 int i;
10197                 void **data;
10198
10199                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10200
10201                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10202                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10203                 for (i = 0; i < rmb->nrefs; ++i)
10204                         data [i + 1] = rmb->refs [i];
10205         }
10206
10207         method_aux = NULL;
10208
10209         /* Parameter info */
10210         if (rmb->pinfo) {
10211                 if (!method_aux)
10212                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10213                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10214                 for (i = 0; i <= m->signature->param_count; ++i) {
10215                         MonoReflectionParamBuilder *pb;
10216                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10217                                 if ((i > 0) && (pb->attrs)) {
10218                                         /* Make a copy since it might point to a shared type structure */
10219                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10220                                         m->signature->params [i - 1]->attrs = pb->attrs;
10221                                 }
10222
10223                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10224                                         MonoDynamicImage *assembly;
10225                                         guint32 idx, def_type, len;
10226                                         char *p;
10227                                         const char *p2;
10228
10229                                         if (!method_aux->param_defaults) {
10230                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10231                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10232                                         }
10233                                         assembly = (MonoDynamicImage*)klass->image;
10234                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10235                                         /* Copy the data from the blob since it might get realloc-ed */
10236                                         p = assembly->blob.data + idx;
10237                                         len = mono_metadata_decode_blob_size (p, &p2);
10238                                         len += p2 - p;
10239                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10240                                         method_aux->param_default_types [i] = def_type;
10241                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10242                                 }
10243
10244                                 if (pb->name) {
10245                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10246                                         g_assert (mono_error_ok (&error));
10247                                 }
10248                                 if (pb->cattrs) {
10249                                         if (!method_aux->param_cattr)
10250                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10251                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10252                                 }
10253                         }
10254                 }
10255         }
10256
10257         /* Parameter marshalling */
10258         specs = NULL;
10259         if (rmb->pinfo)         
10260                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10261                         MonoReflectionParamBuilder *pb;
10262                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10263                                 if (pb->marshal_info) {
10264                                         if (specs == NULL)
10265                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10266                                         specs [pb->position] = 
10267                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10268                                 }
10269                         }
10270                 }
10271         if (specs != NULL) {
10272                 if (!method_aux)
10273                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10274                 method_aux->param_marshall = specs;
10275         }
10276
10277         if (klass->image->dynamic && method_aux)
10278                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10279
10280         mono_loader_unlock ();
10281
10282         return m;
10283 }       
10284
10285 static MonoMethod*
10286 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10287 {
10288         ReflectionMethodBuilder rmb;
10289         MonoMethodSignature *sig;
10290
10291         mono_loader_lock ();
10292         sig = ctor_builder_to_signature (klass->image, mb);
10293         mono_loader_unlock ();
10294
10295         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10296
10297         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10298         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10299
10300         /* If we are in a generic class, we might be called multiple times from inflate_method */
10301         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10302                 /* ilgen is no longer needed */
10303                 mb->ilgen = NULL;
10304         }
10305
10306         return mb->mhandle;
10307 }
10308
10309 static MonoMethod*
10310 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10311 {
10312         ReflectionMethodBuilder rmb;
10313         MonoMethodSignature *sig;
10314
10315         mono_loader_lock ();
10316         sig = method_builder_to_signature (klass->image, mb);
10317         mono_loader_unlock ();
10318
10319         reflection_methodbuilder_from_method_builder (&rmb, mb);
10320
10321         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10322         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10323
10324         /* If we are in a generic class, we might be called multiple times from inflate_method */
10325         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10326                 /* ilgen is no longer needed */
10327                 mb->ilgen = NULL;
10328         }
10329         return mb->mhandle;
10330 }
10331
10332 static MonoClassField*
10333 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10334 {
10335         MonoClassField *field;
10336         MonoType *custom;
10337
10338         field = g_new0 (MonoClassField, 1);
10339
10340         field->name = mono_string_to_utf8 (fb->name);
10341         if (fb->attrs || fb->modreq || fb->modopt) {
10342                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10343                 field->type->attrs = fb->attrs;
10344
10345                 g_assert (klass->image->dynamic);
10346                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10347                 g_free (field->type);
10348                 field->type = custom;
10349         } else {
10350                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10351         }
10352         if (fb->offset != -1)
10353                 field->offset = fb->offset;
10354         field->parent = klass;
10355         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10356
10357         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10358
10359         return field;
10360 }
10361 #endif
10362
10363 MonoType*
10364 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10365 {
10366         MonoClass *klass;
10367         MonoReflectionTypeBuilder *tb = NULL;
10368         gboolean is_dynamic = FALSE;
10369         MonoDomain *domain;
10370         MonoClass *geninst;
10371
10372         mono_loader_lock ();
10373
10374         domain = mono_object_domain (type);
10375
10376         if (is_sre_type_builder (mono_object_class (type))) {
10377                 tb = (MonoReflectionTypeBuilder *) type;
10378
10379                 is_dynamic = TRUE;
10380         } else if (is_sre_generic_instance (mono_object_class (type))) {
10381                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10382                 MonoReflectionType *gtd = rgi->generic_type;
10383
10384                 if (is_sre_type_builder (mono_object_class (gtd))) {
10385                         tb = (MonoReflectionTypeBuilder *)gtd;
10386                         is_dynamic = TRUE;
10387                 }
10388         }
10389
10390         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10391         if (tb && tb->generic_container)
10392                 mono_reflection_create_generic_class (tb);
10393
10394         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10395         if (!klass->generic_container) {
10396                 mono_loader_unlock ();
10397                 return NULL;
10398         }
10399
10400         if (klass->wastypebuilder) {
10401                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10402
10403                 is_dynamic = TRUE;
10404         }
10405
10406         mono_loader_unlock ();
10407
10408         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10409
10410         return &geninst->byval_arg;
10411 }
10412
10413 MonoClass*
10414 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10415 {
10416         MonoGenericClass *gclass;
10417         MonoGenericInst *inst;
10418
10419         g_assert (klass->generic_container);
10420
10421         inst = mono_metadata_get_generic_inst (type_argc, types);
10422         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10423
10424         return mono_generic_class_get_class (gclass);
10425 }
10426
10427 MonoReflectionMethod*
10428 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10429 {
10430         MonoClass *klass;
10431         MonoMethod *method, *inflated;
10432         MonoMethodInflated *imethod;
10433         MonoGenericContext tmp_context;
10434         MonoGenericInst *ginst;
10435         MonoType **type_argv;
10436         int count, i;
10437
10438         MONO_ARCH_SAVE_REGS;
10439
10440         /*FIXME but this no longer should happen*/
10441         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10442 #ifndef DISABLE_REFLECTION_EMIT
10443                 MonoReflectionMethodBuilder *mb = NULL;
10444                 MonoReflectionTypeBuilder *tb;
10445                 MonoClass *klass;
10446
10447                 mb = (MonoReflectionMethodBuilder *) rmethod;
10448                 tb = (MonoReflectionTypeBuilder *) mb->type;
10449                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10450
10451                 method = methodbuilder_to_mono_method (klass, mb);
10452 #else
10453                 g_assert_not_reached ();
10454                 method = NULL;
10455 #endif
10456         } else {
10457                 method = rmethod->method;
10458         }
10459
10460         klass = method->klass;
10461
10462         if (method->is_inflated)
10463                 method = ((MonoMethodInflated *) method)->declaring;
10464
10465         count = mono_method_signature (method)->generic_param_count;
10466         if (count != mono_array_length (types))
10467                 return NULL;
10468
10469         type_argv = g_new0 (MonoType *, count);
10470         for (i = 0; i < count; i++) {
10471                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10472                 type_argv [i] = mono_reflection_type_get_handle (garg);
10473         }
10474         ginst = mono_metadata_get_generic_inst (count, type_argv);
10475         g_free (type_argv);
10476
10477         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10478         tmp_context.method_inst = ginst;
10479
10480         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10481         imethod = (MonoMethodInflated *) inflated;
10482
10483         /*FIXME but I think this is no longer necessary*/
10484         if (method->klass->image->dynamic) {
10485                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10486                 /*
10487                  * This table maps metadata structures representing inflated methods/fields
10488                  * to the reflection objects representing their generic definitions.
10489                  */
10490                 mono_loader_lock ();
10491                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10492                 mono_loader_unlock ();
10493         }
10494         
10495         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10496 }
10497
10498 #ifndef DISABLE_REFLECTION_EMIT
10499
10500 static MonoMethod *
10501 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10502 {
10503         MonoMethodInflated *imethod;
10504         MonoGenericContext *context;
10505         int i;
10506
10507         /*
10508          * With generic code sharing the klass might not be inflated.
10509          * This can happen because classes inflated with their own
10510          * type arguments are "normalized" to the uninflated class.
10511          */
10512         if (!klass->generic_class)
10513                 return method;
10514
10515         context = mono_class_get_context (klass);
10516
10517         if (klass->method.count && klass->methods) {
10518                 /* Find the already created inflated method */
10519                 for (i = 0; i < klass->method.count; ++i) {
10520                         g_assert (klass->methods [i]->is_inflated);
10521                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10522                                 break;
10523                 }
10524                 g_assert (i < klass->method.count);
10525                 imethod = (MonoMethodInflated*)klass->methods [i];
10526         } else {
10527                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10528         }
10529
10530         if (method->is_generic && method->klass->image->dynamic) {
10531                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10532
10533                 mono_loader_lock ();
10534                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10535                 mono_loader_unlock ();
10536         }
10537         return (MonoMethod *) imethod;
10538 }
10539
10540 static MonoMethod *
10541 inflate_method (MonoReflectionType *type, MonoObject *obj)
10542 {
10543         MonoMethod *method;
10544         MonoClass *gklass;
10545
10546         MonoClass *type_class = mono_object_class (type);
10547
10548         if (is_sre_generic_instance (type_class)) {
10549                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10550                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10551         } else if (is_sre_type_builder (type_class)) {
10552                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10553         } else if (type->type) {
10554                 gklass = mono_class_from_mono_type (type->type);
10555                 gklass = mono_class_get_generic_type_definition (gklass);
10556         } else {
10557                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10558         }
10559
10560         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10561                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10562                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10563                 else
10564                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10565         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10566                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10567         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10568                 method = ((MonoReflectionMethod *) obj)->method;
10569         else {
10570                 method = NULL; /* prevent compiler warning */
10571                 g_error ("can't handle type %s", obj->vtable->klass->name);
10572         }
10573
10574         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10575 }
10576
10577 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10578 void
10579 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10580                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10581                                           MonoArray *events)
10582 {
10583         MonoGenericClass *gclass;
10584         MonoDynamicGenericClass *dgclass;
10585         MonoClass *klass, *gklass;
10586         MonoType *gtype;
10587         int i;
10588
10589         MONO_ARCH_SAVE_REGS;
10590
10591         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10592         klass = mono_class_from_mono_type (gtype);
10593         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10594         gclass = gtype->data.generic_class;
10595
10596         if (!gclass->is_dynamic)
10597                 return;
10598
10599         dgclass = (MonoDynamicGenericClass *) gclass;
10600
10601         if (dgclass->initialized)
10602                 return;
10603
10604         gklass = gclass->container_class;
10605         mono_class_init (gklass);
10606
10607         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10608         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10609         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10610
10611         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10612         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10613         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10614         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10615         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10616
10617         for (i = 0; i < dgclass->count_methods; i++) {
10618                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10619
10620                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10621         }
10622
10623         for (i = 0; i < dgclass->count_ctors; i++) {
10624                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10625
10626                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10627         }
10628
10629         for (i = 0; i < dgclass->count_fields; i++) {
10630                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10631                 MonoClassField *field, *inflated_field = NULL;
10632
10633                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10634                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10635                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10636                         field = ((MonoReflectionField *) obj)->field;
10637                 else {
10638                         field = NULL; /* prevent compiler warning */
10639                         g_assert_not_reached ();
10640                 }
10641
10642                 dgclass->fields [i] = *field;
10643                 dgclass->fields [i].parent = klass;
10644                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10645                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10646                 dgclass->field_generic_types [i] = field->type;
10647                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10648                 dgclass->field_objects [i] = obj;
10649
10650                 if (inflated_field) {
10651                         g_free (inflated_field);
10652                 } else {
10653                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10654                 }
10655         }
10656
10657         dgclass->initialized = TRUE;
10658 }
10659
10660 static void
10661 fix_partial_generic_class (MonoClass *klass)
10662 {
10663         MonoClass *gklass = klass->generic_class->container_class;
10664         MonoDynamicGenericClass *dgclass;
10665         int i;
10666
10667         if (klass->wastypebuilder)
10668                 return;
10669
10670         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10671         if (klass->parent != gklass->parent) {
10672                 MonoError error;
10673                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10674                 if (mono_error_ok (&error)) {
10675                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10676                         mono_metadata_free_type (parent_type);
10677                         if (parent != klass->parent) {
10678                                 /*fool mono_class_setup_parent*/
10679                                 klass->supertypes = NULL;
10680                                 mono_class_setup_parent (klass, parent);
10681                         }
10682                 } else {
10683                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10684                         mono_error_cleanup (&error);
10685                         if (gklass->wastypebuilder)
10686                                 klass->wastypebuilder = TRUE;
10687                         return;
10688                 }
10689         }
10690
10691         if (!dgclass->initialized)
10692                 return;
10693
10694         if (klass->method.count != gklass->method.count) {
10695                 klass->method.count = gklass->method.count;
10696                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10697
10698                 for (i = 0; i < klass->method.count; i++) {
10699                         klass->methods [i] = mono_class_inflate_generic_method_full (
10700                                 gklass->methods [i], klass, mono_class_get_context (klass));
10701                 }
10702         }
10703
10704         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10705                 klass->interface_count = gklass->interface_count;
10706                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10707                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10708
10709                 for (i = 0; i < gklass->interface_count; ++i) {
10710                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10711                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10712                         mono_metadata_free_type (iface_type);
10713
10714                         ensure_runtime_vtable (klass->interfaces [i]);
10715                 }
10716                 klass->interfaces_inited = 1;
10717         }
10718
10719         if (klass->field.count != gklass->field.count) {
10720                 klass->field.count = gklass->field.count;
10721                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10722
10723                 for (i = 0; i < klass->field.count; i++) {
10724                         klass->fields [i] = gklass->fields [i];
10725                         klass->fields [i].parent = klass;
10726                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10727                 }
10728         }
10729
10730         /*We can only finish with this klass once it's parent has as well*/
10731         if (gklass->wastypebuilder)
10732                 klass->wastypebuilder = TRUE;
10733         return;
10734 }
10735
10736 static void
10737 ensure_generic_class_runtime_vtable (MonoClass *klass)
10738 {
10739         MonoClass *gklass = klass->generic_class->container_class;
10740
10741         ensure_runtime_vtable (gklass); 
10742
10743         fix_partial_generic_class (klass);
10744 }
10745
10746 static void
10747 ensure_runtime_vtable (MonoClass *klass)
10748 {
10749         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10750         int i, num, j;
10751
10752         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10753                 return;
10754         if (klass->parent)
10755                 ensure_runtime_vtable (klass->parent);
10756
10757         if (tb) {
10758                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10759                 num += tb->num_methods;
10760                 klass->method.count = num;
10761                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10762                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10763                 for (i = 0; i < num; ++i)
10764                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10765                 num = tb->num_methods;
10766                 j = i;
10767                 for (i = 0; i < num; ++i)
10768                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10769         
10770                 if (tb->interfaces) {
10771                         klass->interface_count = mono_array_length (tb->interfaces);
10772                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10773                         for (i = 0; i < klass->interface_count; ++i) {
10774                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10775                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10776                                 ensure_runtime_vtable (klass->interfaces [i]);
10777                         }
10778                         klass->interfaces_inited = 1;
10779                 }
10780         } else if (klass->generic_class){
10781                 ensure_generic_class_runtime_vtable (klass);
10782         }
10783
10784         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10785                 for (i = 0; i < klass->method.count; ++i)
10786                         klass->methods [i]->slot = i;
10787                 
10788                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10789                 mono_class_setup_interface_offsets (klass);
10790                 mono_class_setup_interface_id (klass);
10791         }
10792
10793         /*
10794          * The generic vtable is needed even if image->run is not set since some
10795          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10796          * method->slot being defined.
10797          */
10798
10799         /* 
10800          * tb->methods could not be freed since it is used for determining 
10801          * overrides during dynamic vtable construction.
10802          */
10803 }
10804
10805 static MonoMethod*
10806 mono_reflection_method_get_handle (MonoObject *method)
10807 {
10808         MonoClass *class = mono_object_class (method);
10809         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10810                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10811                 return sr_method->method;
10812         }
10813         if (is_sre_method_builder (class)) {
10814                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10815                 return mb->mhandle;
10816         }
10817         if (is_sre_method_on_tb_inst (class)) {
10818                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10819                 MonoMethod *result;
10820                 /*FIXME move this to a proper method and unify with resolve_object*/
10821                 if (m->method_args) {
10822                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10823                 } else {
10824                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10825                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10826                         MonoMethod *mono_method;
10827
10828                         if (is_sre_method_builder (mono_object_class (m->mb)))
10829                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10830                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10831                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10832                         else
10833                                 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)));
10834
10835                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10836                 }
10837                 return result;
10838         }
10839
10840         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10841         return NULL;
10842 }
10843
10844 void
10845 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10846 {
10847         MonoReflectionTypeBuilder *tb;
10848         int i, onum;
10849
10850         *overrides = NULL;
10851         *num_overrides = 0;
10852
10853         g_assert (klass->image->dynamic);
10854
10855         if (!mono_class_get_ref_info (klass))
10856                 return;
10857
10858         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10859
10860         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10861
10862         onum = 0;
10863         if (tb->methods) {
10864                 for (i = 0; i < tb->num_methods; ++i) {
10865                         MonoReflectionMethodBuilder *mb = 
10866                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10867                         if (mb->override_method)
10868                                 onum ++;
10869                 }
10870         }
10871
10872         if (onum) {
10873                 *overrides = g_new0 (MonoMethod*, onum * 2);
10874
10875                 onum = 0;
10876                 for (i = 0; i < tb->num_methods; ++i) {
10877                         MonoReflectionMethodBuilder *mb = 
10878                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10879                         if (mb->override_method) {
10880                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10881                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10882
10883                                 g_assert (mb->mhandle);
10884
10885                                 onum ++;
10886                         }
10887                 }
10888         }
10889
10890         *num_overrides = onum;
10891 }
10892
10893 static void
10894 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10895 {
10896         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10897         MonoReflectionFieldBuilder *fb;
10898         MonoClassField *field;
10899         MonoImage *image = klass->image;
10900         const char *p, *p2;
10901         int i;
10902         guint32 len, idx, real_size = 0;
10903
10904         klass->field.count = tb->num_fields;
10905         klass->field.first = 0;
10906
10907         mono_error_init (error);
10908
10909         if (tb->class_size) {
10910                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10911                 klass->packing_size = tb->packing_size;
10912                 real_size = klass->instance_size + tb->class_size;
10913         }
10914
10915         if (!klass->field.count) {
10916                 klass->instance_size = MAX (klass->instance_size, real_size);
10917                 return;
10918         }
10919         
10920         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10921         mono_class_alloc_ext (klass);
10922         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10923         /*
10924         This is, guess what, a hack.
10925         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10926         On the static path no field class is resolved, only types are built. This is the right thing to do
10927         but we suck.
10928         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10929         */
10930         klass->size_inited = 1;
10931
10932         for (i = 0; i < klass->field.count; ++i) {
10933                 fb = mono_array_get (tb->fields, gpointer, i);
10934                 field = &klass->fields [i];
10935                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10936                 if (!mono_error_ok (error))
10937                         return;
10938                 if (fb->attrs) {
10939                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10940                         field->type->attrs = fb->attrs;
10941                 } else {
10942                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10943                 }
10944                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10945                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10946                 if (fb->offset != -1)
10947                         field->offset = fb->offset;
10948                 field->parent = klass;
10949                 fb->handle = field;
10950                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10951
10952                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10953                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10954                 }
10955                 if (fb->def_value) {
10956                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10957                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10958                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10959                         /* Copy the data from the blob since it might get realloc-ed */
10960                         p = assembly->blob.data + idx;
10961                         len = mono_metadata_decode_blob_size (p, &p2);
10962                         len += p2 - p;
10963                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10964                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10965                 }
10966         }
10967
10968         klass->instance_size = MAX (klass->instance_size, real_size);
10969         mono_class_layout_fields (klass);
10970 }
10971
10972 static void
10973 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10974 {
10975         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10976         MonoReflectionPropertyBuilder *pb;
10977         MonoImage *image = klass->image;
10978         MonoProperty *properties;
10979         int i;
10980
10981         mono_error_init (error);
10982
10983         if (!klass->ext)
10984                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10985
10986         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10987         klass->ext->property.first = 0;
10988
10989         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10990         klass->ext->properties = properties;
10991         for (i = 0; i < klass->ext->property.count; ++i) {
10992                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10993                 properties [i].parent = klass;
10994                 properties [i].attrs = pb->attrs;
10995                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10996                 if (!mono_error_ok (error))
10997                         return;
10998                 if (pb->get_method)
10999                         properties [i].get = pb->get_method->mhandle;
11000                 if (pb->set_method)
11001                         properties [i].set = pb->set_method->mhandle;
11002
11003                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11004                 if (pb->def_value) {
11005                         guint32 len, idx;
11006                         const char *p, *p2;
11007                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11008                         if (!klass->ext->prop_def_values)
11009                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11010                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11011                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11012                         /* Copy the data from the blob since it might get realloc-ed */
11013                         p = assembly->blob.data + idx;
11014                         len = mono_metadata_decode_blob_size (p, &p2);
11015                         len += p2 - p;
11016                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11017                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11018                 }
11019         }
11020 }
11021
11022 MonoReflectionEvent *
11023 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11024 {
11025         MonoEvent *event = g_new0 (MonoEvent, 1);
11026         MonoClass *klass;
11027
11028         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11029
11030         event->parent = klass;
11031         event->attrs = eb->attrs;
11032         event->name = mono_string_to_utf8 (eb->name);
11033         if (eb->add_method)
11034                 event->add = eb->add_method->mhandle;
11035         if (eb->remove_method)
11036                 event->remove = eb->remove_method->mhandle;
11037         if (eb->raise_method)
11038                 event->raise = eb->raise_method->mhandle;
11039
11040 #ifndef MONO_SMALL_CONFIG
11041         if (eb->other_methods) {
11042                 int j;
11043                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11044                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11045                         MonoReflectionMethodBuilder *mb = 
11046                                 mono_array_get (eb->other_methods,
11047                                                 MonoReflectionMethodBuilder*, j);
11048                         event->other [j] = mb->mhandle;
11049                 }
11050         }
11051 #endif
11052
11053         return mono_event_get_object (mono_object_domain (tb), klass, event);
11054 }
11055
11056 static void
11057 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11058 {
11059         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11060         MonoReflectionEventBuilder *eb;
11061         MonoImage *image = klass->image;
11062         MonoEvent *events;
11063         int i;
11064
11065         mono_error_init (error);
11066
11067         if (!klass->ext)
11068                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11069
11070         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11071         klass->ext->event.first = 0;
11072
11073         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11074         klass->ext->events = events;
11075         for (i = 0; i < klass->ext->event.count; ++i) {
11076                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11077                 events [i].parent = klass;
11078                 events [i].attrs = eb->attrs;
11079                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11080                 if (!mono_error_ok (error))
11081                         return;
11082                 if (eb->add_method)
11083                         events [i].add = eb->add_method->mhandle;
11084                 if (eb->remove_method)
11085                         events [i].remove = eb->remove_method->mhandle;
11086                 if (eb->raise_method)
11087                         events [i].raise = eb->raise_method->mhandle;
11088
11089 #ifndef MONO_SMALL_CONFIG
11090                 if (eb->other_methods) {
11091                         int j;
11092                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11093                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11094                                 MonoReflectionMethodBuilder *mb = 
11095                                         mono_array_get (eb->other_methods,
11096                                                                         MonoReflectionMethodBuilder*, j);
11097                                 events [i].other [j] = mb->mhandle;
11098                         }
11099                 }
11100 #endif
11101                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11102         }
11103 }
11104
11105 static gboolean
11106 remove_instantiations_of_and_ensure_contents (gpointer key,
11107                                                   gpointer value,
11108                                                   gpointer user_data)
11109 {
11110         MonoType *type = (MonoType*)key;
11111         MonoClass *klass = (MonoClass*)user_data;
11112
11113         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11114                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11115                 return TRUE;
11116         } else
11117                 return FALSE;
11118 }
11119
11120 static void
11121 check_array_for_usertypes (MonoArray *arr)
11122 {
11123         int i;
11124
11125         if (!arr)
11126                 return;
11127
11128         for (i = 0; i < mono_array_length (arr); ++i)
11129                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11130 }
11131
11132 MonoReflectionType*
11133 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11134 {
11135         MonoError error;
11136         MonoClass *klass;
11137         MonoDomain* domain;
11138         MonoReflectionType* res;
11139         int i, j;
11140
11141         MONO_ARCH_SAVE_REGS;
11142
11143         domain = mono_object_domain (tb);
11144         klass = mono_class_from_mono_type (tb->type.type);
11145
11146         /*
11147          * Check for user defined Type subclasses.
11148          */
11149         RESOLVE_TYPE (tb->parent);
11150         check_array_for_usertypes (tb->interfaces);
11151         if (tb->fields) {
11152                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11153                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11154                         if (fb) {
11155                                 RESOLVE_TYPE (fb->type);
11156                                 check_array_for_usertypes (fb->modreq);
11157                                 check_array_for_usertypes (fb->modopt);
11158                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11159                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11160                         }
11161                 }
11162         }
11163         if (tb->methods) {
11164                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11165                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11166                         if (mb) {
11167                                 RESOLVE_TYPE (mb->rtype);
11168                                 check_array_for_usertypes (mb->return_modreq);
11169                                 check_array_for_usertypes (mb->return_modopt);
11170                                 check_array_for_usertypes (mb->parameters);
11171                                 if (mb->param_modreq)
11172                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11173                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11174                                 if (mb->param_modopt)
11175                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11176                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11177                         }
11178                 }
11179         }
11180         if (tb->ctors) {
11181                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11182                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11183                         if (mb) {
11184                                 check_array_for_usertypes (mb->parameters);
11185                                 if (mb->param_modreq)
11186                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11187                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11188                                 if (mb->param_modopt)
11189                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11190                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11191                         }
11192                 }
11193         }
11194
11195         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11196
11197         /* 
11198          * we need to lock the domain because the lock will be taken inside
11199          * So, we need to keep the locking order correct.
11200          */
11201         mono_loader_lock ();
11202         mono_domain_lock (domain);
11203         if (klass->wastypebuilder) {
11204                 mono_domain_unlock (domain);
11205                 mono_loader_unlock ();
11206                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11207         }
11208         /*
11209          * Fields to set in klass:
11210          * the various flags: delegate/unicode/contextbound etc.
11211          */
11212         klass->flags = tb->attrs;
11213         klass->has_cctor = 1;
11214         klass->has_finalize = 1;
11215
11216         /* fool mono_class_setup_parent */
11217         klass->supertypes = NULL;
11218         mono_class_setup_parent (klass, klass->parent);
11219         mono_class_setup_mono_type (klass);
11220
11221 #if 0
11222         if (!((MonoDynamicImage*)klass->image)->run) {
11223                 if (klass->generic_container) {
11224                         /* FIXME: The code below can't handle generic classes */
11225                         klass->wastypebuilder = TRUE;
11226                         mono_loader_unlock ();
11227                         mono_domain_unlock (domain);
11228                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11229                 }
11230         }
11231 #endif
11232
11233         /* enums are done right away */
11234         if (!klass->enumtype)
11235                 ensure_runtime_vtable (klass);
11236
11237         if (tb->subtypes) {
11238                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11239                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11240                         mono_class_alloc_ext (klass);
11241                         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)));
11242                 }
11243         }
11244
11245         klass->nested_classes_inited = TRUE;
11246
11247         /* fields and object layout */
11248         if (klass->parent) {
11249                 if (!klass->parent->size_inited)
11250                         mono_class_init (klass->parent);
11251                 klass->instance_size = klass->parent->instance_size;
11252                 klass->sizes.class_size = 0;
11253                 klass->min_align = klass->parent->min_align;
11254                 /* if the type has no fields we won't call the field_setup
11255                  * routine which sets up klass->has_references.
11256                  */
11257                 klass->has_references |= klass->parent->has_references;
11258         } else {
11259                 klass->instance_size = sizeof (MonoObject);
11260                 klass->min_align = 1;
11261         }
11262
11263         /* FIXME: handle packing_size and instance_size */
11264         typebuilder_setup_fields (klass, &error);
11265         if (!mono_error_ok (&error))
11266                 goto failure;
11267         typebuilder_setup_properties (klass, &error);
11268         if (!mono_error_ok (&error))
11269                 goto failure;
11270
11271         typebuilder_setup_events (klass, &error);
11272         if (!mono_error_ok (&error))
11273                 goto failure;
11274
11275         klass->wastypebuilder = TRUE;
11276
11277         /* 
11278          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11279          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11280          * we want to return normal System.MonoType objects, so clear these out from the cache.
11281          *
11282          * Together with this we must ensure the contents of all instances to match the created type.
11283          */
11284         if (domain->type_hash && klass->generic_container)
11285                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11286
11287         mono_domain_unlock (domain);
11288         mono_loader_unlock ();
11289
11290         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11291                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11292                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11293         }
11294
11295         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11296         g_assert (res != (MonoReflectionType*)tb);
11297
11298         return res;
11299
11300 failure:
11301         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11302         klass->wastypebuilder = TRUE;
11303         mono_domain_unlock (domain);
11304         mono_loader_unlock ();
11305         mono_error_raise_exception (&error);
11306         return NULL;
11307 }
11308
11309 void
11310 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11311 {
11312         MonoGenericParamFull *param;
11313         MonoImage *image;
11314         MonoClass *pklass;
11315
11316         MONO_ARCH_SAVE_REGS;
11317
11318         param = g_new0 (MonoGenericParamFull, 1);
11319
11320         if (gparam->mbuilder) {
11321                 if (!gparam->mbuilder->generic_container) {
11322                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11323                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11324                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11325                         gparam->mbuilder->generic_container->is_method = TRUE;
11326                         /* 
11327                          * Cannot set owner.method, since the MonoMethod is not created yet.
11328                          * Set the image field instead, so type_in_image () works.
11329                          */
11330                         gparam->mbuilder->generic_container->image = klass->image;
11331                 }
11332                 param->param.owner = gparam->mbuilder->generic_container;
11333         } else if (gparam->tbuilder) {
11334                 if (!gparam->tbuilder->generic_container) {
11335                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11336                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11337                         gparam->tbuilder->generic_container->owner.klass = klass;
11338                 }
11339                 param->param.owner = gparam->tbuilder->generic_container;
11340         }
11341
11342         param->info.name = mono_string_to_utf8 (gparam->name);
11343         param->param.num = gparam->index;
11344
11345         image = &gparam->tbuilder->module->dynamic_image->image;
11346         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11347
11348         gparam->type.type = &pklass->byval_arg;
11349
11350         mono_class_set_ref_info (pklass, gparam);
11351         mono_image_lock (image);
11352         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11353         mono_image_unlock (image);
11354 }
11355
11356 MonoArray *
11357 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11358 {
11359         MonoReflectionModuleBuilder *module = sig->module;
11360         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11361         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11362         guint32 buflen, i;
11363         MonoArray *result;
11364         SigBuffer buf;
11365
11366         check_array_for_usertypes (sig->arguments);
11367
11368         sigbuffer_init (&buf, 32);
11369
11370         sigbuffer_add_value (&buf, 0x07);
11371         sigbuffer_add_value (&buf, na);
11372         if (assembly != NULL){
11373                 for (i = 0; i < na; ++i) {
11374                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11375                         encode_reflection_type (assembly, type, &buf);
11376                 }
11377         }
11378
11379         buflen = buf.p - buf.buf;
11380         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11381         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11382         sigbuffer_free (&buf);
11383
11384         return result;
11385 }
11386
11387 MonoArray *
11388 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11389 {
11390         MonoDynamicImage *assembly = sig->module->dynamic_image;
11391         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11392         guint32 buflen, i;
11393         MonoArray *result;
11394         SigBuffer buf;
11395
11396         check_array_for_usertypes (sig->arguments);
11397
11398         sigbuffer_init (&buf, 32);
11399
11400         sigbuffer_add_value (&buf, 0x06);
11401         for (i = 0; i < na; ++i) {
11402                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11403                 encode_reflection_type (assembly, type, &buf);
11404         }
11405
11406         buflen = buf.p - buf.buf;
11407         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11408         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11409         sigbuffer_free (&buf);
11410
11411         return result;
11412 }
11413
11414 void 
11415 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11416 {
11417         ReflectionMethodBuilder rmb;
11418         MonoMethodSignature *sig;
11419         MonoClass *klass;
11420         GSList *l;
11421         int i;
11422
11423         sig = dynamic_method_to_signature (mb);
11424
11425         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11426
11427         /*
11428          * Resolve references.
11429          */
11430         /* 
11431          * Every second entry in the refs array is reserved for storing handle_class,
11432          * which is needed by the ldtoken implementation in the JIT.
11433          */
11434         rmb.nrefs = mb->nrefs;
11435         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11436         for (i = 0; i < mb->nrefs; i += 2) {
11437                 MonoClass *handle_class;
11438                 gpointer ref;
11439                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11440
11441                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11442                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11443                         /*
11444                          * The referenced DynamicMethod should already be created by the managed
11445                          * code, except in the case of circular references. In that case, we store
11446                          * method in the refs array, and fix it up later when the referenced 
11447                          * DynamicMethod is created.
11448                          */
11449                         if (method->mhandle) {
11450                                 ref = method->mhandle;
11451                         } else {
11452                                 /* FIXME: GC object stored in unmanaged memory */
11453                                 ref = method;
11454
11455                                 /* FIXME: GC object stored in unmanaged memory */
11456                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11457                         }
11458                         handle_class = mono_defaults.methodhandle_class;
11459                 } else {
11460                         MonoException *ex = NULL;
11461                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11462                         if (!ref)
11463                                 ex = mono_get_exception_type_load (NULL, NULL);
11464                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11465                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11466
11467                         if (ex) {
11468                                 g_free (rmb.refs);
11469                                 mono_raise_exception (ex);
11470                                 return;
11471                         }
11472                 }
11473
11474                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11475                 rmb.refs [i + 1] = handle_class;
11476         }               
11477
11478         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11479
11480         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11481
11482         /* Fix up refs entries pointing at us */
11483         for (l = mb->referenced_by; l; l = l->next) {
11484                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11485                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11486                 gpointer *data;
11487                 
11488                 g_assert (method->mhandle);
11489
11490                 data = (gpointer*)wrapper->method_data;
11491                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11492                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11493                                 data [i + 1] = mb->mhandle;
11494                 }
11495         }
11496         g_slist_free (mb->referenced_by);
11497
11498         g_free (rmb.refs);
11499
11500         /* ilgen is no longer needed */
11501         mb->ilgen = NULL;
11502 }
11503
11504 #endif /* DISABLE_REFLECTION_EMIT */
11505
11506 void
11507 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11508 {
11509         g_assert (mb);
11510
11511         if (mb->mhandle)
11512                 mono_runtime_free_method (
11513                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11514 }
11515
11516 /**
11517  * 
11518  * mono_reflection_is_valid_dynamic_token:
11519  * 
11520  * Returns TRUE if token is valid.
11521  * 
11522  */
11523 gboolean
11524 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11525 {
11526         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11527 }
11528
11529 #ifndef DISABLE_REFLECTION_EMIT
11530
11531 /**
11532  * mono_reflection_lookup_dynamic_token:
11533  *
11534  * Finish the Builder object pointed to by TOKEN and return the corresponding
11535  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11536  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11537  * mapping table.
11538  *
11539  * LOCKING: Take the loader lock
11540  */
11541 gpointer
11542 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11543 {
11544         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11545         MonoObject *obj;
11546         MonoClass *klass;
11547
11548         mono_loader_lock ();
11549         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11550         mono_loader_unlock ();
11551         if (!obj) {
11552                 if (valid_token)
11553                         g_error ("Could not find required dynamic token 0x%08x", token);
11554                 else
11555                         return NULL;
11556         }
11557
11558         if (!handle_class)
11559                 handle_class = &klass;
11560         return resolve_object (image, obj, handle_class, context);
11561 }
11562
11563 MonoMethodSignature *
11564 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11565 {
11566         MonoMethodSignature *sig;
11567         g_assert (image->dynamic);
11568
11569         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11570         if (sig)
11571                 return sig;
11572
11573         return mono_method_signature (method);
11574 }
11575
11576 /*
11577  * ensure_complete_type:
11578  *
11579  *   Ensure that KLASS is completed if it is a dynamic type, or references
11580  * dynamic types.
11581  */
11582 static void
11583 ensure_complete_type (MonoClass *klass)
11584 {
11585         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11586                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11587
11588                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11589
11590                 // Asserting here could break a lot of code
11591                 //g_assert (klass->wastypebuilder);
11592         }
11593
11594         if (klass->generic_class) {
11595                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11596                 int i;
11597
11598                 for (i = 0; i < inst->type_argc; ++i) {
11599                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11600                 }
11601         }
11602 }
11603
11604 static gpointer
11605 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11606 {
11607         gpointer result = NULL;
11608
11609         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11610                 result = mono_string_intern ((MonoString*)obj);
11611                 *handle_class = mono_defaults.string_class;
11612                 g_assert (result);
11613         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11614                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11615                 MonoClass *mc = mono_class_from_mono_type (type);
11616                 if (!mono_class_init (mc))
11617                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11618
11619                 if (context) {
11620                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11621                         result = mono_class_from_mono_type (inflated);
11622                         mono_metadata_free_type (inflated);
11623                 } else {
11624                         result = mono_class_from_mono_type (type);
11625                 }
11626                 *handle_class = mono_defaults.typehandle_class;
11627                 g_assert (result);
11628         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11629                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11630                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11631                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11632                 result = ((MonoReflectionMethod*)obj)->method;
11633                 if (context)
11634                         result = mono_class_inflate_generic_method (result, context);
11635                 *handle_class = mono_defaults.methodhandle_class;
11636                 g_assert (result);
11637         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11638                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11639                 result = mb->mhandle;
11640                 if (!result) {
11641                         /* Type is not yet created */
11642                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11643
11644                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11645
11646                         /*
11647                          * Hopefully this has been filled in by calling CreateType() on the
11648                          * TypeBuilder.
11649                          */
11650                         /*
11651                          * TODO: This won't work if the application finishes another 
11652                          * TypeBuilder instance instead of this one.
11653                          */
11654                         result = mb->mhandle;
11655                 }
11656                 if (context)
11657                         result = mono_class_inflate_generic_method (result, context);
11658                 *handle_class = mono_defaults.methodhandle_class;
11659         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11660                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11661
11662                 result = cb->mhandle;
11663                 if (!result) {
11664                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11665
11666                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11667                         result = cb->mhandle;
11668                 }
11669                 if (context)
11670                         result = mono_class_inflate_generic_method (result, context);
11671                 *handle_class = mono_defaults.methodhandle_class;
11672         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11673                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11674
11675                 ensure_complete_type (field->parent);
11676                 if (context) {
11677                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11678                         MonoClass *class = mono_class_from_mono_type (inflated);
11679                         MonoClassField *inflated_field;
11680                         gpointer iter = NULL;
11681                         mono_metadata_free_type (inflated);
11682                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11683                                 if (!strcmp (field->name, inflated_field->name))
11684                                         break;
11685                         }
11686                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11687                         result = inflated_field;
11688                 } else {
11689                         result = field;
11690                 }
11691                 *handle_class = mono_defaults.fieldhandle_class;
11692                 g_assert (result);
11693         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11694                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11695                 result = fb->handle;
11696
11697                 if (!result) {
11698                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11699
11700                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11701                         result = fb->handle;
11702                 }
11703
11704                 if (fb->handle && fb->handle->parent->generic_container) {
11705                         MonoClass *klass = fb->handle->parent;
11706                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11707                         MonoClass *inflated = mono_class_from_mono_type (type);
11708
11709                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11710                         g_assert (result);
11711                         mono_metadata_free_type (type);
11712                 }
11713                 *handle_class = mono_defaults.fieldhandle_class;
11714         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11715                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11716                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11717                 MonoClass *klass;
11718
11719                 klass = type->data.klass;
11720                 if (klass->wastypebuilder) {
11721                         /* Already created */
11722                         result = klass;
11723                 }
11724                 else {
11725                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11726                         result = type->data.klass;
11727                         g_assert (result);
11728                 }
11729                 *handle_class = mono_defaults.typehandle_class;
11730         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11731                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11732                 MonoMethodSignature *sig;
11733                 int nargs, i;
11734
11735                 if (helper->arguments)
11736                         nargs = mono_array_length (helper->arguments);
11737                 else
11738                         nargs = 0;
11739
11740                 sig = mono_metadata_signature_alloc (image, nargs);
11741                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11742                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11743
11744                 if (helper->unmanaged_call_conv) { /* unmanaged */
11745                         sig->call_convention = helper->unmanaged_call_conv - 1;
11746                         sig->pinvoke = TRUE;
11747                 } else if (helper->call_conv & 0x02) {
11748                         sig->call_convention = MONO_CALL_VARARG;
11749                 } else {
11750                         sig->call_convention = MONO_CALL_DEFAULT;
11751                 }
11752
11753                 sig->param_count = nargs;
11754                 /* TODO: Copy type ? */
11755                 sig->ret = helper->return_type->type;
11756                 for (i = 0; i < nargs; ++i)
11757                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11758
11759                 result = sig;
11760                 *handle_class = NULL;
11761         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11762                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11763                 /* Already created by the managed code */
11764                 g_assert (method->mhandle);
11765                 result = method->mhandle;
11766                 *handle_class = mono_defaults.methodhandle_class;
11767         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11768                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11769                 type = mono_class_inflate_generic_type (type, context);
11770                 result = mono_class_from_mono_type (type);
11771                 *handle_class = mono_defaults.typehandle_class;
11772                 g_assert (result);
11773                 mono_metadata_free_type (type);
11774         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11775                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11776                 type = mono_class_inflate_generic_type (type, context);
11777                 result = mono_class_from_mono_type (type);
11778                 *handle_class = mono_defaults.typehandle_class;
11779                 g_assert (result);
11780                 mono_metadata_free_type (type);
11781         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11782                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11783                 MonoClass *inflated;
11784                 MonoType *type;
11785                 MonoClassField *field;
11786
11787                 if (is_sre_field_builder (mono_object_class (f->fb)))
11788                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11789                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11790                         field = ((MonoReflectionField*)f->fb)->field;
11791                 else
11792                         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)));
11793
11794                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11795                 inflated = mono_class_from_mono_type (type);
11796
11797                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11798                 ensure_complete_type (field->parent);
11799                 g_assert (result);
11800                 mono_metadata_free_type (type);
11801                 *handle_class = mono_defaults.fieldhandle_class;
11802         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11803                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11804                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11805                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11806                 MonoMethod *method;
11807
11808                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11809                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11810                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11811                         method = ((MonoReflectionMethod *)c->cb)->method;
11812                 else
11813                         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)));
11814
11815                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11816                 *handle_class = mono_defaults.methodhandle_class;
11817                 mono_metadata_free_type (type);
11818         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11819                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11820                 if (m->method_args) {
11821                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11822                         if (context)
11823                                 result = mono_class_inflate_generic_method (result, context);
11824                 } else {
11825                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11826                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11827                         MonoMethod *method;
11828
11829                         if (is_sre_method_builder (mono_object_class (m->mb)))
11830                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11831                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11832                                 method = ((MonoReflectionMethod *)m->mb)->method;
11833                         else
11834                                 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)));
11835
11836                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11837                         mono_metadata_free_type (type);
11838                 }
11839                 *handle_class = mono_defaults.methodhandle_class;
11840         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11841                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11842                 MonoType *mtype;
11843                 MonoClass *klass;
11844                 MonoMethod *method;
11845                 gpointer iter;
11846                 char *name;
11847
11848                 mtype = mono_reflection_type_get_handle (m->parent);
11849                 klass = mono_class_from_mono_type (mtype);
11850
11851                 /* Find the method */
11852
11853                 name = mono_string_to_utf8 (m->name);
11854                 iter = NULL;
11855                 while ((method = mono_class_get_methods (klass, &iter))) {
11856                         if (!strcmp (method->name, name))
11857                                 break;
11858                 }
11859                 g_free (name);
11860
11861                 // FIXME:
11862                 g_assert (method);
11863                 // FIXME: Check parameters/return value etc. match
11864
11865                 result = method;
11866                 *handle_class = mono_defaults.methodhandle_class;
11867         } else if (is_sre_array (mono_object_get_class(obj)) ||
11868                                 is_sre_byref (mono_object_get_class(obj)) ||
11869                                 is_sre_pointer (mono_object_get_class(obj))) {
11870                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11871                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11872                 result = mono_class_from_mono_type (type);
11873                 *handle_class = mono_defaults.typehandle_class;
11874         } else {
11875                 g_print ("%s\n", obj->vtable->klass->name);
11876                 g_assert_not_reached ();
11877         }
11878         return result;
11879 }
11880
11881 #else /* DISABLE_REFLECTION_EMIT */
11882
11883 MonoArray*
11884 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11885 {
11886         g_assert_not_reached ();
11887         return NULL;
11888 }
11889
11890 void
11891 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11892 {
11893         g_assert_not_reached ();
11894 }
11895
11896 void
11897 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11898 {
11899         g_assert_not_reached ();
11900 }
11901
11902 void
11903 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11904 {
11905         g_assert_not_reached ();
11906 }
11907
11908 void
11909 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11910 {
11911         g_assert_not_reached ();
11912 }
11913
11914 void
11915 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11916 {
11917         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11918 }
11919
11920 void
11921 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11922 {
11923         g_assert_not_reached ();
11924 }
11925
11926 void
11927 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11928 {
11929         g_assert_not_reached ();
11930 }
11931
11932 MonoReflectionModule *
11933 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11934 {
11935         g_assert_not_reached ();
11936         return NULL;
11937 }
11938
11939 guint32
11940 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11941 {
11942         g_assert_not_reached ();
11943         return 0;
11944 }
11945
11946 guint32
11947 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11948 {
11949         g_assert_not_reached ();
11950         return 0;
11951 }
11952
11953 guint32
11954 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11955                                                  gboolean create_methodspec, gboolean register_token)
11956 {
11957         g_assert_not_reached ();
11958         return 0;
11959 }
11960
11961 void
11962 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11963 {
11964 }
11965
11966 void
11967 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11968                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11969                                           MonoArray *events)
11970 {
11971         g_assert_not_reached ();
11972 }
11973
11974 void
11975 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11976 {
11977         *overrides = NULL;
11978         *num_overrides = 0;
11979 }
11980
11981 MonoReflectionEvent *
11982 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11983 {
11984         g_assert_not_reached ();
11985         return NULL;
11986 }
11987
11988 MonoReflectionType*
11989 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11990 {
11991         g_assert_not_reached ();
11992         return NULL;
11993 }
11994
11995 void
11996 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11997 {
11998         g_assert_not_reached ();
11999 }
12000
12001 MonoArray *
12002 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12003 {
12004         g_assert_not_reached ();
12005         return NULL;
12006 }
12007
12008 MonoArray *
12009 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12010 {
12011         g_assert_not_reached ();
12012         return NULL;
12013 }
12014
12015 void 
12016 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12017 {
12018 }
12019
12020 gpointer
12021 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12022 {
12023         return NULL;
12024 }
12025
12026 MonoType*
12027 mono_reflection_type_get_handle (MonoReflectionType* ref)
12028 {
12029         if (!ref)
12030                 return NULL;
12031         return ref->type;
12032 }
12033
12034 #endif /* DISABLE_REFLECTION_EMIT */
12035
12036 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12037 const static guint32 declsec_flags_map[] = {
12038         0x00000000,                                     /* empty */
12039         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12040         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12041         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12042         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12043         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12044         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12045         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12046         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12047         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12048         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12049         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12050         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12051         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12052         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12053         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12054         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12055         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12056         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12057 };
12058
12059 /*
12060  * Returns flags that includes all available security action associated to the handle.
12061  * @token: metadata token (either for a class or a method)
12062  * @image: image where resides the metadata.
12063  */
12064 static guint32
12065 mono_declsec_get_flags (MonoImage *image, guint32 token)
12066 {
12067         int index = mono_metadata_declsec_from_index (image, token);
12068         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12069         guint32 result = 0;
12070         guint32 action;
12071         int i;
12072
12073         /* HasSecurity can be present for other, not specially encoded, attributes,
12074            e.g. SuppressUnmanagedCodeSecurityAttribute */
12075         if (index < 0)
12076                 return 0;
12077
12078         for (i = index; i < t->rows; i++) {
12079                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12080
12081                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12082                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12083                         break;
12084
12085                 action = cols [MONO_DECL_SECURITY_ACTION];
12086                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12087                         result |= declsec_flags_map [action];
12088                 } else {
12089                         g_assert_not_reached ();
12090                 }
12091         }
12092         return result;
12093 }
12094
12095 /*
12096  * Get the security actions (in the form of flags) associated with the specified method.
12097  *
12098  * @method: The method for which we want the declarative security flags.
12099  * Return the declarative security flags for the method (only).
12100  *
12101  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12102  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12103  */
12104 guint32
12105 mono_declsec_flags_from_method (MonoMethod *method)
12106 {
12107         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12108                 /* FIXME: No cache (for the moment) */
12109                 guint32 idx = mono_method_get_index (method);
12110                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12111                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12112                 return mono_declsec_get_flags (method->klass->image, idx);
12113         }
12114         return 0;
12115 }
12116
12117 /*
12118  * Get the security actions (in the form of flags) associated with the specified class.
12119  *
12120  * @klass: The class for which we want the declarative security flags.
12121  * Return the declarative security flags for the class.
12122  *
12123  * Note: We cache the flags inside the MonoClass structure as this will get 
12124  *       called very often (at least for each method).
12125  */
12126 guint32
12127 mono_declsec_flags_from_class (MonoClass *klass)
12128 {
12129         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12130                 if (!klass->ext || !klass->ext->declsec_flags) {
12131                         guint32 idx;
12132
12133                         idx = mono_metadata_token_index (klass->type_token);
12134                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12135                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12136                         mono_loader_lock ();
12137                         mono_class_alloc_ext (klass);
12138                         mono_loader_unlock ();
12139                         /* we cache the flags on classes */
12140                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12141                 }
12142                 return klass->ext->declsec_flags;
12143         }
12144         return 0;
12145 }
12146
12147 /*
12148  * Get the security actions (in the form of flags) associated with the specified assembly.
12149  *
12150  * @assembly: The assembly for which we want the declarative security flags.
12151  * Return the declarative security flags for the assembly.
12152  */
12153 guint32
12154 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12155 {
12156         guint32 idx = 1; /* there is only one assembly */
12157         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12158         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12159         return mono_declsec_get_flags (assembly->image, idx);
12160 }
12161
12162
12163 /*
12164  * Fill actions for the specific index (which may either be an encoded class token or
12165  * an encoded method token) from the metadata image.
12166  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12167  */
12168 static MonoBoolean
12169 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12170         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12171 {
12172         MonoBoolean result = FALSE;
12173         MonoTableInfo *t;
12174         guint32 cols [MONO_DECL_SECURITY_SIZE];
12175         int index = mono_metadata_declsec_from_index (image, token);
12176         int i;
12177
12178         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12179         for (i = index; i < t->rows; i++) {
12180                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12181
12182                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12183                         return result;
12184
12185                 /* if present only replace (class) permissions with method permissions */
12186                 /* if empty accept either class or method permissions */
12187                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12188                         if (!actions->demand.blob) {
12189                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12190                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12191                                 actions->demand.blob = (char*) (blob + 2);
12192                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12193                                 result = TRUE;
12194                         }
12195                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12196                         if (!actions->noncasdemand.blob) {
12197                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12198                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12199                                 actions->noncasdemand.blob = (char*) (blob + 2);
12200                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12201                                 result = TRUE;
12202                         }
12203                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12204                         if (!actions->demandchoice.blob) {
12205                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12206                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12207                                 actions->demandchoice.blob = (char*) (blob + 2);
12208                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12209                                 result = TRUE;
12210                         }
12211                 }
12212         }
12213
12214         return result;
12215 }
12216
12217 static MonoBoolean
12218 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12219         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12220 {
12221         guint32 idx = mono_metadata_token_index (klass->type_token);
12222         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12223         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12224         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12225 }
12226
12227 static MonoBoolean
12228 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12229         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12230 {
12231         guint32 idx = mono_method_get_index (method);
12232         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12233         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12234         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12235 }
12236
12237 /*
12238  * Collect all actions (that requires to generate code in mini) assigned for
12239  * the specified method.
12240  * Note: Don't use the content of actions if the function return FALSE.
12241  */
12242 MonoBoolean
12243 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12244 {
12245         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12246                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12247         MonoBoolean result = FALSE;
12248         guint32 flags;
12249
12250         /* quick exit if no declarative security is present in the metadata */
12251         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12252                 return FALSE;
12253
12254         /* we want the original as the wrapper is "free" of the security informations */
12255         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12256                 method = mono_marshal_method_from_wrapper (method);
12257                 if (!method)
12258                         return FALSE;
12259         }
12260
12261         /* First we look for method-level attributes */
12262         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12263                 mono_class_init (method->klass);
12264                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12265
12266                 result = mono_declsec_get_method_demands_params (method, demands, 
12267                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12268         }
12269
12270         /* Here we use (or create) the class declarative cache to look for demands */
12271         flags = mono_declsec_flags_from_class (method->klass);
12272         if (flags & mask) {
12273                 if (!result) {
12274                         mono_class_init (method->klass);
12275                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12276                 }
12277                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12278                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12279         }
12280
12281         /* The boolean return value is used as a shortcut in case nothing needs to
12282            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12283         return result;
12284 }
12285
12286
12287 /*
12288  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12289  *
12290  * Note: Don't use the content of actions if the function return FALSE.
12291  */
12292 MonoBoolean
12293 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12294 {
12295         MonoBoolean result = FALSE;
12296         guint32 flags;
12297
12298         /* quick exit if no declarative security is present in the metadata */
12299         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12300                 return FALSE;
12301
12302         /* we want the original as the wrapper is "free" of the security informations */
12303         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12304                 method = mono_marshal_method_from_wrapper (method);
12305                 if (!method)
12306                         return FALSE;
12307         }
12308
12309         /* results are independant - zeroize both */
12310         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12311         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12312
12313         /* First we look for method-level attributes */
12314         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12315                 mono_class_init (method->klass);
12316
12317                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12318                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12319         }
12320
12321         /* Here we use (or create) the class declarative cache to look for demands */
12322         flags = mono_declsec_flags_from_class (method->klass);
12323         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12324                 mono_class_init (method->klass);
12325
12326                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12327                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12328         }
12329
12330         return result;
12331 }
12332
12333 /*
12334  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12335  *
12336  * @klass       The inherited class - this is the class that provides the security check (attributes)
12337  * @demans      
12338  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12339  * 
12340  * Note: Don't use the content of actions if the function return FALSE.
12341  */
12342 MonoBoolean
12343 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12344 {
12345         MonoBoolean result = FALSE;
12346         guint32 flags;
12347
12348         /* quick exit if no declarative security is present in the metadata */
12349         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12350                 return FALSE;
12351
12352         /* Here we use (or create) the class declarative cache to look for demands */
12353         flags = mono_declsec_flags_from_class (klass);
12354         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12355                 mono_class_init (klass);
12356                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12357
12358                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12359                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12360         }
12361
12362         return result;
12363 }
12364
12365 /*
12366  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12367  *
12368  * Note: Don't use the content of actions if the function return FALSE.
12369  */
12370 MonoBoolean
12371 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12372 {
12373         /* quick exit if no declarative security is present in the metadata */
12374         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12375                 return FALSE;
12376
12377         /* we want the original as the wrapper is "free" of the security informations */
12378         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12379                 method = mono_marshal_method_from_wrapper (method);
12380                 if (!method)
12381                         return FALSE;
12382         }
12383
12384         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12385                 mono_class_init (method->klass);
12386                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12387
12388                 return mono_declsec_get_method_demands_params (method, demands, 
12389                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12390         }
12391         return FALSE;
12392 }
12393
12394
12395 static MonoBoolean
12396 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12397 {
12398         guint32 cols [MONO_DECL_SECURITY_SIZE];
12399         MonoTableInfo *t;
12400         int i;
12401
12402         int index = mono_metadata_declsec_from_index (image, token);
12403         if (index == -1)
12404                 return FALSE;
12405
12406         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12407         for (i = index; i < t->rows; i++) {
12408                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12409
12410                 /* shortcut - index are ordered */
12411                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12412                         return FALSE;
12413
12414                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12415                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12416                         entry->blob = (char*) (metadata + 2);
12417                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12418                         return TRUE;
12419                 }
12420         }
12421
12422         return FALSE;
12423 }
12424
12425 MonoBoolean
12426 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12427 {
12428         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12429                 guint32 idx = mono_method_get_index (method);
12430                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12431                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12432                 return get_declsec_action (method->klass->image, idx, action, entry);
12433         }
12434         return FALSE;
12435 }
12436
12437 MonoBoolean
12438 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12439 {
12440         /* use cache */
12441         guint32 flags = mono_declsec_flags_from_class (klass);
12442         if (declsec_flags_map [action] & flags) {
12443                 guint32 idx = mono_metadata_token_index (klass->type_token);
12444                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12445                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12446                 return get_declsec_action (klass->image, idx, action, entry);
12447         }
12448         return FALSE;
12449 }
12450
12451 MonoBoolean
12452 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12453 {
12454         guint32 idx = 1; /* there is only one assembly */
12455         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12456         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12457
12458         return get_declsec_action (assembly->image, idx, action, entry);
12459 }
12460
12461 gboolean
12462 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12463 {
12464         MonoObject *res, *exc;
12465         void *params [1];
12466         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12467         static MonoMethod *method = NULL;
12468
12469         if (!System_Reflection_Emit_TypeBuilder) {
12470                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12471                 g_assert (System_Reflection_Emit_TypeBuilder);
12472         }
12473         if (method == NULL) {
12474                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12475                 g_assert (method);
12476         }
12477
12478         /* 
12479          * The result of mono_type_get_object () might be a System.MonoType but we
12480          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12481          */
12482         g_assert (mono_class_get_ref_info (klass));
12483         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12484
12485         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12486
12487         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12488         if (exc)
12489                 return FALSE;
12490         else
12491                 return *(MonoBoolean*)mono_object_unbox (res);
12492 }