New tests.
[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/utils/mono-string.h>
43 #include <mono/utils/mono-error-internals.h>
44
45
46 #if HAVE_SGEN_GC
47 static void* reflection_info_desc = NULL;
48 #define MOVING_GC_REGISTER(addr) do {   \
49                 if (!reflection_info_desc) {    \
50                         gsize bmap = 1;         \
51                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
52                 }       \
53                 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
54         } while (0)
55 #else
56 #define MOVING_GC_REGISTER(addr)
57 #endif
58
59 static gboolean is_usertype (MonoReflectionType *ref);
60 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
61
62 typedef struct {
63         char *p;
64         char *buf;
65         char *end;
66 } SigBuffer;
67
68 #define TEXT_OFFSET 512
69 #define CLI_H_SIZE 136
70 #define FILE_ALIGN 512
71 #define VIRT_ALIGN 8192
72 #define START_TEXT_RVA  0x00002000
73
74 typedef struct {
75         MonoReflectionILGen *ilgen;
76         MonoReflectionType *rtype;
77         MonoArray *parameters;
78         MonoArray *generic_params;
79         MonoGenericContainer *generic_container;
80         MonoArray *pinfo;
81         MonoArray *opt_types;
82         guint32 attrs;
83         guint32 iattrs;
84         guint32 call_conv;
85         guint32 *table_idx; /* note: it's a pointer */
86         MonoArray *code;
87         MonoObject *type;
88         MonoString *name;
89         MonoBoolean init_locals;
90         MonoBoolean skip_visibility;
91         MonoArray *return_modreq;
92         MonoArray *return_modopt;
93         MonoArray *param_modreq;
94         MonoArray *param_modopt;
95         MonoArray *permissions;
96         MonoMethod *mhandle;
97         guint32 nrefs;
98         gpointer *refs;
99         /* for PInvoke */
100         int charset, extra_flags, native_cc;
101         MonoString *dll, *dllentry;
102 } ReflectionMethodBuilder;
103
104 typedef struct {
105         guint32 owner;
106         MonoReflectionGenericParam *gparam;
107 } GenericParamTableEntry;
108
109 const unsigned char table_sizes [MONO_TABLE_NUM] = {
110         MONO_MODULE_SIZE,
111         MONO_TYPEREF_SIZE,
112         MONO_TYPEDEF_SIZE,
113         0,
114         MONO_FIELD_SIZE,
115         0,
116         MONO_METHOD_SIZE,
117         0,
118         MONO_PARAM_SIZE,
119         MONO_INTERFACEIMPL_SIZE,
120         MONO_MEMBERREF_SIZE,    /* 0x0A */
121         MONO_CONSTANT_SIZE,
122         MONO_CUSTOM_ATTR_SIZE,
123         MONO_FIELD_MARSHAL_SIZE,
124         MONO_DECL_SECURITY_SIZE,
125         MONO_CLASS_LAYOUT_SIZE,
126         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
127         MONO_STAND_ALONE_SIGNATURE_SIZE,
128         MONO_EVENT_MAP_SIZE,
129         0,
130         MONO_EVENT_SIZE,
131         MONO_PROPERTY_MAP_SIZE,
132         0,
133         MONO_PROPERTY_SIZE,
134         MONO_METHOD_SEMA_SIZE,
135         MONO_METHODIMPL_SIZE,
136         MONO_MODULEREF_SIZE,    /* 0x1A */
137         MONO_TYPESPEC_SIZE,
138         MONO_IMPLMAP_SIZE,      
139         MONO_FIELD_RVA_SIZE,
140         0,
141         0,
142         MONO_ASSEMBLY_SIZE,     /* 0x20 */
143         MONO_ASSEMBLY_PROCESSOR_SIZE,
144         MONO_ASSEMBLYOS_SIZE,
145         MONO_ASSEMBLYREF_SIZE,
146         MONO_ASSEMBLYREFPROC_SIZE,
147         MONO_ASSEMBLYREFOS_SIZE,
148         MONO_FILE_SIZE,
149         MONO_EXP_TYPE_SIZE,
150         MONO_MANIFEST_SIZE,
151         MONO_NESTED_CLASS_SIZE,
152
153         MONO_GENERICPARAM_SIZE, /* 0x2A */
154         MONO_METHODSPEC_SIZE,
155         MONO_GENPARCONSTRAINT_SIZE
156
157 };
158
159 #ifndef DISABLE_REFLECTION_EMIT
160 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
161 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
162 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
163 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
164 static void    ensure_runtime_vtable (MonoClass *klass);
165 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
166 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
167 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
168 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
169 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
170 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
171 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
172 #endif
173
174 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
175 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
176 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
177 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
178 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
179 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
180 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
181 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
182 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
183 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
184 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
185 static gboolean is_sre_array (MonoClass *class);
186 static gboolean is_sre_byref (MonoClass *class);
187 static gboolean is_sre_pointer (MonoClass *class);
188 static gboolean is_sre_type_builder (MonoClass *class);
189 static gboolean is_sre_method_builder (MonoClass *class);
190 static gboolean is_sre_ctor_builder (MonoClass *class);
191 static gboolean is_sre_field_builder (MonoClass *class);
192 static gboolean is_sr_mono_method (MonoClass *class);
193 static gboolean is_sr_mono_cmethod (MonoClass *class);
194 static gboolean is_sr_mono_generic_method (MonoClass *class);
195 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
196 static gboolean is_sr_mono_field (MonoClass *class);
197 static gboolean is_sr_mono_property (MonoClass *class);
198 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
199 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
200
201 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
202 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
203 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
204
205 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
206 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
207         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
208         __type = mono_reflection_type_resolve_user_types (__type);      \
209         mono_array_set (arr, MonoReflectionType*, index, __type);       \
210 } while (0)
211
212 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
213
214 void
215 mono_reflection_init (void)
216 {
217 }
218
219 static void
220 sigbuffer_init (SigBuffer *buf, int size)
221 {
222         buf->buf = g_malloc (size);
223         buf->p = buf->buf;
224         buf->end = buf->buf + size;
225 }
226
227 static void
228 sigbuffer_make_room (SigBuffer *buf, int size)
229 {
230         if (buf->end - buf->p < size) {
231                 int new_size = buf->end - buf->buf + size + 32;
232                 char *p = g_realloc (buf->buf, new_size);
233                 size = buf->p - buf->buf;
234                 buf->buf = p;
235                 buf->p = p + size;
236                 buf->end = buf->buf + new_size;
237         }
238 }
239
240 static void
241 sigbuffer_add_value (SigBuffer *buf, guint32 val)
242 {
243         sigbuffer_make_room (buf, 6);
244         mono_metadata_encode_value (val, buf->p, &buf->p);
245 }
246
247 static void
248 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
249 {
250         sigbuffer_make_room (buf, 1);
251         buf->p [0] = val;
252         buf->p++;
253 }
254
255 static void
256 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
257 {
258         sigbuffer_make_room (buf, size);
259         memcpy (buf->p, p, size);
260         buf->p += size;
261 }
262
263 static void
264 sigbuffer_free (SigBuffer *buf)
265 {
266         g_free (buf->buf);
267 }
268
269 #ifndef DISABLE_REFLECTION_EMIT
270 /**
271  * mp_g_alloc:
272  *
273  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
274  * from the C heap.
275  */
276 static gpointer
277 image_g_malloc (MonoImage *image, guint size)
278 {
279         if (image)
280                 return mono_image_alloc (image, size);
281         else
282                 return g_malloc (size);
283 }
284 #endif /* !DISABLE_REFLECTION_EMIT */
285
286 /**
287  * image_g_alloc0:
288  *
289  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
290  * from the C heap.
291  */
292 static gpointer
293 image_g_malloc0 (MonoImage *image, guint size)
294 {
295         if (image)
296                 return mono_image_alloc0 (image, size);
297         else
298                 return g_malloc0 (size);
299 }
300
301 #ifndef DISABLE_REFLECTION_EMIT
302 static char*
303 image_strdup (MonoImage *image, const char *s)
304 {
305         if (image)
306                 return mono_image_strdup (image, s);
307         else
308                 return g_strdup (s);
309 }
310 #endif
311
312 #define image_g_new(image,struct_type, n_structs)               \
313     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
314
315 #define image_g_new0(image,struct_type, n_structs)              \
316     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
317
318
319 static void
320 alloc_table (MonoDynamicTable *table, guint nrows)
321 {
322         table->rows = nrows;
323         g_assert (table->columns);
324         if (nrows + 1 >= table->alloc_rows) {
325                 while (nrows + 1 >= table->alloc_rows) {
326                         if (table->alloc_rows == 0)
327                                 table->alloc_rows = 16;
328                         else
329                                 table->alloc_rows *= 2;
330                 }
331
332                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
333         }
334 }
335
336 static void
337 make_room_in_stream (MonoDynamicStream *stream, int size)
338 {
339         if (size <= stream->alloc_size)
340                 return;
341         
342         while (stream->alloc_size <= size) {
343                 if (stream->alloc_size < 4096)
344                         stream->alloc_size = 4096;
345                 else
346                         stream->alloc_size *= 2;
347         }
348         
349         stream->data = g_realloc (stream->data, stream->alloc_size);
350 }
351
352 static guint32
353 string_heap_insert (MonoDynamicStream *sh, const char *str)
354 {
355         guint32 idx;
356         guint32 len;
357         gpointer oldkey, oldval;
358
359         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
360                 return GPOINTER_TO_UINT (oldval);
361
362         len = strlen (str) + 1;
363         idx = sh->index;
364         
365         make_room_in_stream (sh, idx + len);
366
367         /*
368          * We strdup the string even if we already copy them in sh->data
369          * so that the string pointers in the hash remain valid even if
370          * we need to realloc sh->data. We may want to avoid that later.
371          */
372         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
373         memcpy (sh->data + idx, str, len);
374         sh->index += len;
375         return idx;
376 }
377
378 static guint32
379 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
380 {
381         char *name = mono_string_to_utf8 (str);
382         guint32 idx;
383         idx = string_heap_insert (sh, name);
384         g_free (name);
385         return idx;
386 }
387
388 #ifndef DISABLE_REFLECTION_EMIT
389 static void
390 string_heap_init (MonoDynamicStream *sh)
391 {
392         sh->index = 0;
393         sh->alloc_size = 4096;
394         sh->data = g_malloc (4096);
395         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
396         string_heap_insert (sh, "");
397 }
398 #endif
399
400 static guint32
401 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
402 {
403         guint32 idx;
404         
405         make_room_in_stream (stream, stream->index + len);
406         memcpy (stream->data + stream->index, data, len);
407         idx = stream->index;
408         stream->index += len;
409         /* 
410          * align index? Not without adding an additional param that controls it since
411          * we may store a blob value in pieces.
412          */
413         return idx;
414 }
415
416 static guint32
417 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
418 {
419         guint32 idx;
420         
421         make_room_in_stream (stream, stream->index + len);
422         memset (stream->data + stream->index, 0, len);
423         idx = stream->index;
424         stream->index += len;
425         return idx;
426 }
427
428 static void
429 stream_data_align (MonoDynamicStream *stream)
430 {
431         char buf [4] = {0};
432         guint32 count = stream->index % 4;
433
434         /* we assume the stream data will be aligned */
435         if (count)
436                 mono_image_add_stream_data (stream, buf, 4 - count);
437 }
438
439 #ifndef DISABLE_REFLECTION_EMIT
440 static int
441 mono_blob_entry_hash (const char* str)
442 {
443         guint len, h;
444         const char *end;
445         len = mono_metadata_decode_blob_size (str, &str);
446         if (len > 0) {
447                 end = str + len;
448                 h = *str;
449                 for (str += 1; str < end; str++)
450                         h = (h << 5) - h + *str;
451                 return h;
452         } else {
453                 return 0;
454         }
455 }
456
457 static gboolean
458 mono_blob_entry_equal (const char *str1, const char *str2) {
459         int len, len2;
460         const char *end1;
461         const char *end2;
462         len = mono_metadata_decode_blob_size (str1, &end1);
463         len2 = mono_metadata_decode_blob_size (str2, &end2);
464         if (len != len2)
465                 return 0;
466         return memcmp (end1, end2, len) == 0;
467 }
468 #endif
469 static guint32
470 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
471 {
472         guint32 idx;
473         char *copy;
474         gpointer oldkey, oldval;
475
476         copy = g_malloc (s1+s2);
477         memcpy (copy, b1, s1);
478         memcpy (copy + s1, b2, s2);
479         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
480                 g_free (copy);
481                 idx = GPOINTER_TO_UINT (oldval);
482         } else {
483                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
484                 mono_image_add_stream_data (&assembly->blob, b2, s2);
485                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
486         }
487         return idx;
488 }
489
490 static guint32
491 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
492 {
493         char blob_size [8];
494         char *b = blob_size;
495         guint32 size = buf->p - buf->buf;
496         /* store length */
497         g_assert (size <= (buf->end - buf->buf));
498         mono_metadata_encode_value (size, b, &b);
499         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
500 }
501
502 /*
503  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
504  * dest may be misaligned.
505  */
506 static void
507 swap_with_size (char *dest, const char* val, int len, int nelem) {
508 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
509         int elem;
510
511         for (elem = 0; elem < nelem; ++elem) {
512                 switch (len) {
513                 case 1:
514                         *dest = *val;
515                         break;
516                 case 2:
517                         dest [0] = val [1];
518                         dest [1] = val [0];
519                         break;
520                 case 4:
521                         dest [0] = val [3];
522                         dest [1] = val [2];
523                         dest [2] = val [1];
524                         dest [3] = val [0];
525                         break;
526                 case 8:
527                         dest [0] = val [7];
528                         dest [1] = val [6];
529                         dest [2] = val [5];
530                         dest [3] = val [4];
531                         dest [4] = val [3];
532                         dest [5] = val [2];
533                         dest [6] = val [1];
534                         dest [7] = val [0];
535                         break;
536                 default:
537                         g_assert_not_reached ();
538                 }
539                 dest += len;
540                 val += len;
541         }
542 #else
543         memcpy (dest, val, len * nelem);
544 #endif
545 }
546
547 static guint32
548 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
549 {
550         char blob_size [64];
551         char *b = blob_size;
552         guint32 idx = 0, len;
553
554         len = str->length * 2;
555         mono_metadata_encode_value (len, b, &b);
556 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
557         {
558                 char *swapped = g_malloc (2 * mono_string_length (str));
559                 const char *p = (const char*)mono_string_chars (str);
560
561                 swap_with_size (swapped, p, 2, mono_string_length (str));
562                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
563                 g_free (swapped);
564         }
565 #else
566         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
567 #endif
568         return idx;
569 }
570
571 #ifndef DISABLE_REFLECTION_EMIT
572 static MonoClass *
573 default_class_from_mono_type (MonoType *type)
574 {
575         switch (type->type) {
576         case MONO_TYPE_OBJECT:
577                 return mono_defaults.object_class;
578         case MONO_TYPE_VOID:
579                 return mono_defaults.void_class;
580         case MONO_TYPE_BOOLEAN:
581                 return mono_defaults.boolean_class;
582         case MONO_TYPE_CHAR:
583                 return mono_defaults.char_class;
584         case MONO_TYPE_I1:
585                 return mono_defaults.sbyte_class;
586         case MONO_TYPE_U1:
587                 return mono_defaults.byte_class;
588         case MONO_TYPE_I2:
589                 return mono_defaults.int16_class;
590         case MONO_TYPE_U2:
591                 return mono_defaults.uint16_class;
592         case MONO_TYPE_I4:
593                 return mono_defaults.int32_class;
594         case MONO_TYPE_U4:
595                 return mono_defaults.uint32_class;
596         case MONO_TYPE_I:
597                 return mono_defaults.int_class;
598         case MONO_TYPE_U:
599                 return mono_defaults.uint_class;
600         case MONO_TYPE_I8:
601                 return mono_defaults.int64_class;
602         case MONO_TYPE_U8:
603                 return mono_defaults.uint64_class;
604         case MONO_TYPE_R4:
605                 return mono_defaults.single_class;
606         case MONO_TYPE_R8:
607                 return mono_defaults.double_class;
608         case MONO_TYPE_STRING:
609                 return mono_defaults.string_class;
610         default:
611                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
612                 g_assert_not_reached ();
613         }
614         
615         return NULL;
616 }
617 #endif
618
619 /*
620  * mono_class_get_ref_info:
621  *
622  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
623  */
624 gpointer
625 mono_class_get_ref_info (MonoClass *klass)
626 {
627         if (klass->ref_info_handle == 0)
628                 return NULL;
629         else
630                 return mono_gchandle_get_target (klass->ref_info_handle);
631 }
632
633 void
634 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
635 {
636         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
637         g_assert (klass->ref_info_handle != 0);
638 }
639
640 void
641 mono_class_free_ref_info (MonoClass *klass)
642 {
643         if (klass->ref_info_handle) {
644                 mono_gchandle_free (klass->ref_info_handle);
645                 klass->ref_info_handle = 0;
646         }
647 }
648
649 static void
650 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
651 {
652         int i;
653         MonoGenericInst *class_inst;
654         MonoClass *klass;
655
656         g_assert (gclass);
657
658         class_inst = gclass->context.class_inst;
659
660         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
661         klass = gclass->container_class;
662         sigbuffer_add_value (buf, klass->byval_arg.type);
663         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
664
665         sigbuffer_add_value (buf, class_inst->type_argc);
666         for (i = 0; i < class_inst->type_argc; ++i)
667                 encode_type (assembly, class_inst->type_argv [i], buf);
668
669 }
670
671 static void
672 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
673 {
674         if (!type) {
675                 g_assert_not_reached ();
676                 return;
677         }
678                 
679         if (type->byref)
680                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
681
682         switch (type->type){
683         case MONO_TYPE_VOID:
684         case MONO_TYPE_BOOLEAN:
685         case MONO_TYPE_CHAR:
686         case MONO_TYPE_I1:
687         case MONO_TYPE_U1:
688         case MONO_TYPE_I2:
689         case MONO_TYPE_U2:
690         case MONO_TYPE_I4:
691         case MONO_TYPE_U4:
692         case MONO_TYPE_I8:
693         case MONO_TYPE_U8:
694         case MONO_TYPE_R4:
695         case MONO_TYPE_R8:
696         case MONO_TYPE_I:
697         case MONO_TYPE_U:
698         case MONO_TYPE_STRING:
699         case MONO_TYPE_OBJECT:
700         case MONO_TYPE_TYPEDBYREF:
701                 sigbuffer_add_value (buf, type->type);
702                 break;
703         case MONO_TYPE_PTR:
704                 sigbuffer_add_value (buf, type->type);
705                 encode_type (assembly, type->data.type, buf);
706                 break;
707         case MONO_TYPE_SZARRAY:
708                 sigbuffer_add_value (buf, type->type);
709                 encode_type (assembly, &type->data.klass->byval_arg, buf);
710                 break;
711         case MONO_TYPE_VALUETYPE:
712         case MONO_TYPE_CLASS: {
713                 MonoClass *k = mono_class_from_mono_type (type);
714
715                 if (k->generic_container) {
716                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
717                         encode_generic_class (assembly, gclass, buf);
718                 } else {
719                         /*
720                          * Make sure we use the correct type.
721                          */
722                         sigbuffer_add_value (buf, k->byval_arg.type);
723                         /*
724                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
725                          * otherwise two typerefs could point to the same type, leading to
726                          * verification errors.
727                          */
728                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
729                 }
730                 break;
731         }
732         case MONO_TYPE_ARRAY:
733                 sigbuffer_add_value (buf, type->type);
734                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
735                 sigbuffer_add_value (buf, type->data.array->rank);
736                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
737                 sigbuffer_add_value (buf, 0);
738                 break;
739         case MONO_TYPE_GENERICINST:
740                 encode_generic_class (assembly, type->data.generic_class, buf);
741                 break;
742         case MONO_TYPE_VAR:
743         case MONO_TYPE_MVAR:
744                 sigbuffer_add_value (buf, type->type);
745                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
746                 break;
747         default:
748                 g_error ("need to encode type %x", type->type);
749         }
750 }
751
752 static void
753 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
754 {
755         if (!type) {
756                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
757                 return;
758         }
759
760         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
761 }
762
763 static void
764 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
765 {
766         int i;
767
768         if (modreq) {
769                 for (i = 0; i < mono_array_length (modreq); ++i) {
770                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
771                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
772                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
773                 }
774         }
775         if (modopt) {
776                 for (i = 0; i < mono_array_length (modopt); ++i) {
777                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
778                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
779                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
780                 }
781         }
782 }
783
784 #ifndef DISABLE_REFLECTION_EMIT
785 static guint32
786 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
787 {
788         SigBuffer buf;
789         int i;
790         guint32 nparams =  sig->param_count;
791         guint32 idx;
792
793         if (!assembly->save)
794                 return 0;
795
796         sigbuffer_init (&buf, 32);
797         /*
798          * FIXME: vararg, explicit_this, differenc call_conv values...
799          */
800         idx = sig->call_convention;
801         if (sig->hasthis)
802                 idx |= 0x20; /* hasthis */
803         if (sig->generic_param_count)
804                 idx |= 0x10; /* generic */
805         sigbuffer_add_byte (&buf, idx);
806         if (sig->generic_param_count)
807                 sigbuffer_add_value (&buf, sig->generic_param_count);
808         sigbuffer_add_value (&buf, nparams);
809         encode_type (assembly, sig->ret, &buf);
810         for (i = 0; i < nparams; ++i) {
811                 if (i == sig->sentinelpos)
812                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
813                 encode_type (assembly, sig->params [i], &buf);
814         }
815         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
816         sigbuffer_free (&buf);
817         return idx;
818 }
819 #endif
820
821 static guint32
822 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
823 {
824         /*
825          * FIXME: reuse code from method_encode_signature().
826          */
827         SigBuffer buf;
828         int i;
829         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
830         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
831         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
832         guint32 idx;
833
834         sigbuffer_init (&buf, 32);
835         /* LAMESPEC: all the call conv spec is foobared */
836         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
837         if (mb->call_conv & 2)
838                 idx |= 0x5; /* vararg */
839         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
840                 idx |= 0x20; /* hasthis */
841         if (ngparams)
842                 idx |= 0x10; /* generic */
843         sigbuffer_add_byte (&buf, idx);
844         if (ngparams)
845                 sigbuffer_add_value (&buf, ngparams);
846         sigbuffer_add_value (&buf, nparams + notypes);
847         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
848         encode_reflection_type (assembly, mb->rtype, &buf);
849         for (i = 0; i < nparams; ++i) {
850                 MonoArray *modreq = NULL;
851                 MonoArray *modopt = NULL;
852                 MonoReflectionType *pt;
853
854                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
855                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
856                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
857                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
858                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
859                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
860                 encode_reflection_type (assembly, pt, &buf);
861         }
862         if (notypes)
863                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
864         for (i = 0; i < notypes; ++i) {
865                 MonoReflectionType *pt;
866
867                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
868                 encode_reflection_type (assembly, pt, &buf);
869         }
870
871         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
872         sigbuffer_free (&buf);
873         return idx;
874 }
875
876 static guint32
877 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
878 {
879         MonoDynamicTable *table;
880         guint32 *values;
881         guint32 idx, sig_idx;
882         guint nl = mono_array_length (ilgen->locals);
883         SigBuffer buf;
884         int i;
885
886         sigbuffer_init (&buf, 32);
887         sigbuffer_add_value (&buf, 0x07);
888         sigbuffer_add_value (&buf, nl);
889         for (i = 0; i < nl; ++i) {
890                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
891                 
892                 if (lb->is_pinned)
893                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
894                 
895                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
896         }
897         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
898         sigbuffer_free (&buf);
899
900         if (assembly->standalonesig_cache == NULL)
901                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
902         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
903         if (idx)
904                 return idx;
905
906         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
907         idx = table->next_idx ++;
908         table->rows ++;
909         alloc_table (table, table->rows);
910         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
911
912         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
913
914         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
915
916         return idx;
917 }
918
919 static guint32
920 method_count_clauses (MonoReflectionILGen *ilgen)
921 {
922         guint32 num_clauses = 0;
923         int i;
924
925         MonoILExceptionInfo *ex_info;
926         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
927                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
928                 if (ex_info->handlers)
929                         num_clauses += mono_array_length (ex_info->handlers);
930                 else
931                         num_clauses++;
932         }
933
934         return num_clauses;
935 }
936
937 #ifndef DISABLE_REFLECTION_EMIT
938 static MonoExceptionClause*
939 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
940 {
941         MonoExceptionClause *clauses;
942         MonoExceptionClause *clause;
943         MonoILExceptionInfo *ex_info;
944         MonoILExceptionBlock *ex_block;
945         guint32 finally_start;
946         int i, j, clause_index;;
947
948         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
949
950         clause_index = 0;
951         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
952                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
953                 finally_start = ex_info->start + ex_info->len;
954                 if (!ex_info->handlers)
955                         continue;
956                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
957                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
958                         clause = &(clauses [clause_index]);
959
960                         clause->flags = ex_block->type;
961                         clause->try_offset = ex_info->start;
962
963                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
964                                 clause->try_len = finally_start - ex_info->start;
965                         else
966                                 clause->try_len = ex_info->len;
967                         clause->handler_offset = ex_block->start;
968                         clause->handler_len = ex_block->len;
969                         if (ex_block->extype) {
970                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
971                         } else {
972                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
973                                         clause->data.filter_offset = ex_block->filter_offset;
974                                 else
975                                         clause->data.filter_offset = 0;
976                         }
977                         finally_start = ex_block->start + ex_block->len;
978
979                         clause_index ++;
980                 }
981         }
982
983         return clauses;
984 }
985 #endif /* !DISABLE_REFLECTION_EMIT */
986
987 static guint32
988 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
989 {
990         char flags = 0;
991         guint32 idx;
992         guint32 code_size;
993         gint32 max_stack, i;
994         gint32 num_locals = 0;
995         gint32 num_exception = 0;
996         gint maybe_small;
997         guint32 fat_flags;
998         char fat_header [12];
999         guint32 int_value;
1000         guint16 short_value;
1001         guint32 local_sig = 0;
1002         guint32 header_size = 12;
1003         MonoArray *code;
1004
1005         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1006                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1007                 return 0;
1008
1009         /*if (mb->name)
1010                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1011         if (mb->ilgen) {
1012                 code = mb->ilgen->code;
1013                 code_size = mb->ilgen->code_len;
1014                 max_stack = mb->ilgen->max_stack;
1015                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1016                 if (mb->ilgen->ex_handlers)
1017                         num_exception = method_count_clauses (mb->ilgen);
1018         } else {
1019                 code = mb->code;
1020                 if (code == NULL){
1021                         char *name = mono_string_to_utf8 (mb->name);
1022                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1023                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1024                         g_free (str);
1025                         g_free (name);
1026                         mono_raise_exception (exception);
1027                 }
1028
1029                 code_size = mono_array_length (code);
1030                 max_stack = 8; /* we probably need to run a verifier on the code... */
1031         }
1032
1033         stream_data_align (&assembly->code);
1034
1035         /* check for exceptions, maxstack, locals */
1036         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1037         if (maybe_small) {
1038                 if (code_size < 64 && !(code_size & 1)) {
1039                         flags = (code_size << 2) | 0x2;
1040                 } else if (code_size < 32 && (code_size & 1)) {
1041                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1042                 } else {
1043                         goto fat_header;
1044                 }
1045                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1046                 /* add to the fixup todo list */
1047                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1048                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1049                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1050                 return assembly->text_rva + idx;
1051         } 
1052 fat_header:
1053         if (num_locals)
1054                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1055         /* 
1056          * FIXME: need to set also the header size in fat_flags.
1057          * (and more sects and init locals flags)
1058          */
1059         fat_flags =  0x03;
1060         if (num_exception)
1061                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1062         if (mb->init_locals)
1063                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1064         fat_header [0] = fat_flags;
1065         fat_header [1] = (header_size / 4 ) << 4;
1066         short_value = GUINT16_TO_LE (max_stack);
1067         memcpy (fat_header + 2, &short_value, 2);
1068         int_value = GUINT32_TO_LE (code_size);
1069         memcpy (fat_header + 4, &int_value, 4);
1070         int_value = GUINT32_TO_LE (local_sig);
1071         memcpy (fat_header + 8, &int_value, 4);
1072         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1073         /* add to the fixup todo list */
1074         if (mb->ilgen && mb->ilgen->num_token_fixups)
1075                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1076         
1077         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1078         if (num_exception) {
1079                 unsigned char sheader [4];
1080                 MonoILExceptionInfo * ex_info;
1081                 MonoILExceptionBlock * ex_block;
1082                 int j;
1083
1084                 stream_data_align (&assembly->code);
1085                 /* always use fat format for now */
1086                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1087                 num_exception *= 6 * sizeof (guint32);
1088                 num_exception += 4; /* include the size of the header */
1089                 sheader [1] = num_exception & 0xff;
1090                 sheader [2] = (num_exception >> 8) & 0xff;
1091                 sheader [3] = (num_exception >> 16) & 0xff;
1092                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1093                 /* fat header, so we are already aligned */
1094                 /* reverse order */
1095                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1096                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1097                         if (ex_info->handlers) {
1098                                 int finally_start = ex_info->start + ex_info->len;
1099                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1100                                         guint32 val;
1101                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1102                                         /* the flags */
1103                                         val = GUINT32_TO_LE (ex_block->type);
1104                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105                                         /* try offset */
1106                                         val = GUINT32_TO_LE (ex_info->start);
1107                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108                                         /* need fault, too, probably */
1109                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1110                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1111                                         else
1112                                                 val = GUINT32_TO_LE (ex_info->len);
1113                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1114                                         /* handler offset */
1115                                         val = GUINT32_TO_LE (ex_block->start);
1116                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1117                                         /* handler len */
1118                                         val = GUINT32_TO_LE (ex_block->len);
1119                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1120                                         finally_start = ex_block->start + ex_block->len;
1121                                         if (ex_block->extype) {
1122                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1123                                         } else {
1124                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1125                                                         val = ex_block->filter_offset;
1126                                                 else
1127                                                         val = 0;
1128                                         }
1129                                         val = GUINT32_TO_LE (val);
1130                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1131                                         /*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", 
1132                                                         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);*/
1133                                 }
1134                         } else {
1135                                 g_error ("No clauses for ex info block %d", i);
1136                         }
1137                 }
1138         }
1139         return assembly->text_rva + idx;
1140 }
1141
1142 static guint32
1143 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1144 {
1145         int i;
1146         MonoDynamicTable *table;
1147         guint32 *values;
1148         
1149         table = &assembly->tables [table_idx];
1150
1151         g_assert (col < table->columns);
1152
1153         values = table->values + table->columns;
1154         for (i = 1; i <= table->rows; ++i) {
1155                 if (values [col] == token)
1156                         return i;
1157                 values += table->columns;
1158         }
1159         return 0;
1160 }
1161
1162 /*
1163  * LOCKING: Acquires the loader lock. 
1164  */
1165 static MonoCustomAttrInfo*
1166 lookup_custom_attr (MonoImage *image, gpointer member)
1167 {
1168         MonoCustomAttrInfo* res;
1169
1170         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1171
1172         if (!res)
1173                 return NULL;
1174
1175         return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1176 }
1177
1178 static gboolean
1179 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1180 {
1181         /* FIXME: Need to do more checks */
1182         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1183                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1184
1185                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1186                         return FALSE;
1187         }
1188
1189         return TRUE;
1190 }
1191
1192 static MonoCustomAttrInfo*
1193 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1194 {
1195         int i, index, count, not_visible;
1196         MonoCustomAttrInfo *ainfo;
1197         MonoReflectionCustomAttr *cattr;
1198
1199         if (!cattrs)
1200                 return NULL;
1201         /* FIXME: check in assembly the Run flag is set */
1202
1203         count = mono_array_length (cattrs);
1204
1205         /* Skip nonpublic attributes since MS.NET seems to do the same */
1206         /* FIXME: This needs to be done more globally */
1207         not_visible = 0;
1208         for (i = 0; i < count; ++i) {
1209                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1210                 if (!custom_attr_visible (image, cattr))
1211                         not_visible ++;
1212         }
1213         count -= not_visible;
1214
1215         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1216
1217         ainfo->image = image;
1218         ainfo->num_attrs = count;
1219         ainfo->cached = alloc_img != NULL;
1220         index = 0;
1221         for (i = 0; i < count; ++i) {
1222                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1223                 if (custom_attr_visible (image, cattr)) {
1224                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1225                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1226                         ainfo->attrs [index].ctor = cattr->ctor->method;
1227                         ainfo->attrs [index].data = saved;
1228                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1229                         index ++;
1230                 }
1231         }
1232
1233         return ainfo;
1234 }
1235
1236 #ifndef DISABLE_REFLECTION_EMIT
1237 /*
1238  * LOCKING: Acquires the loader lock. 
1239  */
1240 static void
1241 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1242 {
1243         MonoCustomAttrInfo *ainfo, *tmp;
1244
1245         if (!cattrs || !mono_array_length (cattrs))
1246                 return;
1247
1248         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1249
1250         mono_loader_lock ();
1251         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1252         if (tmp)
1253                 mono_custom_attrs_free (tmp);
1254         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1255         mono_loader_unlock ();
1256
1257 }
1258 #endif
1259
1260 void
1261 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1262 {
1263         if (!ainfo->cached)
1264                 g_free (ainfo);
1265 }
1266
1267 /*
1268  * idx is the table index of the object
1269  * type is one of MONO_CUSTOM_ATTR_*
1270  */
1271 static void
1272 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1273 {
1274         MonoDynamicTable *table;
1275         MonoReflectionCustomAttr *cattr;
1276         guint32 *values;
1277         guint32 count, i, token;
1278         char blob_size [6];
1279         char *p = blob_size;
1280         
1281         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1282         if (!cattrs)
1283                 return;
1284         count = mono_array_length (cattrs);
1285         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1286         table->rows += count;
1287         alloc_table (table, table->rows);
1288         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1289         idx <<= MONO_CUSTOM_ATTR_BITS;
1290         idx |= type;
1291         for (i = 0; i < count; ++i) {
1292                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1293                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1294                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1295                 type = mono_metadata_token_index (token);
1296                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1297                 switch (mono_metadata_token_table (token)) {
1298                 case MONO_TABLE_METHOD:
1299                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1300                         break;
1301                 case MONO_TABLE_MEMBERREF:
1302                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1303                         break;
1304                 default:
1305                         g_warning ("got wrong token in custom attr");
1306                         continue;
1307                 }
1308                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1309                 p = blob_size;
1310                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1311                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1312                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1313                 values += MONO_CUSTOM_ATTR_SIZE;
1314                 ++table->next_idx;
1315         }
1316 }
1317
1318 static void
1319 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1320 {
1321         MonoDynamicTable *table;
1322         guint32 *values;
1323         guint32 count, i, idx;
1324         MonoReflectionPermissionSet *perm;
1325
1326         if (!permissions)
1327                 return;
1328
1329         count = mono_array_length (permissions);
1330         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1331         table->rows += count;
1332         alloc_table (table, table->rows);
1333
1334         for (i = 0; i < mono_array_length (permissions); ++i) {
1335                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1336
1337                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1338
1339                 idx = mono_metadata_token_index (parent_token);
1340                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1341                 switch (mono_metadata_token_table (parent_token)) {
1342                 case MONO_TABLE_TYPEDEF:
1343                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1344                         break;
1345                 case MONO_TABLE_METHOD:
1346                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1347                         break;
1348                 case MONO_TABLE_ASSEMBLY:
1349                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1350                         break;
1351                 default:
1352                         g_assert_not_reached ();
1353                 }
1354
1355                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1356                 values [MONO_DECL_SECURITY_PARENT] = idx;
1357                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1358
1359                 ++table->next_idx;
1360         }
1361 }
1362
1363 /*
1364  * Fill in the MethodDef and ParamDef tables for a method.
1365  * This is used for both normal methods and constructors.
1366  */
1367 static void
1368 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1369 {
1370         MonoDynamicTable *table;
1371         guint32 *values;
1372         guint i, count;
1373
1374         /* room in this table is already allocated */
1375         table = &assembly->tables [MONO_TABLE_METHOD];
1376         *mb->table_idx = table->next_idx ++;
1377         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1378         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1379         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1380         values [MONO_METHOD_FLAGS] = mb->attrs;
1381         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1382         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1383         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1384         
1385         table = &assembly->tables [MONO_TABLE_PARAM];
1386         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1387
1388         mono_image_add_decl_security (assembly, 
1389                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1390
1391         if (mb->pinfo) {
1392                 MonoDynamicTable *mtable;
1393                 guint32 *mvalues;
1394                 
1395                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1396                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1397                 
1398                 count = 0;
1399                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1400                         if (mono_array_get (mb->pinfo, gpointer, i))
1401                                 count++;
1402                 }
1403                 table->rows += count;
1404                 alloc_table (table, table->rows);
1405                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1406                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1407                         MonoReflectionParamBuilder *pb;
1408                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1409                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1410                                 values [MONO_PARAM_SEQUENCE] = i;
1411                                 if (pb->name != NULL) {
1412                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1413                                 } else {
1414                                         values [MONO_PARAM_NAME] = 0;
1415                                 }
1416                                 values += MONO_PARAM_SIZE;
1417                                 if (pb->marshal_info) {
1418                                         mtable->rows++;
1419                                         alloc_table (mtable, mtable->rows);
1420                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1421                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1422                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1423                                 }
1424                                 pb->table_idx = table->next_idx++;
1425                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1426                                         guint32 field_type = 0;
1427                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1428                                         mtable->rows ++;
1429                                         alloc_table (mtable, mtable->rows);
1430                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1431                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1432                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1433                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1434                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1435                                 }
1436                         }
1437                 }
1438         }
1439 }
1440
1441 #ifndef DISABLE_REFLECTION_EMIT
1442 static void
1443 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1444 {
1445         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1446
1447         rmb->ilgen = mb->ilgen;
1448         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1449         rmb->parameters = mb->parameters;
1450         rmb->generic_params = mb->generic_params;
1451         rmb->generic_container = mb->generic_container;
1452         rmb->opt_types = NULL;
1453         rmb->pinfo = mb->pinfo;
1454         rmb->attrs = mb->attrs;
1455         rmb->iattrs = mb->iattrs;
1456         rmb->call_conv = mb->call_conv;
1457         rmb->code = mb->code;
1458         rmb->type = mb->type;
1459         rmb->name = mb->name;
1460         rmb->table_idx = &mb->table_idx;
1461         rmb->init_locals = mb->init_locals;
1462         rmb->skip_visibility = FALSE;
1463         rmb->return_modreq = mb->return_modreq;
1464         rmb->return_modopt = mb->return_modopt;
1465         rmb->param_modreq = mb->param_modreq;
1466         rmb->param_modopt = mb->param_modopt;
1467         rmb->permissions = mb->permissions;
1468         rmb->mhandle = mb->mhandle;
1469         rmb->nrefs = 0;
1470         rmb->refs = NULL;
1471
1472         if (mb->dll) {
1473                 rmb->charset = mb->charset;
1474                 rmb->extra_flags = mb->extra_flags;
1475                 rmb->native_cc = mb->native_cc;
1476                 rmb->dllentry = mb->dllentry;
1477                 rmb->dll = mb->dll;
1478         }
1479 }
1480
1481 static void
1482 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1483 {
1484         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1485
1486         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1487
1488         rmb->ilgen = mb->ilgen;
1489         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1490         rmb->parameters = mb->parameters;
1491         rmb->generic_params = NULL;
1492         rmb->generic_container = NULL;
1493         rmb->opt_types = NULL;
1494         rmb->pinfo = mb->pinfo;
1495         rmb->attrs = mb->attrs;
1496         rmb->iattrs = mb->iattrs;
1497         rmb->call_conv = mb->call_conv;
1498         rmb->code = NULL;
1499         rmb->type = mb->type;
1500         rmb->name = mono_string_new (mono_domain_get (), name);
1501         rmb->table_idx = &mb->table_idx;
1502         rmb->init_locals = mb->init_locals;
1503         rmb->skip_visibility = FALSE;
1504         rmb->return_modreq = NULL;
1505         rmb->return_modopt = NULL;
1506         rmb->param_modreq = mb->param_modreq;
1507         rmb->param_modopt = mb->param_modopt;
1508         rmb->permissions = mb->permissions;
1509         rmb->mhandle = mb->mhandle;
1510         rmb->nrefs = 0;
1511         rmb->refs = NULL;
1512 }
1513
1514 static void
1515 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1516 {
1517         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1518
1519         rmb->ilgen = mb->ilgen;
1520         rmb->rtype = mb->rtype;
1521         rmb->parameters = mb->parameters;
1522         rmb->generic_params = NULL;
1523         rmb->generic_container = NULL;
1524         rmb->opt_types = NULL;
1525         rmb->pinfo = NULL;
1526         rmb->attrs = mb->attrs;
1527         rmb->iattrs = 0;
1528         rmb->call_conv = mb->call_conv;
1529         rmb->code = NULL;
1530         rmb->type = (MonoObject *) mb->owner;
1531         rmb->name = mb->name;
1532         rmb->table_idx = NULL;
1533         rmb->init_locals = mb->init_locals;
1534         rmb->skip_visibility = mb->skip_visibility;
1535         rmb->return_modreq = NULL;
1536         rmb->return_modopt = NULL;
1537         rmb->param_modreq = NULL;
1538         rmb->param_modopt = NULL;
1539         rmb->permissions = NULL;
1540         rmb->mhandle = mb->mhandle;
1541         rmb->nrefs = 0;
1542         rmb->refs = NULL;
1543 }       
1544 #endif
1545
1546 static void
1547 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1548 {
1549         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1550         MonoDynamicTable *table;
1551         guint32 *values;
1552         guint32 tok;
1553
1554         if (!mb->override_method)
1555                 return;
1556
1557         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1558         table->rows ++;
1559         alloc_table (table, table->rows);
1560         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1561         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1562         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1563
1564         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1565         switch (mono_metadata_token_table (tok)) {
1566         case MONO_TABLE_MEMBERREF:
1567                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1568                 break;
1569         case MONO_TABLE_METHOD:
1570                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1571                 break;
1572         default:
1573                 g_assert_not_reached ();
1574         }
1575         values [MONO_METHODIMPL_DECLARATION] = tok;
1576 }
1577
1578 #ifndef DISABLE_REFLECTION_EMIT
1579 static void
1580 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1581 {
1582         MonoDynamicTable *table;
1583         guint32 *values;
1584         ReflectionMethodBuilder rmb;
1585         int i;
1586
1587         reflection_methodbuilder_from_method_builder (&rmb, mb);
1588
1589         mono_image_basic_method (&rmb, assembly);
1590         mb->table_idx = *rmb.table_idx;
1591
1592         if (mb->dll) { /* It's a P/Invoke method */
1593                 guint32 moduleref;
1594                 /* map CharSet values to on-disk values */
1595                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1596                 int extra_flags = mb->extra_flags;
1597                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1598                 table->rows ++;
1599                 alloc_table (table, table->rows);
1600                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1601                 
1602                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1603                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1604                 if (mb->dllentry)
1605                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1606                 else
1607                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1608                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1609                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1610                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1611                         table->rows ++;
1612                         alloc_table (table, table->rows);
1613                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1614                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1615                 }
1616         }
1617
1618         if (mb->generic_params) {
1619                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1620                 table->rows += mono_array_length (mb->generic_params);
1621                 alloc_table (table, table->rows);
1622                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1623                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1624
1625                         mono_image_get_generic_param_info (
1626                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1627                 }
1628         }
1629
1630 }
1631
1632 static void
1633 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1634 {
1635         ReflectionMethodBuilder rmb;
1636
1637         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1638
1639         mono_image_basic_method (&rmb, assembly);
1640         mb->table_idx = *rmb.table_idx;
1641 }
1642 #endif
1643
1644 static char*
1645 type_get_fully_qualified_name (MonoType *type)
1646 {
1647         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1648 }
1649
1650 static char*
1651 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1652         MonoClass *klass;
1653         MonoAssembly *ta;
1654
1655         klass = mono_class_from_mono_type (type);
1656         if (!klass) 
1657                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1658         ta = klass->image->assembly;
1659         if (ta->dynamic || (ta == ass)) {
1660                 if (klass->generic_class || klass->generic_container)
1661                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1662                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1663                 else
1664                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1665         }
1666
1667         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1668 }
1669
1670 #ifndef DISABLE_REFLECTION_EMIT
1671 /*field_image is the image to which the eventual custom mods have been encoded against*/
1672 static guint32
1673 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1674 {
1675         SigBuffer buf;
1676         guint32 idx, i, token;
1677
1678         if (!assembly->save)
1679                 return 0;
1680
1681         sigbuffer_init (&buf, 32);
1682         
1683         sigbuffer_add_value (&buf, 0x06);
1684         /* encode custom attributes before the type */
1685         if (type->num_mods) {
1686                 for (i = 0; i < type->num_mods; ++i) {
1687                         if (field_image) {
1688                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1689                                 g_assert (class);
1690                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1691                         } else {
1692                                 token = type->modifiers [i].token;
1693                         }
1694
1695                         if (type->modifiers [i].required)
1696                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1697                         else
1698                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1699
1700                         sigbuffer_add_value (&buf, token);
1701                 }
1702         }
1703         encode_type (assembly, type, &buf);
1704         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1705         sigbuffer_free (&buf);
1706         return idx;
1707 }
1708 #endif
1709
1710 static guint32
1711 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1712 {
1713         SigBuffer buf;
1714         guint32 idx;
1715
1716         sigbuffer_init (&buf, 32);
1717         
1718         sigbuffer_add_value (&buf, 0x06);
1719         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1720         /* encode custom attributes before the type */
1721         encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1722         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1723         sigbuffer_free (&buf);
1724         return idx;
1725 }
1726
1727 static guint32
1728 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1729         char blob_size [64];
1730         char *b = blob_size;
1731         char *p, *box_val;
1732         char* buf;
1733         guint32 idx = 0, len = 0, dummy = 0;
1734 #ifdef ARM_FPU_FPA
1735 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1736         guint32 fpa_double [2];
1737         guint32 *fpa_p;
1738 #endif
1739 #endif
1740         
1741         p = buf = g_malloc (64);
1742         if (!val) {
1743                 *ret_type = MONO_TYPE_CLASS;
1744                 len = 4;
1745                 box_val = (char*)&dummy;
1746         } else {
1747                 box_val = ((char*)val) + sizeof (MonoObject);
1748                 *ret_type = val->vtable->klass->byval_arg.type;
1749         }
1750 handle_enum:
1751         switch (*ret_type) {
1752         case MONO_TYPE_BOOLEAN:
1753         case MONO_TYPE_U1:
1754         case MONO_TYPE_I1:
1755                 len = 1;
1756                 break;
1757         case MONO_TYPE_CHAR:
1758         case MONO_TYPE_U2:
1759         case MONO_TYPE_I2:
1760                 len = 2;
1761                 break;
1762         case MONO_TYPE_U4:
1763         case MONO_TYPE_I4:
1764         case MONO_TYPE_R4:
1765                 len = 4;
1766                 break;
1767         case MONO_TYPE_U8:
1768         case MONO_TYPE_I8:
1769                 len = 8;
1770                 break;
1771         case MONO_TYPE_R8:
1772                 len = 8;
1773 #ifdef ARM_FPU_FPA
1774 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1775                 fpa_p = (guint32*)box_val;
1776                 fpa_double [0] = fpa_p [1];
1777                 fpa_double [1] = fpa_p [0];
1778                 box_val = (char*)fpa_double;
1779 #endif
1780 #endif
1781                 break;
1782         case MONO_TYPE_VALUETYPE:
1783                 if (val->vtable->klass->enumtype) {
1784                         *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1785                         goto handle_enum;
1786                 } else
1787                         g_error ("we can't encode valuetypes");
1788         case MONO_TYPE_CLASS:
1789                 break;
1790         case MONO_TYPE_STRING: {
1791                 MonoString *str = (MonoString*)val;
1792                 /* there is no signature */
1793                 len = str->length * 2;
1794                 mono_metadata_encode_value (len, b, &b);
1795 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1796                 {
1797                         char *swapped = g_malloc (2 * mono_string_length (str));
1798                         const char *p = (const char*)mono_string_chars (str);
1799
1800                         swap_with_size (swapped, p, 2, mono_string_length (str));
1801                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1802                         g_free (swapped);
1803                 }
1804 #else
1805                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1806 #endif
1807
1808                 g_free (buf);
1809                 return idx;
1810         }
1811         case MONO_TYPE_GENERICINST:
1812                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1813                 goto handle_enum;
1814         default:
1815                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1816         }
1817
1818         /* there is no signature */
1819         mono_metadata_encode_value (len, b, &b);
1820 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1821         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1822         swap_with_size (blob_size, box_val, len, 1);
1823         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1824 #else
1825         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1826 #endif
1827
1828         g_free (buf);
1829         return idx;
1830 }
1831
1832 static guint32
1833 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1834         char *str;
1835         SigBuffer buf;
1836         guint32 idx, len;
1837
1838         sigbuffer_init (&buf, 32);
1839
1840         sigbuffer_add_value (&buf, minfo->type);
1841
1842         switch (minfo->type) {
1843         case MONO_NATIVE_BYVALTSTR:
1844         case MONO_NATIVE_BYVALARRAY:
1845                 sigbuffer_add_value (&buf, minfo->count);
1846                 break;
1847         case MONO_NATIVE_LPARRAY:
1848                 if (minfo->eltype || minfo->has_size) {
1849                         sigbuffer_add_value (&buf, minfo->eltype);
1850                         if (minfo->has_size) {
1851                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1852                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1853
1854                                 /* LAMESPEC: ElemMult is undocumented */
1855                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1856                         }
1857                 }
1858                 break;
1859         case MONO_NATIVE_SAFEARRAY:
1860                 if (minfo->eltype)
1861                         sigbuffer_add_value (&buf, minfo->eltype);
1862                 break;
1863         case MONO_NATIVE_CUSTOM:
1864                 if (minfo->guid) {
1865                         str = mono_string_to_utf8 (minfo->guid);
1866                         len = strlen (str);
1867                         sigbuffer_add_value (&buf, len);
1868                         sigbuffer_add_mem (&buf, str, len);
1869                         g_free (str);
1870                 } else {
1871                         sigbuffer_add_value (&buf, 0);
1872                 }
1873                 /* native type name */
1874                 sigbuffer_add_value (&buf, 0);
1875                 /* custom marshaler type name */
1876                 if (minfo->marshaltype || minfo->marshaltyperef) {
1877                         if (minfo->marshaltyperef)
1878                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1879                         else
1880                                 str = mono_string_to_utf8 (minfo->marshaltype);
1881                         len = strlen (str);
1882                         sigbuffer_add_value (&buf, len);
1883                         sigbuffer_add_mem (&buf, str, len);
1884                         g_free (str);
1885                 } else {
1886                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1887                         sigbuffer_add_value (&buf, 0);
1888                 }
1889                 if (minfo->mcookie) {
1890                         str = mono_string_to_utf8 (minfo->mcookie);
1891                         len = strlen (str);
1892                         sigbuffer_add_value (&buf, len);
1893                         sigbuffer_add_mem (&buf, str, len);
1894                         g_free (str);
1895                 } else {
1896                         sigbuffer_add_value (&buf, 0);
1897                 }
1898                 break;
1899         default:
1900                 break;
1901         }
1902         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1903         sigbuffer_free (&buf);
1904         return idx;
1905 }
1906
1907 static void
1908 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1909 {
1910         MonoDynamicTable *table;
1911         guint32 *values;
1912
1913         /* maybe this fixup should be done in the C# code */
1914         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1915                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1916         table = &assembly->tables [MONO_TABLE_FIELD];
1917         fb->table_idx = table->next_idx ++;
1918         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1919         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1920         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1921         values [MONO_FIELD_FLAGS] = fb->attrs;
1922         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1923
1924         if (fb->offset != -1) {
1925                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1926                 table->rows ++;
1927                 alloc_table (table, table->rows);
1928                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1929                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1930                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1931         }
1932         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1933                 guint32 field_type = 0;
1934                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1935                 table->rows ++;
1936                 alloc_table (table, table->rows);
1937                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1938                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1939                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1940                 values [MONO_CONSTANT_TYPE] = field_type;
1941                 values [MONO_CONSTANT_PADDING] = 0;
1942         }
1943         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1944                 guint32 rva_idx;
1945                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1946                 table->rows ++;
1947                 alloc_table (table, table->rows);
1948                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1949                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1950                 /*
1951                  * We store it in the code section because it's simpler for now.
1952                  */
1953                 if (fb->rva_data) {
1954                         if (mono_array_length (fb->rva_data) >= 10)
1955                                 stream_data_align (&assembly->code);
1956                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1957                 } else
1958                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1959                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1960         }
1961         if (fb->marshal_info) {
1962                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1963                 table->rows ++;
1964                 alloc_table (table, table->rows);
1965                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1966                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1967                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1968         }
1969 }
1970
1971 static guint32
1972 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1973 {
1974         SigBuffer buf;
1975         guint32 nparams = 0;
1976         MonoReflectionMethodBuilder *mb = fb->get_method;
1977         MonoReflectionMethodBuilder *smb = fb->set_method;
1978         guint32 idx, i;
1979
1980         if (mb && mb->parameters)
1981                 nparams = mono_array_length (mb->parameters);
1982         if (!mb && smb && smb->parameters)
1983                 nparams = mono_array_length (smb->parameters) - 1;
1984         sigbuffer_init (&buf, 32);
1985         sigbuffer_add_byte (&buf, 0x08);
1986         sigbuffer_add_value (&buf, nparams);
1987         if (mb) {
1988                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1989                 for (i = 0; i < nparams; ++i) {
1990                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1991                         encode_reflection_type (assembly, pt, &buf);
1992                 }
1993         } else if (smb && smb->parameters) {
1994                 /* the property type is the last param */
1995                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1996                 for (i = 0; i < nparams; ++i) {
1997                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1998                         encode_reflection_type (assembly, pt, &buf);
1999                 }
2000         } else {
2001                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2002         }
2003
2004         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2005         sigbuffer_free (&buf);
2006         return idx;
2007 }
2008
2009 static void
2010 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2011 {
2012         MonoDynamicTable *table;
2013         guint32 *values;
2014         guint num_methods = 0;
2015         guint32 semaidx;
2016
2017         /* 
2018          * we need to set things in the following tables:
2019          * PROPERTYMAP (info already filled in _get_type_info ())
2020          * PROPERTY    (rows already preallocated in _get_type_info ())
2021          * METHOD      (method info already done with the generic method code)
2022          * METHODSEMANTICS
2023          * CONSTANT
2024          */
2025         table = &assembly->tables [MONO_TABLE_PROPERTY];
2026         pb->table_idx = table->next_idx ++;
2027         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2028         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2029         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2030         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2031
2032         /* FIXME: we still don't handle 'other' methods */
2033         if (pb->get_method) num_methods ++;
2034         if (pb->set_method) num_methods ++;
2035
2036         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2037         table->rows += num_methods;
2038         alloc_table (table, table->rows);
2039
2040         if (pb->get_method) {
2041                 semaidx = table->next_idx ++;
2042                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2043                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2044                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2045                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2046         }
2047         if (pb->set_method) {
2048                 semaidx = table->next_idx ++;
2049                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2050                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2051                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2052                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2053         }
2054         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2055                 guint32 field_type = 0;
2056                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2057                 table->rows ++;
2058                 alloc_table (table, table->rows);
2059                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2060                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2061                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2062                 values [MONO_CONSTANT_TYPE] = field_type;
2063                 values [MONO_CONSTANT_PADDING] = 0;
2064         }
2065 }
2066
2067 static void
2068 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2069 {
2070         MonoDynamicTable *table;
2071         guint32 *values;
2072         guint num_methods = 0;
2073         guint32 semaidx;
2074
2075         /* 
2076          * we need to set things in the following tables:
2077          * EVENTMAP (info already filled in _get_type_info ())
2078          * EVENT    (rows already preallocated in _get_type_info ())
2079          * METHOD      (method info already done with the generic method code)
2080          * METHODSEMANTICS
2081          */
2082         table = &assembly->tables [MONO_TABLE_EVENT];
2083         eb->table_idx = table->next_idx ++;
2084         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2085         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2086         values [MONO_EVENT_FLAGS] = eb->attrs;
2087         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2088
2089         /*
2090          * FIXME: we still don't handle 'other' methods 
2091          */
2092         if (eb->add_method) num_methods ++;
2093         if (eb->remove_method) num_methods ++;
2094         if (eb->raise_method) num_methods ++;
2095
2096         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2097         table->rows += num_methods;
2098         alloc_table (table, table->rows);
2099
2100         if (eb->add_method) {
2101                 semaidx = table->next_idx ++;
2102                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2103                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2104                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2105                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2106         }
2107         if (eb->remove_method) {
2108                 semaidx = table->next_idx ++;
2109                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2110                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2111                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2112                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2113         }
2114         if (eb->raise_method) {
2115                 semaidx = table->next_idx ++;
2116                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2117                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2118                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2119                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2120         }
2121 }
2122
2123 static void
2124 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2125 {
2126         MonoDynamicTable *table;
2127         guint32 num_constraints, i;
2128         guint32 *values;
2129         guint32 table_idx;
2130
2131         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2132         num_constraints = gparam->iface_constraints ?
2133                 mono_array_length (gparam->iface_constraints) : 0;
2134         table->rows += num_constraints;
2135         if (gparam->base_type)
2136                 table->rows++;
2137         alloc_table (table, table->rows);
2138
2139         if (gparam->base_type) {
2140                 table_idx = table->next_idx ++;
2141                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2142
2143                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2144                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2145                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2146         }
2147
2148         for (i = 0; i < num_constraints; i++) {
2149                 MonoReflectionType *constraint = mono_array_get (
2150                         gparam->iface_constraints, gpointer, i);
2151
2152                 table_idx = table->next_idx ++;
2153                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2154
2155                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2156                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2157                         assembly, mono_reflection_type_get_handle (constraint));
2158         }
2159 }
2160
2161 static void
2162 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2163 {
2164         GenericParamTableEntry *entry;
2165
2166         /*
2167          * The GenericParam table must be sorted according to the `owner' field.
2168          * We need to do this sorting prior to writing the GenericParamConstraint
2169          * table, since we have to use the final GenericParam table indices there
2170          * and they must also be sorted.
2171          */
2172
2173         entry = g_new0 (GenericParamTableEntry, 1);
2174         entry->owner = owner;
2175         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2176         MOVING_GC_REGISTER (&entry->gparam);
2177         entry->gparam = gparam;
2178         
2179         g_ptr_array_add (assembly->gen_params, entry);
2180 }
2181
2182 static void
2183 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2184 {
2185         MonoDynamicTable *table;
2186         MonoGenericParam *param;
2187         guint32 *values;
2188         guint32 table_idx;
2189
2190         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2191         table_idx = table->next_idx ++;
2192         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2193
2194         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2195
2196         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2197         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2198         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2199         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2200
2201         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2202
2203         encode_constraints (entry->gparam, table_idx, assembly);
2204 }
2205
2206 static guint32
2207 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2208 {
2209         MonoDynamicTable *table;
2210         guint32 token;
2211         guint32 *values;
2212         guint32 cols [MONO_ASSEMBLY_SIZE];
2213         const char *pubkey;
2214         guint32 publen;
2215
2216         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2217                 return token;
2218
2219         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2220                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2221                 token = table->next_idx ++;
2222                 table->rows ++;
2223                 alloc_table (table, table->rows);
2224                 values = table->values + token * MONO_MODULEREF_SIZE;
2225                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2226
2227                 token <<= MONO_RESOLTION_SCOPE_BITS;
2228                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2229                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2230
2231                 return token;
2232         }
2233         
2234         if (image->assembly->dynamic)
2235                 /* FIXME: */
2236                 memset (cols, 0, sizeof (cols));
2237         else {
2238                 /* image->assembly->image is the manifest module */
2239                 image = image->assembly->image;
2240                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2241         }
2242
2243         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2244         token = table->next_idx ++;
2245         table->rows ++;
2246         alloc_table (table, table->rows);
2247         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2248         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2249         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2250         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2251         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2252         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2253         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2254         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2255         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2256
2257         if (strcmp ("", image->assembly->aname.culture)) {
2258                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2259                                 image->assembly->aname.culture);
2260         }
2261
2262         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2263                 guchar pubtoken [9];
2264                 pubtoken [0] = 8;
2265                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2266                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2267         } else {
2268                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2269         }
2270         token <<= MONO_RESOLTION_SCOPE_BITS;
2271         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2272         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2273         return token;
2274 }
2275
2276 static guint32
2277 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2278 {
2279         MonoDynamicTable *table;
2280         guint32 *values;
2281         guint32 token;
2282         SigBuffer buf;
2283
2284         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2285                 return token;
2286
2287         sigbuffer_init (&buf, 32);
2288         switch (type->type) {
2289         case MONO_TYPE_FNPTR:
2290         case MONO_TYPE_PTR:
2291         case MONO_TYPE_SZARRAY:
2292         case MONO_TYPE_ARRAY:
2293         case MONO_TYPE_VAR:
2294         case MONO_TYPE_MVAR:
2295         case MONO_TYPE_GENERICINST:
2296                 encode_type (assembly, type, &buf);
2297                 break;
2298         case MONO_TYPE_CLASS:
2299         case MONO_TYPE_VALUETYPE: {
2300                 MonoClass *k = mono_class_from_mono_type (type);
2301                 if (!k || !k->generic_container) {
2302                         sigbuffer_free (&buf);
2303                         return 0;
2304                 }
2305                 encode_type (assembly, type, &buf);
2306                 break;
2307         }
2308         default:
2309                 sigbuffer_free (&buf);
2310                 return 0;
2311         }
2312
2313         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2314         if (assembly->save) {
2315                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2316                 alloc_table (table, table->rows + 1);
2317                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2318                 values [MONO_TYPESPEC_SIGNATURE] = token;
2319         }
2320         sigbuffer_free (&buf);
2321
2322         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2323         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2324         table->next_idx ++;
2325         return token;
2326 }
2327
2328 static guint32
2329 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2330 {
2331         MonoDynamicTable *table;
2332         guint32 *values;
2333         guint32 token, scope, enclosing;
2334         MonoClass *klass;
2335
2336         /* if the type requires a typespec, we must try that first*/
2337         if (try_typespec && (token = create_typespec (assembly, type)))
2338                 return token;
2339         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2340         if (token)
2341                 return token;
2342         klass = mono_class_from_mono_type (type);
2343         if (!klass)
2344                 klass = mono_class_from_mono_type (type);
2345
2346         /*
2347          * If it's in the same module and not a generic type parameter:
2348          */
2349         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2350                         (type->type != MONO_TYPE_MVAR)) {
2351                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2352                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2353                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2354                 return token;
2355         }
2356
2357         if (klass->nested_in) {
2358                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2359                 /* get the typeref idx of the enclosing type */
2360                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2361                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2362         } else {
2363                 scope = resolution_scope_from_image (assembly, klass->image);
2364         }
2365         table = &assembly->tables [MONO_TABLE_TYPEREF];
2366         if (assembly->save) {
2367                 alloc_table (table, table->rows + 1);
2368                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2369                 values [MONO_TYPEREF_SCOPE] = scope;
2370                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2371                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2372         }
2373         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2374         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2375         table->next_idx ++;
2376         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2377         return token;
2378 }
2379
2380 /*
2381  * Despite the name, we handle also TypeSpec (with the above helper).
2382  */
2383 static guint32
2384 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2385 {
2386         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2387 }
2388
2389 #ifndef DISABLE_REFLECTION_EMIT
2390 static guint32
2391 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2392 {
2393         MonoDynamicTable *table;
2394         guint32 *values;
2395         guint32 token, pclass;
2396
2397         switch (parent & MONO_TYPEDEFORREF_MASK) {
2398         case MONO_TYPEDEFORREF_TYPEREF:
2399                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2400                 break;
2401         case MONO_TYPEDEFORREF_TYPESPEC:
2402                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2403                 break;
2404         case MONO_TYPEDEFORREF_TYPEDEF:
2405                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2406                 break;
2407         default:
2408                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2409                 return 0;
2410         }
2411         /* extract the index */
2412         parent >>= MONO_TYPEDEFORREF_BITS;
2413
2414         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2415
2416         if (assembly->save) {
2417                 alloc_table (table, table->rows + 1);
2418                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2419                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2420                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2421                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2422         }
2423
2424         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2425         table->next_idx ++;
2426
2427         return token;
2428 }
2429
2430 /*
2431  * Insert a memberef row into the metadata: the token that point to the memberref
2432  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2433  * mono_image_get_fieldref_token()).
2434  * The sig param is an index to an already built signature.
2435  */
2436 static guint32
2437 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2438 {
2439         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2440         return mono_image_add_memberef_row (assembly, parent, name, sig);
2441 }
2442
2443
2444 static guint32
2445 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2446 {
2447         guint32 token;
2448         MonoMethodSignature *sig;
2449         
2450         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2451
2452         if (create_typespec) {
2453                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2454                 if (token)
2455                         return token;
2456         } 
2457
2458         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2459         if (token && !create_typespec)
2460                 return token;
2461
2462         g_assert (!method->is_inflated);
2463         if (!token) {
2464                 /*
2465                  * A methodref signature can't contain an unmanaged calling convention.
2466                  */
2467                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2468                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2469                         sig->call_convention = MONO_CALL_DEFAULT;
2470                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2471                         method->name,  method_encode_signature (assembly, sig));
2472                 g_free (sig);
2473                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2474         }
2475
2476         if (create_typespec) {
2477                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2478                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2479                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2480
2481                 if (assembly->save) {
2482                         guint32 *values;
2483
2484                         alloc_table (table, table->rows + 1);
2485                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2486                         values [MONO_METHODSPEC_METHOD] = token;
2487                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2488                 }
2489
2490                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2491                 table->next_idx ++;
2492                 /*methodspec and memberef tokens are diferent, */
2493                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2494                 return token;
2495         }
2496         return token;
2497 }
2498
2499 static guint32
2500 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2501 {
2502         guint32 token, parent, sig;
2503         ReflectionMethodBuilder rmb;
2504         char *name;
2505         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2506         
2507         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2508         if (token)
2509                 return token;
2510
2511         name = mono_string_to_utf8 (method->name);
2512         reflection_methodbuilder_from_method_builder (&rmb, method);
2513
2514         /*
2515          * A methodref signature can't contain an unmanaged calling convention.
2516          * Since some flags are encoded as part of call_conv, we need to check against it.
2517         */
2518         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2519                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2520
2521         sig = method_builder_encode_signature (assembly, &rmb);
2522
2523         if (tb->generic_params)
2524                 parent = create_generic_typespec (assembly, tb);
2525         else
2526                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2527
2528         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2529
2530         g_free (name);
2531         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2532         return token;
2533 }
2534
2535 static guint32
2536 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2537                                      const gchar *name, guint32 sig)
2538 {
2539         MonoDynamicTable *table;
2540         guint32 token;
2541         guint32 *values;
2542         
2543         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2544
2545         if (assembly->save) {
2546                 alloc_table (table, table->rows + 1);
2547                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2548                 values [MONO_MEMBERREF_CLASS] = original;
2549                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2550                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2551         }
2552
2553         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2554         table->next_idx ++;
2555
2556         return token;
2557 }
2558
2559 static guint32
2560 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2561 {
2562         SigBuffer buf;
2563         int i;
2564         guint32 nparams = mono_array_length (mb->generic_params);
2565         guint32 idx;
2566
2567         if (!assembly->save)
2568                 return 0;
2569
2570         sigbuffer_init (&buf, 32);
2571
2572         sigbuffer_add_value (&buf, 0xa);
2573         sigbuffer_add_value (&buf, nparams);
2574
2575         for (i = 0; i < nparams; i++) {
2576                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2577                 sigbuffer_add_value (&buf, i);
2578         }
2579
2580         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2581         sigbuffer_free (&buf);
2582         return idx;
2583 }
2584
2585 static guint32
2586 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2587 {
2588         MonoDynamicTable *table;
2589         guint32 *values;
2590         guint32 token, mtoken = 0;
2591
2592         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2593         if (token)
2594                 return token;
2595
2596         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2597
2598         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2599         switch (mono_metadata_token_table (mtoken)) {
2600         case MONO_TABLE_MEMBERREF:
2601                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2602                 break;
2603         case MONO_TABLE_METHOD:
2604                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2605                 break;
2606         default:
2607                 g_assert_not_reached ();
2608         }
2609
2610         if (assembly->save) {
2611                 alloc_table (table, table->rows + 1);
2612                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2613                 values [MONO_METHODSPEC_METHOD] = mtoken;
2614                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2615         }
2616
2617         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2618         table->next_idx ++;
2619
2620         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2621         return token;
2622 }
2623
2624 static guint32
2625 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2626 {
2627         guint32 token;
2628
2629         if (mb->generic_params && create_methodspec) 
2630                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2631
2632         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2633         if (token)
2634                 return token;
2635
2636         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2637         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2638         return token;
2639 }
2640
2641 static guint32
2642 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2643 {
2644         guint32 token, parent, sig;
2645         ReflectionMethodBuilder rmb;
2646         char *name;
2647         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2648         
2649         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2650         if (token)
2651                 return token;
2652
2653         g_assert (tb->generic_params);
2654
2655         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2656
2657         parent = create_generic_typespec (assembly, tb);
2658         name = mono_string_to_utf8 (rmb.name);
2659         sig = method_builder_encode_signature (assembly, &rmb);
2660
2661         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2662
2663         g_free (name);
2664         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2665         return token;
2666 }
2667 #endif
2668
2669 static gboolean
2670 is_field_on_inst (MonoClassField *field)
2671 {
2672         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2673 }
2674
2675 /*
2676  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2677  */
2678 static MonoType*
2679 get_field_on_inst_generic_type (MonoClassField *field)
2680 {
2681         MonoClass *class, *gtd;
2682         MonoDynamicGenericClass *dgclass;
2683         int field_index;
2684
2685         g_assert (is_field_on_inst (field));
2686
2687         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2688
2689         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2690                 field_index = field - dgclass->fields;
2691                 return dgclass->field_generic_types [field_index];              
2692         }
2693
2694         class = field->parent;
2695         gtd = class->generic_class->container_class;
2696
2697         if (field >= class->fields && field - class->fields < class->field.count) {
2698                 field_index = field - class->fields;
2699                 return gtd->fields [field_index].type;
2700         }
2701
2702         g_assert_not_reached ();
2703         return 0;
2704 }
2705
2706 #ifndef DISABLE_REFLECTION_EMIT
2707 static guint32
2708 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2709 {
2710         MonoType *type;
2711         guint32 token;
2712         MonoClassField *field;
2713
2714         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2715         if (token)
2716                 return token;
2717         g_assert (f->field->parent);
2718
2719         field = f->field;
2720         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2721                 int index = field - field->parent->fields;
2722                 type = field->parent->generic_class->container_class->fields [index].type;
2723         } else {
2724                 if (is_field_on_inst (f->field))
2725                         type = get_field_on_inst_generic_type (f->field);
2726                 else
2727                         type = f->field->type;
2728         }
2729         token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg, 
2730                                                                                         mono_field_get_name (f->field),  
2731                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2732         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2733         return token;
2734 }
2735
2736 static guint32
2737 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2738 {
2739         guint32 token;
2740         MonoClass *klass;
2741         MonoGenericClass *gclass;
2742         MonoDynamicGenericClass *dgclass;
2743         MonoType *type;
2744         char *name;
2745
2746         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2747         if (token)
2748                 return token;
2749         if (is_sre_field_builder (mono_object_class (f->fb))) {
2750                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2751                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2752                 klass = mono_class_from_mono_type (type);
2753                 gclass = type->data.generic_class;
2754                 g_assert (gclass->is_dynamic);
2755                 dgclass = (MonoDynamicGenericClass *) gclass;
2756
2757                 name = mono_string_to_utf8 (fb->name);
2758                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2759                                                                                                 field_encode_signature (assembly, fb));
2760                 g_free (name);          
2761         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2762                 guint32 sig;
2763                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2764
2765                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2766                 klass = mono_class_from_mono_type (type);
2767
2768                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2769                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2770         } else {
2771                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2772                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2773         }
2774
2775         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2776         return token;
2777 }
2778
2779 static guint32
2780 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2781 {
2782         guint32 sig, token;
2783         MonoClass *klass;
2784         MonoGenericClass *gclass;
2785         MonoType *type;
2786
2787         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2788
2789         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2790         if (token)
2791                 return token;
2792
2793         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2794                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2795                 MonoDynamicGenericClass *dgclass;
2796                 ReflectionMethodBuilder rmb;
2797                 char *name;
2798
2799                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2800                 klass = mono_class_from_mono_type (type);
2801
2802                 gclass = type->data.generic_class;
2803                 g_assert (gclass->is_dynamic);
2804                 dgclass = (MonoDynamicGenericClass *) gclass;
2805
2806                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2807
2808                 name = mono_string_to_utf8 (rmb.name);
2809
2810                 sig = method_builder_encode_signature (assembly, &rmb);
2811
2812                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2813                 g_free (name);
2814         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2815                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2816
2817                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2818                 klass = mono_class_from_mono_type (type);
2819
2820                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2821                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2822         } else {
2823                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2824                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2825         }
2826
2827
2828         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2829         return token;
2830 }
2831
2832 static MonoMethod*
2833 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2834 {
2835         MonoClass *klass;
2836         MonoGenericContext tmp_context;
2837         MonoType **type_argv;
2838         MonoGenericInst *ginst;
2839         MonoMethod *method, *inflated;
2840         int count, i;
2841
2842         method = inflate_method (m->inst, (MonoObject*)m->mb);
2843
2844         klass = method->klass;
2845
2846         if (m->method_args == NULL)
2847                 return method;
2848
2849         if (method->is_inflated)
2850                 method = ((MonoMethodInflated *) method)->declaring;
2851
2852         count = mono_array_length (m->method_args);
2853
2854         type_argv = g_new0 (MonoType *, count);
2855         for (i = 0; i < count; i++) {
2856                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2857                 type_argv [i] = mono_reflection_type_get_handle (garg);
2858         }
2859         ginst = mono_metadata_get_generic_inst (count, type_argv);
2860         g_free (type_argv);
2861
2862         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2863         tmp_context.method_inst = ginst;
2864
2865         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2866         return inflated;
2867 }
2868
2869 static guint32
2870 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2871 {
2872         guint32 sig, token = 0;
2873         MonoType *type;
2874         MonoClass *klass;
2875
2876         if (m->method_args) {
2877                 MonoMethod *inflated;
2878
2879                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2880                 if (create_methodspec)
2881                         token = mono_image_get_methodspec_token (assembly, inflated);
2882                 else
2883                         token = mono_image_get_inflated_method_token (assembly, inflated);
2884                 return token;
2885         }
2886
2887         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2888         if (token)
2889                 return token;
2890
2891         if (is_sre_method_builder (mono_object_class (m->mb))) {
2892                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2893                 MonoGenericClass *gclass;
2894                 ReflectionMethodBuilder rmb;
2895                 char *name;
2896
2897                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2898                 klass = mono_class_from_mono_type (type);
2899                 gclass = type->data.generic_class;
2900                 g_assert (gclass->is_dynamic);
2901
2902                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2903
2904                 name = mono_string_to_utf8 (rmb.name);
2905
2906                 sig = method_builder_encode_signature (assembly, &rmb);
2907
2908                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2909                 g_free (name);          
2910         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2911                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2912
2913                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2914                 klass = mono_class_from_mono_type (type);
2915
2916                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2917                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2918         } else {
2919                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2920                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2921         }
2922
2923         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2924         return token;
2925 }
2926
2927 static guint32
2928 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2929 {
2930         SigBuffer buf;
2931         int i;
2932         guint32 nparams = context->method_inst->type_argc;
2933         guint32 idx;
2934
2935         if (!assembly->save)
2936                 return 0;
2937
2938         sigbuffer_init (&buf, 32);
2939         /*
2940          * FIXME: vararg, explicit_this, differenc call_conv values...
2941          */
2942         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2943         sigbuffer_add_value (&buf, nparams);
2944
2945         for (i = 0; i < nparams; i++)
2946                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2947
2948         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2949         sigbuffer_free (&buf);
2950         return idx;
2951 }
2952
2953 static guint32
2954 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2955 {
2956         MonoDynamicTable *table;
2957         guint32 *values;
2958         guint32 token, mtoken = 0, sig;
2959         MonoMethodInflated *imethod;
2960         MonoMethod *declaring;
2961
2962         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2963
2964         g_assert (method->is_inflated);
2965         imethod = (MonoMethodInflated *) method;
2966         declaring = imethod->declaring;
2967
2968         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2969         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2970
2971         if (!mono_method_signature (declaring)->generic_param_count)
2972                 return mtoken;
2973
2974         switch (mono_metadata_token_table (mtoken)) {
2975         case MONO_TABLE_MEMBERREF:
2976                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2977                 break;
2978         case MONO_TABLE_METHOD:
2979                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2980                 break;
2981         default:
2982                 g_assert_not_reached ();
2983         }
2984
2985         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2986
2987         if (assembly->save) {
2988                 alloc_table (table, table->rows + 1);
2989                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2990                 values [MONO_METHODSPEC_METHOD] = mtoken;
2991                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2992         }
2993
2994         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2995         table->next_idx ++;
2996
2997         return token;
2998 }
2999
3000 static guint32
3001 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3002 {
3003         MonoMethodInflated *imethod;
3004         guint32 token;
3005         
3006         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3007         if (token)
3008                 return token;
3009
3010         g_assert (method->is_inflated);
3011         imethod = (MonoMethodInflated *) method;
3012
3013         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3014                 token = method_encode_methodspec (assembly, method);
3015         } else {
3016                 guint32 sig = method_encode_signature (
3017                         assembly, mono_method_signature (imethod->declaring));
3018                 token = mono_image_get_memberref_token (
3019                         assembly, &method->klass->byval_arg, method->name, sig);
3020         }
3021
3022         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3023         return token;
3024 }
3025
3026 static guint32
3027 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3028 {
3029         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3030         guint32 sig, token;
3031
3032         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3033         token = mono_image_get_memberref_token (
3034                 assembly, &m->klass->byval_arg, m->name, sig);
3035
3036         return token;
3037 }
3038
3039 static guint32
3040 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3041 {
3042         MonoDynamicTable *table;
3043         MonoClass *klass;
3044         MonoType *type;
3045         guint32 *values;
3046         guint32 token;
3047         SigBuffer buf;
3048         int count, i;
3049
3050         /*
3051          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3052          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3053          * Because of this, we must not insert it into the `typeref' hash table.
3054          */
3055         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3056         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3057         if (token)
3058                 return token;
3059
3060         sigbuffer_init (&buf, 32);
3061
3062         g_assert (tb->generic_params);
3063         klass = mono_class_from_mono_type (type);
3064
3065         if (tb->generic_container)
3066                 mono_reflection_create_generic_class (tb);
3067
3068         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3069         g_assert (klass->generic_container);
3070         sigbuffer_add_value (&buf, klass->byval_arg.type);
3071         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3072
3073         count = mono_array_length (tb->generic_params);
3074         sigbuffer_add_value (&buf, count);
3075         for (i = 0; i < count; i++) {
3076                 MonoReflectionGenericParam *gparam;
3077
3078                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3079
3080                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3081         }
3082
3083         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3084
3085         if (assembly->save) {
3086                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3087                 alloc_table (table, table->rows + 1);
3088                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3089                 values [MONO_TYPESPEC_SIGNATURE] = token;
3090         }
3091         sigbuffer_free (&buf);
3092
3093         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3094         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3095         table->next_idx ++;
3096         return token;
3097 }
3098
3099 /*
3100  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3101  */
3102 static MonoType*
3103 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3104 {
3105         int i, count, len, pos;
3106         MonoType *t;
3107
3108         count = 0;
3109         if (modreq)
3110                 count += mono_array_length (modreq);
3111         if (modopt)
3112                 count += mono_array_length (modopt);
3113
3114         if (count == 0)
3115                 return mono_metadata_type_dup (NULL, type);
3116
3117         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3118         t = g_malloc (len);
3119         memcpy (t, type, MONO_SIZEOF_TYPE);
3120
3121         t->num_mods = count;
3122         pos = 0;
3123         if (modreq) {
3124                 for (i = 0; i < mono_array_length (modreq); ++i) {
3125                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3126                         t->modifiers [pos].required = 1;
3127                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3128                         pos ++;
3129                 }
3130         }
3131         if (modopt) {
3132                 for (i = 0; i < mono_array_length (modopt); ++i) {
3133                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3134                         t->modifiers [pos].required = 0;
3135                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3136                         pos ++;
3137                 }
3138         }
3139
3140         return t;
3141 }
3142
3143 static guint32
3144 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3145 {
3146         MonoDynamicTable *table;
3147         MonoClass *klass;
3148         MonoType *custom = NULL;
3149         guint32 *values;
3150         guint32 token, pclass, parent, sig;
3151         gchar *name;
3152
3153         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3154         if (token)
3155                 return token;
3156
3157         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3158         name = mono_string_to_utf8 (fb->name);
3159
3160         /* fb->type does not include the custom modifiers */
3161         /* FIXME: We should do this in one place when a fieldbuilder is created */
3162         if (fb->modreq || fb->modopt) {
3163                 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3164                 sig = fieldref_encode_signature (assembly, NULL, custom);
3165                 g_free (custom);
3166         } else {
3167                 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3168         }
3169
3170         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3171         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3172         
3173         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3174         parent >>= MONO_TYPEDEFORREF_BITS;
3175
3176         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3177
3178         if (assembly->save) {
3179                 alloc_table (table, table->rows + 1);
3180                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3181                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3182                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3183                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3184         }
3185
3186         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3187         table->next_idx ++;
3188         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3189         g_free (name);
3190         return token;
3191 }
3192
3193 static guint32
3194 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3195 {
3196         SigBuffer buf;
3197         guint32 nargs;
3198         guint32 size;
3199         guint32 i, idx;
3200
3201         if (!assembly->save)
3202                 return 0;
3203
3204         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3205         g_assert (helper->type == 2);
3206
3207         if (helper->arguments)
3208                 nargs = mono_array_length (helper->arguments);
3209         else
3210                 nargs = 0;
3211
3212         size = 10 + (nargs * 10);
3213         
3214         sigbuffer_init (&buf, 32);
3215
3216         /* Encode calling convention */
3217         /* Change Any to Standard */
3218         if ((helper->call_conv & 0x03) == 0x03)
3219                 helper->call_conv = 0x01;
3220         /* explicit_this implies has_this */
3221         if (helper->call_conv & 0x40)
3222                 helper->call_conv &= 0x20;
3223
3224         if (helper->call_conv == 0) { /* Unmanaged */
3225                 idx = helper->unmanaged_call_conv - 1;
3226         } else {
3227                 /* Managed */
3228                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3229                 if (helper->call_conv & 0x02) /* varargs */
3230                         idx += 0x05;
3231         }
3232
3233         sigbuffer_add_byte (&buf, idx);
3234         sigbuffer_add_value (&buf, nargs);
3235         encode_reflection_type (assembly, helper->return_type, &buf);
3236         for (i = 0; i < nargs; ++i) {
3237                 MonoArray *modreqs = NULL;
3238                 MonoArray *modopts = NULL;
3239                 MonoReflectionType *pt;
3240
3241                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3242                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3243                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3244                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3245
3246                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3247                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3248                 encode_reflection_type (assembly, pt, &buf);
3249         }
3250         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3251         sigbuffer_free (&buf);
3252
3253         return idx;
3254 }
3255
3256 static guint32 
3257 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3258 {
3259         guint32 idx;
3260         MonoDynamicTable *table;
3261         guint32 *values;
3262
3263         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3264         idx = table->next_idx ++;
3265         table->rows ++;
3266         alloc_table (table, table->rows);
3267         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3268
3269         values [MONO_STAND_ALONE_SIGNATURE] =
3270                 mono_reflection_encode_sighelper (assembly, helper);
3271
3272         return idx;
3273 }
3274
3275 static int
3276 reflection_cc_to_file (int call_conv) {
3277         switch (call_conv & 0x3) {
3278         case 0:
3279         case 1: return MONO_CALL_DEFAULT;
3280         case 2: return MONO_CALL_VARARG;
3281         default:
3282                 g_assert_not_reached ();
3283         }
3284         return 0;
3285 }
3286 #endif /* !DISABLE_REFLECTION_EMIT */
3287
3288 typedef struct {
3289         MonoType *parent;
3290         MonoMethodSignature *sig;
3291         char *name;
3292         guint32 token;
3293 } ArrayMethod;
3294
3295 #ifndef DISABLE_REFLECTION_EMIT
3296 static guint32
3297 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3298 {
3299         guint32 nparams, i;
3300         GList *tmp;
3301         char *name;
3302         MonoMethodSignature *sig;
3303         ArrayMethod *am;
3304         MonoType *mtype;
3305
3306         name = mono_string_to_utf8 (m->name);
3307         nparams = mono_array_length (m->parameters);
3308         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3309         sig->hasthis = 1;
3310         sig->sentinelpos = -1;
3311         sig->call_convention = reflection_cc_to_file (m->call_conv);
3312         sig->param_count = nparams;
3313         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3314         mtype = mono_reflection_type_get_handle (m->parent);
3315         for (i = 0; i < nparams; ++i)
3316                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3317
3318         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3319                 am = tmp->data;
3320                 if (strcmp (name, am->name) == 0 && 
3321                                 mono_metadata_type_equal (am->parent, mtype) &&
3322                                 mono_metadata_signature_equal (am->sig, sig)) {
3323                         g_free (name);
3324                         g_free (sig);
3325                         m->table_idx = am->token & 0xffffff;
3326                         return am->token;
3327                 }
3328         }
3329         am = g_new0 (ArrayMethod, 1);
3330         am->name = name;
3331         am->sig = sig;
3332         am->parent = mtype;
3333         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3334                 method_encode_signature (assembly, sig));
3335         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3336         m->table_idx = am->token & 0xffffff;
3337         return am->token;
3338 }
3339
3340 /*
3341  * Insert into the metadata tables all the info about the TypeBuilder tb.
3342  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3343  */
3344 static void
3345 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3346 {
3347         MonoDynamicTable *table;
3348         guint *values;
3349         int i, is_object = 0, is_system = 0;
3350         char *n;
3351
3352         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3353         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3354         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3355         n = mono_string_to_utf8 (tb->name);
3356         if (strcmp (n, "Object") == 0)
3357                 is_object++;
3358         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3359         g_free (n);
3360         n = mono_string_to_utf8 (tb->nspace);
3361         if (strcmp (n, "System") == 0)
3362                 is_system++;
3363         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3364         g_free (n);
3365         if (tb->parent && !(is_system && is_object) && 
3366                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3367                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3368         } else {
3369                 values [MONO_TYPEDEF_EXTENDS] = 0;
3370         }
3371         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3372         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3373
3374         /*
3375          * if we have explicitlayout or sequentiallayouts, output data in the
3376          * ClassLayout table.
3377          */
3378         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3379                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3380                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3381                 table->rows++;
3382                 alloc_table (table, table->rows);
3383                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3384                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3385                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3386                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3387         }
3388
3389         /* handle interfaces */
3390         if (tb->interfaces) {
3391                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3392                 i = table->rows;
3393                 table->rows += mono_array_length (tb->interfaces);
3394                 alloc_table (table, table->rows);
3395                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3396                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3397                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3398                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3399                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3400                         values += MONO_INTERFACEIMPL_SIZE;
3401                 }
3402         }
3403
3404         /* handle fields */
3405         if (tb->fields) {
3406                 table = &assembly->tables [MONO_TABLE_FIELD];
3407                 table->rows += tb->num_fields;
3408                 alloc_table (table, table->rows);
3409                 for (i = 0; i < tb->num_fields; ++i)
3410                         mono_image_get_field_info (
3411                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3412         }
3413
3414         /* handle constructors */
3415         if (tb->ctors) {
3416                 table = &assembly->tables [MONO_TABLE_METHOD];
3417                 table->rows += mono_array_length (tb->ctors);
3418                 alloc_table (table, table->rows);
3419                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3420                         mono_image_get_ctor_info (domain,
3421                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3422         }
3423
3424         /* handle methods */
3425         if (tb->methods) {
3426                 table = &assembly->tables [MONO_TABLE_METHOD];
3427                 table->rows += tb->num_methods;
3428                 alloc_table (table, table->rows);
3429                 for (i = 0; i < tb->num_methods; ++i)
3430                         mono_image_get_method_info (
3431                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3432         }
3433
3434         /* Do the same with properties etc.. */
3435         if (tb->events && mono_array_length (tb->events)) {
3436                 table = &assembly->tables [MONO_TABLE_EVENT];
3437                 table->rows += mono_array_length (tb->events);
3438                 alloc_table (table, table->rows);
3439                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3440                 table->rows ++;
3441                 alloc_table (table, table->rows);
3442                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3443                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3444                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3445                 for (i = 0; i < mono_array_length (tb->events); ++i)
3446                         mono_image_get_event_info (
3447                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3448         }
3449         if (tb->properties && mono_array_length (tb->properties)) {
3450                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3451                 table->rows += mono_array_length (tb->properties);
3452                 alloc_table (table, table->rows);
3453                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3454                 table->rows ++;
3455                 alloc_table (table, table->rows);
3456                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3457                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3458                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3459                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3460                         mono_image_get_property_info (
3461                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3462         }
3463
3464         /* handle generic parameters */
3465         if (tb->generic_params) {
3466                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3467                 table->rows += mono_array_length (tb->generic_params);
3468                 alloc_table (table, table->rows);
3469                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3470                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3471
3472                         mono_image_get_generic_param_info (
3473                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3474                 }
3475         }
3476
3477         mono_image_add_decl_security (assembly, 
3478                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3479
3480         if (tb->subtypes) {
3481                 MonoDynamicTable *ntable;
3482                 
3483                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3484                 ntable->rows += mono_array_length (tb->subtypes);
3485                 alloc_table (ntable, ntable->rows);
3486                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3487
3488                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3489                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3490
3491                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3492                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3493                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3494                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3495                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3496                                 ntable->next_idx, ntable->rows);*/
3497                         values += MONO_NESTED_CLASS_SIZE;
3498                         ntable->next_idx++;
3499                 }
3500         }
3501 }
3502 #endif
3503
3504 static void
3505 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3506 {
3507         int i;
3508
3509         g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3510
3511         if (!type->subtypes)
3512                 return;
3513
3514         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3515                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3516                 collect_types (types, subtype);
3517         }
3518 }
3519
3520 static gint
3521 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3522 {
3523         if ((*type1)->table_idx < (*type2)->table_idx)
3524                 return -1;
3525         else
3526                 if ((*type1)->table_idx > (*type2)->table_idx)
3527                         return 1;
3528         else
3529                 return 0;
3530 }
3531
3532 static void
3533 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3534         int i;
3535
3536         if (!pinfo)
3537                 return;
3538         for (i = 0; i < mono_array_length (pinfo); ++i) {
3539                 MonoReflectionParamBuilder *pb;
3540                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3541                 if (!pb)
3542                         continue;
3543                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3544         }
3545 }
3546
3547 static void
3548 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3549         int i;
3550         
3551         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3552         if (tb->fields) {
3553                 for (i = 0; i < tb->num_fields; ++i) {
3554                         MonoReflectionFieldBuilder* fb;
3555                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3556                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3557                 }
3558         }
3559         if (tb->events) {
3560                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3561                         MonoReflectionEventBuilder* eb;
3562                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3563                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3564                 }
3565         }
3566         if (tb->properties) {
3567                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3568                         MonoReflectionPropertyBuilder* pb;
3569                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3570                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3571                 }
3572         }
3573         if (tb->ctors) {
3574                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3575                         MonoReflectionCtorBuilder* cb;
3576                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3577                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3578                         params_add_cattrs (assembly, cb->pinfo);
3579                 }
3580         }
3581
3582         if (tb->methods) {
3583                 for (i = 0; i < tb->num_methods; ++i) {
3584                         MonoReflectionMethodBuilder* mb;
3585                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3586                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3587                         params_add_cattrs (assembly, mb->pinfo);
3588                 }
3589         }
3590
3591         if (tb->subtypes) {
3592                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3593                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3594         }
3595 }
3596
3597 static void
3598 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3599 {
3600         int i;
3601         
3602         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3603
3604         if (moduleb->global_methods) {
3605                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3606                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3607                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3608                         params_add_cattrs (assembly, mb->pinfo);
3609                 }
3610         }
3611
3612         if (moduleb->global_fields) {
3613                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3614                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3615                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3616                 }
3617         }
3618         
3619         if (moduleb->types) {
3620                 for (i = 0; i < moduleb->num_types; ++i)
3621                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3622         }
3623 }
3624
3625 static void
3626 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3627 {
3628         MonoDynamicTable *table;
3629         guint32 *values;
3630         char blob_size [6];
3631         guchar hash [20];
3632         char *b = blob_size;
3633         char *dir, *path;
3634
3635         table = &assembly->tables [MONO_TABLE_FILE];
3636         table->rows++;
3637         alloc_table (table, table->rows);
3638         values = table->values + table->next_idx * MONO_FILE_SIZE;
3639         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3640         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3641         if (module->image->dynamic) {
3642                 /* This depends on the fact that the main module is emitted last */
3643                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3644                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3645         } else {
3646                 dir = NULL;
3647                 path = g_strdup (module->image->name);
3648         }
3649         mono_sha1_get_digest_from_file (path, hash);
3650         g_free (dir);
3651         g_free (path);
3652         mono_metadata_encode_value (20, b, &b);
3653         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3654         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3655         table->next_idx ++;
3656 }
3657
3658 static void
3659 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3660 {
3661         MonoDynamicTable *table;
3662         int i;
3663
3664         table = &assembly->tables [MONO_TABLE_MODULE];
3665         mb->table_idx = table->next_idx ++;
3666         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3667         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3668         i /= 16;
3669         ++i;
3670         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3671         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3672         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3673         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3674 }
3675
3676 static guint32
3677 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3678         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3679 {
3680         MonoDynamicTable *table;
3681         guint32 *values;
3682         guint32 visib, res;
3683
3684         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3685         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3686                 return 0;
3687
3688         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3689         table->rows++;
3690         alloc_table (table, table->rows);
3691         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3692
3693         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3694         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3695         if (klass->nested_in)
3696                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3697         else
3698                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3699         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3700         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3701
3702         res = table->next_idx;
3703
3704         table->next_idx ++;
3705
3706         /* Emit nested types */
3707         if (klass->ext && klass->ext->nested_classes) {
3708                 GList *tmp;
3709
3710                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3711                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3712         }
3713
3714         return res;
3715 }
3716
3717 static void
3718 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3719         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3720 {
3721         MonoClass *klass;
3722         guint32 idx, i;
3723
3724         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3725
3726         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3727
3728         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3729                                                                                                    parent_index, assembly);
3730
3731         /* 
3732          * Emit nested types
3733          * We need to do this ourselves since klass->nested_classes is not set up.
3734          */
3735         if (tb->subtypes) {
3736                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3737                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3738         }
3739 }
3740
3741 static void
3742 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3743         guint32 module_index, MonoDynamicImage *assembly)
3744 {
3745         MonoImage *image = module->image;
3746         MonoTableInfo  *t;
3747         guint32 i;
3748
3749         t = &image->tables [MONO_TABLE_TYPEDEF];
3750
3751         for (i = 0; i < t->rows; ++i) {
3752                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3753
3754                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3755                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3756         }
3757 }
3758
3759 static void
3760 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3761 {
3762         MonoDynamicTable *table;
3763         guint32 *values;
3764         guint32 scope, scope_idx, impl, current_idx;
3765         gboolean forwarder = TRUE;
3766         gpointer iter = NULL;
3767         MonoClass *nested;
3768
3769         if (klass->nested_in) {
3770                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3771                 forwarder = FALSE;
3772         } else {
3773                 scope = resolution_scope_from_image (assembly, klass->image);
3774                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3775                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3776                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3777         }
3778
3779         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3780
3781         table->rows++;
3782         alloc_table (table, table->rows);
3783         current_idx = table->next_idx;
3784         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3785
3786         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3787         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3788         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3789         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3790         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3791
3792         table->next_idx++;
3793
3794         while ((nested = mono_class_get_nested_types (klass, &iter)))
3795                 add_exported_type (assemblyb, assembly, nested, current_idx);
3796 }
3797
3798 static void
3799 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3800 {
3801         MonoClass *klass;
3802         int i;
3803
3804         if (!assemblyb->type_forwarders)
3805                 return;
3806
3807         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3808                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3809                 MonoType *type;
3810                 if (!t)
3811                         continue;
3812
3813                 type = mono_reflection_type_get_handle (t);
3814                 g_assert (type);
3815
3816                 klass = mono_class_from_mono_type (type);
3817
3818                 add_exported_type (assemblyb, assembly, klass, 0);
3819         }
3820 }
3821
3822 #define align_pointer(base,p)\
3823         do {\
3824                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3825                 if (__diff & 3)\
3826                         (p) += 4 - (__diff & 3);\
3827         } while (0)
3828
3829 static int
3830 compare_constants (const void *a, const void *b)
3831 {
3832         const guint32 *a_values = a;
3833         const guint32 *b_values = b;
3834         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3835 }
3836
3837 static int
3838 compare_semantics (const void *a, const void *b)
3839 {
3840         const guint32 *a_values = a;
3841         const guint32 *b_values = b;
3842         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3843         if (assoc)
3844                 return assoc;
3845         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3846 }
3847
3848 static int
3849 compare_custom_attrs (const void *a, const void *b)
3850 {
3851         const guint32 *a_values = a;
3852         const guint32 *b_values = b;
3853
3854         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3855 }
3856
3857 static int
3858 compare_field_marshal (const void *a, const void *b)
3859 {
3860         const guint32 *a_values = a;
3861         const guint32 *b_values = b;
3862
3863         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3864 }
3865
3866 static int
3867 compare_nested (const void *a, const void *b)
3868 {
3869         const guint32 *a_values = a;
3870         const guint32 *b_values = b;
3871
3872         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3873 }
3874
3875 static int
3876 compare_genericparam (const void *a, const void *b)
3877 {
3878         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3879         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3880
3881         if ((*b_entry)->owner == (*a_entry)->owner)
3882                 return 
3883                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3884                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3885         else
3886                 return (*a_entry)->owner - (*b_entry)->owner;
3887 }
3888
3889 static int
3890 compare_declsecurity_attrs (const void *a, const void *b)
3891 {
3892         const guint32 *a_values = a;
3893         const guint32 *b_values = b;
3894
3895         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3896 }
3897
3898 static int
3899 compare_interface_impl (const void *a, const void *b)
3900 {
3901         const guint32 *a_values = a;
3902         const guint32 *b_values = b;
3903
3904         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3905         if (klass)
3906                 return klass;
3907
3908         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3909 }
3910
3911 static void
3912 pad_heap (MonoDynamicStream *sh)
3913 {
3914         if (sh->index & 3) {
3915                 int sz = 4 - (sh->index & 3);
3916                 memset (sh->data + sh->index, 0, sz);
3917                 sh->index += sz;
3918         }
3919 }
3920
3921 struct StreamDesc {
3922         const char *name;
3923         MonoDynamicStream *stream;
3924 };
3925
3926 /*
3927  * build_compressed_metadata() fills in the blob of data that represents the 
3928  * raw metadata as it will be saved in the PE file. The five streams are output 
3929  * and the metadata tables are comnpressed from the guint32 array representation, 
3930  * to the compressed on-disk format.
3931  */
3932 static void
3933 build_compressed_metadata (MonoDynamicImage *assembly)
3934 {
3935         MonoDynamicTable *table;
3936         int i;
3937         guint64 valid_mask = 0;
3938         guint64 sorted_mask;
3939         guint32 heapt_size = 0;
3940         guint32 meta_size = 256; /* allow for header and other stuff */
3941         guint32 table_offset;
3942         guint32 ntables = 0;
3943         guint64 *int64val;
3944         guint32 *int32val;
3945         guint16 *int16val;
3946         MonoImage *meta;
3947         unsigned char *p;
3948         struct StreamDesc stream_desc [5];
3949
3950         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3951         for (i = 0; i < assembly->gen_params->len; i++){
3952                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3953                 write_generic_param_entry (assembly, entry);
3954         }
3955
3956         stream_desc [0].name  = "#~";
3957         stream_desc [0].stream = &assembly->tstream;
3958         stream_desc [1].name  = "#Strings";
3959         stream_desc [1].stream = &assembly->sheap;
3960         stream_desc [2].name  = "#US";
3961         stream_desc [2].stream = &assembly->us;
3962         stream_desc [3].name  = "#Blob";
3963         stream_desc [3].stream = &assembly->blob;
3964         stream_desc [4].name  = "#GUID";
3965         stream_desc [4].stream = &assembly->guid;
3966         
3967         /* tables that are sorted */
3968         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3969                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3970                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3971                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3972                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3973                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3974                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3975         
3976         /* Compute table sizes */
3977         /* the MonoImage has already been created in mono_image_basic_init() */
3978         meta = &assembly->image;
3979
3980         /* sizes should be multiple of 4 */
3981         pad_heap (&assembly->blob);
3982         pad_heap (&assembly->guid);
3983         pad_heap (&assembly->sheap);
3984         pad_heap (&assembly->us);
3985
3986         /* Setup the info used by compute_sizes () */
3987         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3988         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3989         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3990
3991         meta_size += assembly->blob.index;
3992         meta_size += assembly->guid.index;
3993         meta_size += assembly->sheap.index;
3994         meta_size += assembly->us.index;
3995
3996         for (i=0; i < MONO_TABLE_NUM; ++i)
3997                 meta->tables [i].rows = assembly->tables [i].rows;
3998         
3999         for (i = 0; i < MONO_TABLE_NUM; i++){
4000                 if (meta->tables [i].rows == 0)
4001                         continue;
4002                 valid_mask |= (guint64)1 << i;
4003                 ntables ++;
4004                 meta->tables [i].row_size = mono_metadata_compute_size (
4005                         meta, i, &meta->tables [i].size_bitfield);
4006                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4007         }
4008         heapt_size += 24; /* #~ header size */
4009         heapt_size += ntables * 4;
4010         /* make multiple of 4 */
4011         heapt_size += 3;
4012         heapt_size &= ~3;
4013         meta_size += heapt_size;
4014         meta->raw_metadata = g_malloc0 (meta_size);
4015         p = (unsigned char*)meta->raw_metadata;
4016         /* the metadata signature */
4017         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4018         /* version numbers and 4 bytes reserved */
4019         int16val = (guint16*)p;
4020         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4021         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4022         p += 8;
4023         /* version string */
4024         int32val = (guint32*)p;
4025         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4026         p += 4;
4027         memcpy (p, meta->version, strlen (meta->version));
4028         p += GUINT32_FROM_LE (*int32val);
4029         align_pointer (meta->raw_metadata, p);
4030         int16val = (guint16*)p;
4031         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4032         *int16val = GUINT16_TO_LE (5); /* number of streams */
4033         p += 4;
4034
4035         /*
4036          * write the stream info.
4037          */
4038         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4039         table_offset += 3; table_offset &= ~3;
4040
4041         assembly->tstream.index = heapt_size;
4042         for (i = 0; i < 5; ++i) {
4043                 int32val = (guint32*)p;
4044                 stream_desc [i].stream->offset = table_offset;
4045                 *int32val++ = GUINT32_TO_LE (table_offset);
4046                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4047                 table_offset += GUINT32_FROM_LE (*int32val);
4048                 table_offset += 3; table_offset &= ~3;
4049                 p += 8;
4050                 strcpy ((char*)p, stream_desc [i].name);
4051                 p += strlen (stream_desc [i].name) + 1;
4052                 align_pointer (meta->raw_metadata, p);
4053         }
4054         /* 
4055          * now copy the data, the table stream header and contents goes first.
4056          */
4057         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4058         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4059         int32val = (guint32*)p;
4060         *int32val = GUINT32_TO_LE (0); /* reserved */
4061         p += 4;
4062
4063         *p++ = 2; /* version */
4064         *p++ = 0;
4065
4066         if (meta->idx_string_wide)
4067                 *p |= 0x01;
4068         if (meta->idx_guid_wide)
4069                 *p |= 0x02;
4070         if (meta->idx_blob_wide)
4071                 *p |= 0x04;
4072         ++p;
4073         *p++ = 1; /* reserved */
4074         int64val = (guint64*)p;
4075         *int64val++ = GUINT64_TO_LE (valid_mask);
4076         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4077         p += 16;
4078         int32val = (guint32*)p;
4079         for (i = 0; i < MONO_TABLE_NUM; i++){
4080                 if (meta->tables [i].rows == 0)
4081                         continue;
4082                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4083         }
4084         p = (unsigned char*)int32val;
4085
4086         /* sort the tables that still need sorting */
4087         table = &assembly->tables [MONO_TABLE_CONSTANT];
4088         if (table->rows)
4089                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4090         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4091         if (table->rows)
4092                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4093         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4094         if (table->rows)
4095                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4096         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4097         if (table->rows)
4098                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4099         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4100         if (table->rows)
4101                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4102         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4103         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4104         if (table->rows)
4105                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4106         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4107         if (table->rows)
4108                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4109
4110         /* compress the tables */
4111         for (i = 0; i < MONO_TABLE_NUM; i++){
4112                 int row, col;
4113                 guint32 *values;
4114                 guint32 bitfield = meta->tables [i].size_bitfield;
4115                 if (!meta->tables [i].rows)
4116                         continue;
4117                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4118                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4119                 meta->tables [i].base = (char*)p;
4120                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4121                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4122                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4123                                 switch (mono_metadata_table_size (bitfield, col)) {
4124                                 case 1:
4125                                         *p++ = values [col];
4126                                         break;
4127                                 case 2:
4128                                         *p++ = values [col] & 0xff;
4129                                         *p++ = (values [col] >> 8) & 0xff;
4130                                         break;
4131                                 case 4:
4132                                         *p++ = values [col] & 0xff;
4133                                         *p++ = (values [col] >> 8) & 0xff;
4134                                         *p++ = (values [col] >> 16) & 0xff;
4135                                         *p++ = (values [col] >> 24) & 0xff;
4136                                         break;
4137                                 default:
4138                                         g_assert_not_reached ();
4139                                 }
4140                         }
4141                 }
4142                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4143         }
4144         
4145         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4146         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4147         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4148         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4149         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4150
4151         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4152 }
4153
4154 /*
4155  * Some tables in metadata need to be sorted according to some criteria, but
4156  * when methods and fields are first created with reflection, they may be assigned a token
4157  * that doesn't correspond to the final token they will get assigned after the sorting.
4158  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4159  * with the reflection objects that represent them. Once all the tables are set up, the 
4160  * reflection objects will contains the correct table index. fixup_method() will fixup the
4161  * tokens for the method with ILGenerator @ilgen.
4162  */
4163 static void
4164 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4165 {
4166         guint32 code_idx = GPOINTER_TO_UINT (value);
4167         MonoReflectionILTokenInfo *iltoken;
4168         MonoReflectionFieldBuilder *field;
4169         MonoReflectionCtorBuilder *ctor;
4170         MonoReflectionMethodBuilder *method;
4171         MonoReflectionTypeBuilder *tb;
4172         MonoReflectionArrayMethod *am;
4173         guint32 i, idx = 0;
4174         unsigned char *target;
4175
4176         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4177                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4178                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4179                 switch (target [3]) {
4180                 case MONO_TABLE_FIELD:
4181                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4182                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4183                                 idx = field->table_idx;
4184                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4185                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4186                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4187                         } else {
4188                                 g_assert_not_reached ();
4189                         }
4190                         break;
4191                 case MONO_TABLE_METHOD:
4192                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4193                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4194                                 idx = method->table_idx;
4195                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4196                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4197                                 idx = ctor->table_idx;
4198                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4199                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4200                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4201                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4202                         } else {
4203                                 g_assert_not_reached ();
4204                         }
4205                         break;
4206                 case MONO_TABLE_TYPEDEF:
4207                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4208                                 g_assert_not_reached ();
4209                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4210                         idx = tb->table_idx;
4211                         break;
4212                 case MONO_TABLE_MEMBERREF:
4213                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4214                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4215                                 idx = am->table_idx;
4216                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4217                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4218                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4219                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4220                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4221                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4222                                 continue;
4223                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4224                                 continue;
4225                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4226                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4227                                 g_assert (is_field_on_inst (f));
4228                                 continue;
4229                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4230                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4231                                 continue;
4232                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4233                                 continue;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4235                                 continue;
4236                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4237                                 continue;
4238                         } else {
4239                                 g_assert_not_reached ();
4240                         }
4241                         break;
4242                 case MONO_TABLE_METHODSPEC:
4243                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4244                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4245                                 g_assert (mono_method_signature (m)->generic_param_count);
4246                                 continue;
4247                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4248                                 continue;
4249                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4250                                 continue;
4251                         } else {
4252                                 g_assert_not_reached ();
4253                         }
4254                         break;
4255                 default:
4256                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4257                 }
4258                 target [0] = idx & 0xff;
4259                 target [1] = (idx >> 8) & 0xff;
4260                 target [2] = (idx >> 16) & 0xff;
4261         }
4262 }
4263
4264 /*
4265  * fixup_cattrs:
4266  *
4267  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4268  * value is not known when the table is emitted.
4269  */
4270 static void
4271 fixup_cattrs (MonoDynamicImage *assembly)
4272 {
4273         MonoDynamicTable *table;
4274         guint32 *values;
4275         guint32 type, i, idx, token;
4276         MonoObject *ctor;
4277
4278         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4279
4280         for (i = 0; i < table->rows; ++i) {
4281                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4282
4283                 type = values [MONO_CUSTOM_ATTR_TYPE];
4284                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4285                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4286                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4287                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4288                         g_assert (ctor);
4289
4290                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4291                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4292                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4293                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4294                         }
4295                 }
4296         }
4297 }
4298
4299 static void
4300 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4301 {
4302         MonoDynamicTable *table;
4303         guint32 *values;
4304
4305         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4306         table->rows++;
4307         alloc_table (table, table->rows);
4308         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4309         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4310         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4311         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4312         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4313         table->next_idx++;
4314 }
4315
4316 static void
4317 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4318 {
4319         MonoDynamicTable *table;
4320         guint32 *values;
4321         char blob_size [6];
4322         guchar hash [20];
4323         char *b = blob_size;
4324         char *name, *sname;
4325         guint32 idx, offset;
4326
4327         if (rsrc->filename) {
4328                 name = mono_string_to_utf8 (rsrc->filename);
4329                 sname = g_path_get_basename (name);
4330         
4331                 table = &assembly->tables [MONO_TABLE_FILE];
4332                 table->rows++;
4333                 alloc_table (table, table->rows);
4334                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4335                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4336                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4337                 g_free (sname);
4338
4339                 mono_sha1_get_digest_from_file (name, hash);
4340                 mono_metadata_encode_value (20, b, &b);
4341                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4342                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4343                 g_free (name);
4344                 idx = table->next_idx++;
4345                 rsrc->offset = 0;
4346                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4347         } else {
4348                 char sizebuf [4];
4349                 char *data;
4350                 guint len;
4351                 if (rsrc->data) {
4352                         data = mono_array_addr (rsrc->data, char, 0);
4353                         len = mono_array_length (rsrc->data);
4354                 } else {
4355                         data = NULL;
4356                         len = 0;
4357                 }
4358                 offset = len;
4359                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4360                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4361                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4362                 mono_image_add_stream_data (&assembly->resources, data, len);
4363
4364                 if (!mb->is_main)
4365                         /* 
4366                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4367                          * the main module, but that needs to reference the FILE table
4368                          * which isn't emitted yet.
4369                          */
4370                         return;
4371                 else
4372                         idx = 0;
4373         }
4374
4375         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4376 }
4377
4378 static void
4379 set_version_from_string (MonoString *version, guint32 *values)
4380 {
4381         gchar *ver, *p, *str;
4382         guint32 i;
4383         
4384         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4385         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4386         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4387         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4388         if (!version)
4389                 return;
4390         ver = str = mono_string_to_utf8 (version);
4391         for (i = 0; i < 4; ++i) {
4392                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4393                 switch (*p) {
4394                 case '.':
4395                         p++;
4396                         break;
4397                 case '*':
4398                         /* handle Revision and Build */
4399                         p++;
4400                         break;
4401                 }
4402                 ver = p;
4403         }
4404         g_free (str);
4405 }
4406
4407 static guint32
4408 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4409         gsize len;
4410         guint32 token = 0;
4411         char blob_size [6];
4412         char *b = blob_size;
4413
4414         if (!pkey)
4415                 return token;
4416
4417         len = mono_array_length (pkey);
4418         mono_metadata_encode_value (len, b, &b);
4419         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4420         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4421
4422         assembly->public_key = g_malloc (len);
4423         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4424         assembly->public_key_len = len;
4425
4426         /* Special case: check for ECMA key (16 bytes) */
4427         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4428                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4429                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4430         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4431                 /* minimum key size (in 2.0) is 384 bits */
4432                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4433         } else {
4434                 /* FIXME - verifier */
4435                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4436                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4437         }
4438         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4439
4440         return token;
4441 }
4442
4443 static void
4444 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4445 {
4446         MonoDynamicTable *table;
4447         MonoDynamicImage *assembly;
4448         MonoReflectionAssemblyBuilder *assemblyb;
4449         MonoDomain *domain;
4450         guint32 *values;
4451         int i;
4452         guint32 module_index;
4453
4454         assemblyb = moduleb->assemblyb;
4455         assembly = moduleb->dynamic_image;
4456         domain = mono_object_domain (assemblyb);
4457
4458         /* Emit ASSEMBLY table */
4459         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4460         alloc_table (table, 1);
4461         values = table->values + MONO_ASSEMBLY_SIZE;
4462         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4463         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4464         if (assemblyb->culture) {
4465                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4466         } else {
4467                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4468         }
4469         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4470         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4471         set_version_from_string (assemblyb->version, values);
4472
4473         /* Emit FILE + EXPORTED_TYPE table */
4474         module_index = 0;
4475         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4476                 int j;
4477                 MonoReflectionModuleBuilder *file_module = 
4478                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4479                 if (file_module != moduleb) {
4480                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4481                         module_index ++;
4482                         if (file_module->types) {
4483                                 for (j = 0; j < file_module->num_types; ++j) {
4484                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4485                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4486                                 }
4487                         }
4488                 }
4489         }
4490         if (assemblyb->loaded_modules) {
4491                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4492                         MonoReflectionModule *file_module = 
4493                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4494                         mono_image_fill_file_table (domain, file_module, assembly);
4495                         module_index ++;
4496                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4497                 }
4498         }
4499         if (assemblyb->type_forwarders)
4500                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4501
4502         /* Emit MANIFESTRESOURCE table */
4503         module_index = 0;
4504         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4505                 int j;
4506                 MonoReflectionModuleBuilder *file_module = 
4507                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4508                 /* The table for the main module is emitted later */
4509                 if (file_module != moduleb) {
4510                         module_index ++;
4511                         if (file_module->resources) {
4512                                 int len = mono_array_length (file_module->resources);
4513                                 for (j = 0; j < len; ++j) {
4514                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4515                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4516                                 }
4517                         }
4518                 }
4519         }               
4520 }
4521
4522 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4523
4524 /*
4525  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4526  * for the modulebuilder @moduleb.
4527  * At the end of the process, method and field tokens are fixed up and the 
4528  * on-disk compressed metadata representation is created.
4529  */
4530 void
4531 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4532 {
4533         MonoDynamicTable *table;
4534         MonoDynamicImage *assembly;
4535         MonoReflectionAssemblyBuilder *assemblyb;
4536         MonoDomain *domain;
4537         GPtrArray *types;
4538         guint32 *values;
4539         int i, j;
4540
4541         assemblyb = moduleb->assemblyb;
4542         assembly = moduleb->dynamic_image;
4543         domain = mono_object_domain (assemblyb);
4544
4545         if (assembly->text_rva)
4546                 return;
4547
4548         assembly->text_rva = START_TEXT_RVA;
4549
4550         if (moduleb->is_main) {
4551                 mono_image_emit_manifest (moduleb);
4552         }
4553
4554         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4555         table->rows = 1; /* .<Module> */
4556         table->next_idx++;
4557         alloc_table (table, table->rows);
4558         /*
4559          * Set the first entry.
4560          */
4561         values = table->values + table->columns;
4562         values [MONO_TYPEDEF_FLAGS] = 0;
4563         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4564         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4565         values [MONO_TYPEDEF_EXTENDS] = 0;
4566         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4567         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4568
4569         /* 
4570          * handle global methods 
4571          * FIXME: test what to do when global methods are defined in multiple modules.
4572          */
4573         if (moduleb->global_methods) {
4574                 table = &assembly->tables [MONO_TABLE_METHOD];
4575                 table->rows += mono_array_length (moduleb->global_methods);
4576                 alloc_table (table, table->rows);
4577                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4578                         mono_image_get_method_info (
4579                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4580         }
4581         if (moduleb->global_fields) {
4582                 table = &assembly->tables [MONO_TABLE_FIELD];
4583                 table->rows += mono_array_length (moduleb->global_fields);
4584                 alloc_table (table, table->rows);
4585                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4586                         mono_image_get_field_info (
4587                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4588         }
4589
4590         table = &assembly->tables [MONO_TABLE_MODULE];
4591         alloc_table (table, 1);
4592         mono_image_fill_module_table (domain, moduleb, assembly);
4593
4594         /* Collect all types into a list sorted by their table_idx */
4595         types = g_ptr_array_new ();
4596
4597         if (moduleb->types)
4598                 for (i = 0; i < moduleb->num_types; ++i) {
4599                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4600                         collect_types (types, type);
4601                 }
4602
4603         g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4604         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4605         table->rows += types->len;
4606         alloc_table (table, table->rows);
4607
4608         /*
4609          * Emit type names + namespaces at one place inside the string heap,
4610          * so load_class_names () needs to touch fewer pages.
4611          */
4612         for (i = 0; i < types->len; ++i) {
4613                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4614                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4615         }
4616         for (i = 0; i < types->len; ++i) {
4617                 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4618                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4619         }
4620
4621         for (i = 0; i < types->len; ++i) {
4622                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4623                 mono_image_get_type_info (domain, type, assembly);
4624         }
4625
4626         /* 
4627          * table->rows is already set above and in mono_image_fill_module_table.
4628          */
4629         /* add all the custom attributes at the end, once all the indexes are stable */
4630         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4631
4632         /* CAS assembly permissions */
4633         if (assemblyb->permissions_minimum)
4634                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4635         if (assemblyb->permissions_optional)
4636                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4637         if (assemblyb->permissions_refused)
4638                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4639
4640         module_add_cattrs (assembly, moduleb);
4641
4642         /* fixup tokens */
4643         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4644
4645         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4646          * the final tokens and don't need another fixup pass. */
4647
4648         if (moduleb->global_methods) {
4649                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4650                         MonoReflectionMethodBuilder *mb = mono_array_get (
4651                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4652                         mono_image_add_methodimpl (assembly, mb);
4653                 }
4654         }
4655
4656         for (i = 0; i < types->len; ++i) {
4657                 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4658                 if (type->methods) {
4659                         for (j = 0; j < type->num_methods; ++j) {
4660                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4661                                         type->methods, MonoReflectionMethodBuilder*, j);
4662
4663                                 mono_image_add_methodimpl (assembly, mb);
4664                         }
4665                 }
4666         }
4667
4668         g_ptr_array_free (types, TRUE);
4669
4670         fixup_cattrs (assembly);
4671 }
4672
4673 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4674
4675 void
4676 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4677 {
4678         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4679 }
4680
4681 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4682
4683
4684 typedef struct {
4685         guint32 import_lookup_table;
4686         guint32 timestamp;
4687         guint32 forwarder;
4688         guint32 name_rva;
4689         guint32 import_address_table_rva;
4690 } MonoIDT;
4691
4692 typedef struct {
4693         guint32 name_rva;
4694         guint32 flags;
4695 } MonoILT;
4696
4697 #ifndef DISABLE_REFLECTION_EMIT
4698
4699 /*
4700  * mono_image_insert_string:
4701  * @module: module builder object
4702  * @str: a string
4703  *
4704  * Insert @str into the user string stream of @module.
4705  */
4706 guint32
4707 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4708 {
4709         MonoDynamicImage *assembly;
4710         guint32 idx;
4711         char buf [16];
4712         char *b = buf;
4713         
4714         MONO_ARCH_SAVE_REGS;
4715
4716         if (!module->dynamic_image)
4717                 mono_image_module_basic_init (module);
4718
4719         assembly = module->dynamic_image;
4720         
4721         if (assembly->save) {
4722                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4723                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4724 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4725         {
4726                 char *swapped = g_malloc (2 * mono_string_length (str));
4727                 const char *p = (const char*)mono_string_chars (str);
4728
4729                 swap_with_size (swapped, p, 2, mono_string_length (str));
4730                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4731                 g_free (swapped);
4732         }
4733 #else
4734                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4735 #endif
4736                 mono_image_add_stream_data (&assembly->us, "", 1);
4737         } else {
4738                 idx = assembly->us.index ++;
4739         }
4740
4741         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4742
4743         return MONO_TOKEN_STRING | idx;
4744 }
4745
4746 guint32
4747 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4748 {
4749         MonoClass *klass;
4750         guint32 token = 0;
4751
4752         klass = obj->vtable->klass;
4753         if (strcmp (klass->name, "MonoMethod") == 0) {
4754                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4755                 MonoMethodSignature *sig, *old;
4756                 guint32 sig_token, parent;
4757                 int nargs, i;
4758
4759                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4760
4761                 nargs = mono_array_length (opt_param_types);
4762                 old = mono_method_signature (method);
4763                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4764
4765                 sig->hasthis = old->hasthis;
4766                 sig->explicit_this = old->explicit_this;
4767                 sig->call_convention = old->call_convention;
4768                 sig->generic_param_count = old->generic_param_count;
4769                 sig->param_count = old->param_count + nargs;
4770                 sig->sentinelpos = old->param_count;
4771                 sig->ret = old->ret;
4772
4773                 for (i = 0; i < old->param_count; i++)
4774                         sig->params [i] = old->params [i];
4775
4776                 for (i = 0; i < nargs; i++) {
4777                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4778                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4779                 }
4780
4781                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4782                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4783                 parent >>= MONO_TYPEDEFORREF_BITS;
4784
4785                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4786                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4787
4788                 sig_token = method_encode_signature (assembly, sig);
4789                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4790         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4791                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4792                 ReflectionMethodBuilder rmb;
4793                 guint32 parent, sig;
4794                 char *name;
4795
4796                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4797                 rmb.opt_types = opt_param_types;
4798
4799                 sig = method_builder_encode_signature (assembly, &rmb);
4800
4801                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4802                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4803
4804                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4805                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4806
4807                 name = mono_string_to_utf8 (rmb.name);
4808                 token = mono_image_get_varargs_method_token (
4809                         assembly, parent, name, sig);
4810                 g_free (name);
4811         } else {
4812                 g_error ("requested method token for %s\n", klass->name);
4813         }
4814
4815         return token;
4816 }
4817
4818 /*
4819  * mono_image_create_token:
4820  * @assembly: a dynamic assembly
4821  * @obj:
4822  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4823  *
4824  * Get a token to insert in the IL code stream for the given MemberInfo.
4825  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4826  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4827  * entry.
4828  */
4829 guint32
4830 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4831                                                  gboolean create_methodspec, gboolean register_token)
4832 {
4833         MonoClass *klass;
4834         guint32 token = 0;
4835
4836         klass = obj->vtable->klass;
4837
4838         /* Check for user defined reflection objects */
4839         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4840         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4841                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4842
4843         if (strcmp (klass->name, "MethodBuilder") == 0) {
4844                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4845                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4846
4847                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4848                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4849                 else
4850                         token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4851                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4852         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4853                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4854                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4855
4856                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4857                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4858                 else
4859                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4860                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4861         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4862                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4863                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4864                 if (tb->generic_params) {
4865                         token = mono_image_get_generic_field_token (assembly, fb);
4866                 } else {
4867                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4868                 }
4869         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4870                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4871                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4872         } else if (strcmp (klass->name, "MonoType") == 0) {
4873                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4874                 MonoClass *mc = mono_class_from_mono_type (type);
4875                 token = mono_metadata_token_from_dor (
4876                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4877         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4878                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4879                 token = mono_metadata_token_from_dor (
4880                         mono_image_typedef_or_ref (assembly, type));
4881         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4882                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4883                 token = mono_metadata_token_from_dor (
4884                         mono_image_typedef_or_ref (assembly, type));
4885         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4886                    strcmp (klass->name, "MonoMethod") == 0 ||
4887                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4888                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4889                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4890                 if (m->method->is_inflated) {
4891                         if (create_methodspec)
4892                                 token = mono_image_get_methodspec_token (assembly, m->method);
4893                         else
4894                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4895                 } else if ((m->method->klass->image == &assembly->image) &&
4896                          !m->method->klass->generic_class) {
4897                         static guint32 method_table_idx = 0xffffff;
4898                         if (m->method->klass->wastypebuilder) {
4899                                 /* we use the same token as the one that was assigned
4900                                  * to the Methodbuilder.
4901                                  * FIXME: do the equivalent for Fields.
4902                                  */
4903                                 token = m->method->token;
4904                         } else {
4905                                 /*
4906                                  * Each token should have a unique index, but the indexes are
4907                                  * assigned by managed code, so we don't know about them. An
4908                                  * easy solution is to count backwards...
4909                                  */
4910                                 method_table_idx --;
4911                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4912                         }
4913                 } else {
4914                         token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4915                 }
4916                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4917         } else if (strcmp (klass->name, "MonoField") == 0) {
4918                 MonoReflectionField *f = (MonoReflectionField *)obj;
4919                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4920                         static guint32 field_table_idx = 0xffffff;
4921                         field_table_idx --;
4922                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4923                 } else {
4924                         token = mono_image_get_fieldref_token (assembly, f);
4925                 }
4926                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4927         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4928                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4929                 token = mono_image_get_array_token (assembly, m);
4930         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4931                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4932                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4933         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4934                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4935                 token = mono_metadata_token_from_dor (
4936                         mono_image_typedef_or_ref (assembly, type));
4937         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4938                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4939                 token = mono_image_get_field_on_inst_token (assembly, f);
4940         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4941                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4942                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4943         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4944                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4945                 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4946         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4947                 MonoReflectionType *type = (MonoReflectionType *)obj;
4948                 token = mono_metadata_token_from_dor (
4949                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4950         } else {
4951                 g_error ("requested token for %s\n", klass->name);
4952         }
4953
4954         if (register_token)
4955                 mono_image_register_token (assembly, token, obj);
4956
4957         return token;
4958 }
4959
4960 /*
4961  * mono_image_register_token:
4962  *
4963  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4964  * the Module.ResolveXXXToken () methods to work.
4965  */
4966 void
4967 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4968 {
4969         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4970         if (prev) {
4971                 /* There could be multiple MethodInfo objects with the same token */
4972                 //g_assert (prev == obj);
4973         } else {
4974                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4975         }
4976 }
4977
4978 static MonoDynamicImage*
4979 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4980 {
4981         static const guchar entrycode [16] = {0xff, 0x25, 0};
4982         MonoDynamicImage *image;
4983         int i;
4984
4985         const char *version;
4986
4987         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4988                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4989         else
4990                 version = mono_get_runtime_info ()->runtime_version;
4991
4992 #if HAVE_BOEHM_GC
4993         image = GC_MALLOC (sizeof (MonoDynamicImage));
4994 #else
4995         image = g_new0 (MonoDynamicImage, 1);
4996 #endif
4997         
4998         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4999         
5000         /*g_print ("created image %p\n", image);*/
5001         /* keep in sync with image.c */
5002         image->image.name = assembly_name;
5003         image->image.assembly_name = image->image.name; /* they may be different */
5004         image->image.module_name = module_name;
5005         image->image.version = g_strdup (version);
5006         image->image.md_version_major = 1;
5007         image->image.md_version_minor = 1;
5008         image->image.dynamic = TRUE;
5009
5010         image->image.references = g_new0 (MonoAssembly*, 1);
5011         image->image.references [0] = NULL;
5012
5013         mono_image_init (&image->image);
5014
5015         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5016         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5017         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5018         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5019         image->handleref = g_hash_table_new (NULL, NULL);
5020         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5021         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5022         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5023         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5024         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5025         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5026         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5027         image->gen_params = g_ptr_array_new ();
5028
5029         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5030         string_heap_init (&image->sheap);
5031         mono_image_add_stream_data (&image->us, "", 1);
5032         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5033         /* import tables... */
5034         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5035         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5036         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5037         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5038         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5039         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5040         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5041         stream_data_align (&image->code);
5042
5043         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5044
5045         for (i=0; i < MONO_TABLE_NUM; ++i) {
5046                 image->tables [i].next_idx = 1;
5047                 image->tables [i].columns = table_sizes [i];
5048         }
5049
5050         image->image.assembly = (MonoAssembly*)assembly;
5051         image->run = assembly->run;
5052         image->save = assembly->save;
5053         image->pe_kind = 0x1; /* ILOnly */
5054         image->machine = 0x14c; /* I386 */
5055         
5056         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5057
5058         return image;
5059 }
5060 #endif
5061
5062 static void
5063 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5064 {
5065         g_free (key);
5066 }
5067
5068 void
5069 mono_dynamic_image_free (MonoDynamicImage *image)
5070 {
5071         MonoDynamicImage *di = image;
5072         GList *list;
5073         int i;
5074
5075         if (di->methodspec)
5076                 mono_g_hash_table_destroy (di->methodspec);
5077         if (di->typespec)
5078                 g_hash_table_destroy (di->typespec);
5079         if (di->typeref)
5080                 g_hash_table_destroy (di->typeref);
5081         if (di->handleref)
5082                 g_hash_table_destroy (di->handleref);
5083         if (di->handleref_managed)
5084                 mono_g_hash_table_destroy (di->handleref_managed);
5085         if (di->tokens)
5086                 mono_g_hash_table_destroy (di->tokens);
5087         if (di->generic_def_objects)
5088                 mono_g_hash_table_destroy (di->generic_def_objects);
5089         if (di->blob_cache) {
5090                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5091                 g_hash_table_destroy (di->blob_cache);
5092         }
5093         if (di->standalonesig_cache)
5094                 g_hash_table_destroy (di->standalonesig_cache);
5095         for (list = di->array_methods; list; list = list->next) {
5096                 ArrayMethod *am = (ArrayMethod *)list->data;
5097                 g_free (am->sig);
5098                 g_free (am->name);
5099                 g_free (am);
5100         }
5101         g_list_free (di->array_methods);
5102         if (di->gen_params) {
5103                 for (i = 0; i < di->gen_params->len; i++) {
5104                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5105                         if (entry->gparam->type.type) {
5106                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5107                                 g_free ((char*)mono_generic_param_info (param)->name);
5108                                 g_free (param);
5109                         }
5110                         mono_gc_deregister_root ((char*) &entry->gparam);
5111                         g_free (entry);
5112                 }
5113                 g_ptr_array_free (di->gen_params, TRUE);
5114         }
5115         if (di->token_fixups)
5116                 mono_g_hash_table_destroy (di->token_fixups);
5117         if (di->method_to_table_idx)
5118                 g_hash_table_destroy (di->method_to_table_idx);
5119         if (di->field_to_table_idx)
5120                 g_hash_table_destroy (di->field_to_table_idx);
5121         if (di->method_aux_hash)
5122                 g_hash_table_destroy (di->method_aux_hash);
5123         g_free (di->strong_name);
5124         g_free (di->win32_res);
5125         if (di->public_key)
5126                 g_free (di->public_key);
5127
5128         /*g_print ("string heap destroy for image %p\n", di);*/
5129         mono_dynamic_stream_reset (&di->sheap);
5130         mono_dynamic_stream_reset (&di->code);
5131         mono_dynamic_stream_reset (&di->resources);
5132         mono_dynamic_stream_reset (&di->us);
5133         mono_dynamic_stream_reset (&di->blob);
5134         mono_dynamic_stream_reset (&di->tstream);
5135         mono_dynamic_stream_reset (&di->guid);
5136         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5137                 g_free (di->tables [i].values);
5138         }
5139 }       
5140
5141 #ifndef DISABLE_REFLECTION_EMIT
5142
5143 /*
5144  * mono_image_basic_init:
5145  * @assembly: an assembly builder object
5146  *
5147  * Create the MonoImage that represents the assembly builder and setup some
5148  * of the helper hash table and the basic metadata streams.
5149  */
5150 void
5151 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5152 {
5153         MonoDynamicAssembly *assembly;
5154         MonoDynamicImage *image;
5155         MonoDomain *domain = mono_object_domain (assemblyb);
5156         
5157         MONO_ARCH_SAVE_REGS;
5158
5159         if (assemblyb->dynamic_assembly)
5160                 return;
5161
5162 #if HAVE_BOEHM_GC
5163         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5164 #else
5165         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5166 #endif
5167
5168         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5169         
5170         assembly->assembly.ref_count = 1;
5171         assembly->assembly.dynamic = TRUE;
5172         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5173         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5174         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5175         if (assemblyb->culture)
5176                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5177         else
5178                 assembly->assembly.aname.culture = g_strdup ("");
5179
5180         if (assemblyb->version) {
5181                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5182                         char **version = g_strsplit (vstr, ".", 4);
5183                         char **parts = version;
5184                         assembly->assembly.aname.major = atoi (*parts++);
5185                         assembly->assembly.aname.minor = atoi (*parts++);
5186                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5187                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5188
5189                         g_strfreev (version);
5190                         g_free (vstr);
5191         } else {
5192                         assembly->assembly.aname.major = 0;
5193                         assembly->assembly.aname.minor = 0;
5194                         assembly->assembly.aname.build = 0;
5195                         assembly->assembly.aname.revision = 0;
5196         }
5197
5198         assembly->run = assemblyb->access != 2;
5199         assembly->save = assemblyb->access != 1;
5200         assembly->domain = domain;
5201
5202         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5203         image->initial_image = TRUE;
5204         assembly->assembly.aname.name = image->image.name;
5205         assembly->assembly.image = &image->image;
5206         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5207                 /* -1 to correct for the trailing NULL byte */
5208                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5209                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5210                 }
5211                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5212         }
5213
5214         mono_domain_assemblies_lock (domain);
5215         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5216         mono_domain_assemblies_unlock (domain);
5217
5218         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5219         
5220         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5221         
5222         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5223 }
5224
5225 #endif /* !DISABLE_REFLECTION_EMIT */
5226
5227 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5228
5229 static int
5230 calc_section_size (MonoDynamicImage *assembly)
5231 {
5232         int nsections = 0;
5233
5234         /* alignment constraints */
5235         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5236         g_assert ((assembly->code.index % 4) == 0);
5237         assembly->meta_size += 3;
5238         assembly->meta_size &= ~3;
5239         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5240         g_assert ((assembly->resources.index % 4) == 0);
5241
5242         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5243         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5244         nsections++;
5245
5246         if (assembly->win32_res) {
5247                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5248
5249                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5250                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5251                 nsections++;
5252         }
5253
5254         assembly->sections [MONO_SECTION_RELOC].size = 12;
5255         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5256         nsections++;
5257
5258         return nsections;
5259 }
5260
5261 typedef struct {
5262         guint32 id;
5263         guint32 offset;
5264         GSList *children;
5265         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5266 } ResTreeNode;
5267
5268 static int
5269 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5270 {
5271         ResTreeNode *t1 = (ResTreeNode*)a;
5272         ResTreeNode *t2 = (ResTreeNode*)b;
5273
5274         return t1->id - t2->id;
5275 }
5276
5277 /*
5278  * resource_tree_create:
5279  *
5280  *  Organize the resources into a resource tree.
5281  */
5282 static ResTreeNode *
5283 resource_tree_create (MonoArray *win32_resources)
5284 {
5285         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5286         GSList *l;
5287         int i;
5288
5289         tree = g_new0 (ResTreeNode, 1);
5290         
5291         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5292                 MonoReflectionWin32Resource *win32_res =
5293                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5294
5295                 /* Create node */
5296
5297                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5298                 lang_node = g_new0 (ResTreeNode, 1);
5299                 lang_node->id = win32_res->lang_id;
5300                 lang_node->win32_res = win32_res;
5301
5302                 /* Create type node if neccesary */
5303                 type_node = NULL;
5304                 for (l = tree->children; l; l = l->next)
5305                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5306                                 type_node = (ResTreeNode*)l->data;
5307                                 break;
5308                         }
5309
5310                 if (!type_node) {
5311                         type_node = g_new0 (ResTreeNode, 1);
5312                         type_node->id = win32_res->res_type;
5313
5314                         /* 
5315                          * The resource types have to be sorted otherwise
5316                          * Windows Explorer can't display the version information.
5317                          */
5318                         tree->children = g_slist_insert_sorted (tree->children, 
5319                                 type_node, resource_tree_compare_by_id);
5320                 }
5321
5322                 /* Create res node if neccesary */
5323                 res_node = NULL;
5324                 for (l = type_node->children; l; l = l->next)
5325                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5326                                 res_node = (ResTreeNode*)l->data;
5327                                 break;
5328                         }
5329
5330                 if (!res_node) {
5331                         res_node = g_new0 (ResTreeNode, 1);
5332                         res_node->id = win32_res->res_id;
5333                         type_node->children = g_slist_append (type_node->children, res_node);
5334                 }
5335
5336                 res_node->children = g_slist_append (res_node->children, lang_node);
5337         }
5338
5339         return tree;
5340 }
5341
5342 /*
5343  * resource_tree_encode:
5344  * 
5345  *   Encode the resource tree into the format used in the PE file.
5346  */
5347 static void
5348 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5349 {
5350         char *entries;
5351         MonoPEResourceDir dir;
5352         MonoPEResourceDirEntry dir_entry;
5353         MonoPEResourceDataEntry data_entry;
5354         GSList *l;
5355         guint32 res_id_entries;
5356
5357         /*
5358          * For the format of the resource directory, see the article
5359          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5360          * Matt Pietrek
5361          */
5362
5363         memset (&dir, 0, sizeof (dir));
5364         memset (&dir_entry, 0, sizeof (dir_entry));
5365         memset (&data_entry, 0, sizeof (data_entry));
5366
5367         g_assert (sizeof (dir) == 16);
5368         g_assert (sizeof (dir_entry) == 8);
5369         g_assert (sizeof (data_entry) == 16);
5370
5371         node->offset = p - begin;
5372
5373         /* IMAGE_RESOURCE_DIRECTORY */
5374         res_id_entries = g_slist_length (node->children);
5375         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5376
5377         memcpy (p, &dir, sizeof (dir));
5378         p += sizeof (dir);
5379
5380         /* Reserve space for entries */
5381         entries = p;
5382         p += sizeof (dir_entry) * res_id_entries;
5383
5384         /* Write children */
5385         for (l = node->children; l; l = l->next) {
5386                 ResTreeNode *child = (ResTreeNode*)l->data;
5387
5388                 if (child->win32_res) {
5389                         guint32 size;
5390
5391                         child->offset = p - begin;
5392
5393                         /* IMAGE_RESOURCE_DATA_ENTRY */
5394                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5395                         size = mono_array_length (child->win32_res->res_data);
5396                         data_entry.rde_size = GUINT32_TO_LE (size);
5397
5398                         memcpy (p, &data_entry, sizeof (data_entry));
5399                         p += sizeof (data_entry);
5400
5401                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5402                         p += size;
5403                 } else {
5404                         resource_tree_encode (child, begin, p, &p);
5405                 }
5406         }
5407
5408         /* IMAGE_RESOURCE_ENTRY */
5409         for (l = node->children; l; l = l->next) {
5410                 ResTreeNode *child = (ResTreeNode*)l->data;
5411
5412                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5413                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5414
5415                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5416                 entries += sizeof (dir_entry);
5417         }
5418
5419         *endbuf = p;
5420 }
5421
5422 static void
5423 resource_tree_free (ResTreeNode * node)
5424 {
5425         GSList * list;
5426         for (list = node->children; list; list = list->next)
5427                 resource_tree_free ((ResTreeNode*)list->data);
5428         g_slist_free(node->children);
5429         g_free (node);
5430 }
5431
5432 static void
5433 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5434 {
5435         char *buf;
5436         char *p;
5437         guint32 size, i;
5438         MonoReflectionWin32Resource *win32_res;
5439         ResTreeNode *tree;
5440
5441         if (!assemblyb->win32_resources)
5442                 return;
5443
5444         /*
5445          * Resources are stored in a three level tree inside the PE file.
5446          * - level one contains a node for each type of resource
5447          * - level two contains a node for each resource
5448          * - level three contains a node for each instance of a resource for a
5449          *   specific language.
5450          */
5451
5452         tree = resource_tree_create (assemblyb->win32_resources);
5453
5454         /* Estimate the size of the encoded tree */
5455         size = 0;
5456         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5457                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5458                 size += mono_array_length (win32_res->res_data);
5459         }
5460         /* Directory structure */
5461         size += mono_array_length (assemblyb->win32_resources) * 256;
5462         p = buf = g_malloc (size);
5463
5464         resource_tree_encode (tree, p, p, &p);
5465
5466         g_assert (p - buf <= size);
5467
5468         assembly->win32_res = g_malloc (p - buf);
5469         assembly->win32_res_size = p - buf;
5470         memcpy (assembly->win32_res, buf, p - buf);
5471
5472         g_free (buf);
5473         resource_tree_free (tree);
5474 }
5475
5476 static void
5477 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5478 {
5479         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5480         int i;
5481
5482         p += sizeof (MonoPEResourceDir);
5483         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5484                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5485                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5486                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5487                         fixup_resource_directory (res_section, child, rva);
5488                 } else {
5489                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5490                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5491                 }
5492
5493                 p += sizeof (MonoPEResourceDirEntry);
5494         }
5495 }
5496
5497 static void
5498 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5499 {
5500         guint32 dummy;
5501         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5502                 g_error ("WriteFile returned %d\n", GetLastError ());
5503 }
5504
5505 /*
5506  * mono_image_create_pefile:
5507  * @mb: a module builder object
5508  * 
5509  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5510  * assembly->pefile where it can be easily retrieved later in chunks.
5511  */
5512 void
5513 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5514 {
5515         MonoMSDOSHeader *msdos;
5516         MonoDotNetHeader *header;
5517         MonoSectionTable *section;
5518         MonoCLIHeader *cli_header;
5519         guint32 size, image_size, virtual_base, text_offset;
5520         guint32 header_start, section_start, file_offset, virtual_offset;
5521         MonoDynamicImage *assembly;
5522         MonoReflectionAssemblyBuilder *assemblyb;
5523         MonoDynamicStream pefile_stream = {0};
5524         MonoDynamicStream *pefile = &pefile_stream;
5525         int i, nsections;
5526         guint32 *rva, value;
5527         guchar *p;
5528         static const unsigned char msheader[] = {
5529                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5530                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5531                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5532                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5533                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5534                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5535                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5536                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5537         };
5538
5539         assemblyb = mb->assemblyb;
5540
5541         mono_image_basic_init (assemblyb);
5542         assembly = mb->dynamic_image;
5543
5544         assembly->pe_kind = assemblyb->pe_kind;
5545         assembly->machine = assemblyb->machine;
5546         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5547         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5548         
5549         mono_image_build_metadata (mb);
5550
5551         if (mb->is_main && assemblyb->resources) {
5552                 int len = mono_array_length (assemblyb->resources);
5553                 for (i = 0; i < len; ++i)
5554                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5555         }
5556
5557         if (mb->resources) {
5558                 int len = mono_array_length (mb->resources);
5559                 for (i = 0; i < len; ++i)
5560                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5561         }
5562
5563         build_compressed_metadata (assembly);
5564
5565         if (mb->is_main)
5566                 assembly_add_win32_resources (assembly, assemblyb);
5567
5568         nsections = calc_section_size (assembly);
5569         
5570         /* The DOS header and stub */
5571         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5572         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5573
5574         /* the dotnet header */
5575         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5576
5577         /* the section tables */
5578         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5579
5580         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5581         virtual_offset = VIRT_ALIGN;
5582         image_size = 0;
5583
5584         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5585                 if (!assembly->sections [i].size)
5586                         continue;
5587                 /* align offsets */
5588                 file_offset += FILE_ALIGN - 1;
5589                 file_offset &= ~(FILE_ALIGN - 1);
5590                 virtual_offset += VIRT_ALIGN - 1;
5591                 virtual_offset &= ~(VIRT_ALIGN - 1);
5592
5593                 assembly->sections [i].offset = file_offset;
5594                 assembly->sections [i].rva = virtual_offset;
5595
5596                 file_offset += assembly->sections [i].size;
5597                 virtual_offset += assembly->sections [i].size;
5598                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5599         }
5600
5601         file_offset += FILE_ALIGN - 1;
5602         file_offset &= ~(FILE_ALIGN - 1);
5603
5604         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5605
5606         /* back-patch info */
5607         msdos = (MonoMSDOSHeader*)pefile->data;
5608         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5609
5610         header = (MonoDotNetHeader*)(pefile->data + header_start);
5611         header->pesig [0] = 'P';
5612         header->pesig [1] = 'E';
5613         
5614         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5615         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5616         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5617         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5618         if (assemblyb->pekind == 1) {
5619                 /* it's a dll */
5620                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5621         } else {
5622                 /* it's an exe */
5623                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5624         }
5625
5626         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5627
5628         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5629         header->pe.pe_major = 6;
5630         header->pe.pe_minor = 0;
5631         size = assembly->sections [MONO_SECTION_TEXT].size;
5632         size += FILE_ALIGN - 1;
5633         size &= ~(FILE_ALIGN - 1);
5634         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5635         size = assembly->sections [MONO_SECTION_RSRC].size;
5636         size += FILE_ALIGN - 1;
5637         size &= ~(FILE_ALIGN - 1);
5638         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5639         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5640         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5641         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5642         /* pe_rva_entry_point always at the beginning of the text section */
5643         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5644
5645         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5646         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5647         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5648         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5649         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5650         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5651         size = section_start;
5652         size += FILE_ALIGN - 1;
5653         size &= ~(FILE_ALIGN - 1);
5654         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5655         size = image_size;
5656         size += VIRT_ALIGN - 1;
5657         size &= ~(VIRT_ALIGN - 1);
5658         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5659
5660         /*
5661         // Translate the PEFileKind value to the value expected by the Windows loader
5662         */
5663         {
5664                 short kind;
5665
5666                 /*
5667                 // PEFileKinds.Dll == 1
5668                 // PEFileKinds.ConsoleApplication == 2
5669                 // PEFileKinds.WindowApplication == 3
5670                 //
5671                 // need to get:
5672                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5673                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5674                 */
5675                 if (assemblyb->pekind == 3)
5676                         kind = 2;
5677                 else
5678                         kind = 3;
5679                 
5680                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5681         }    
5682         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5683         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5684         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5685         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5686         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5687         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5688
5689         /* fill data directory entries */
5690
5691         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5692         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5693
5694         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5695         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5696
5697         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5698         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5699         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5700         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5701         /* patch entrypoint name */
5702         if (assemblyb->pekind == 1)
5703                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5704         else
5705                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5706         /* patch imported function RVA name */
5707         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5708         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5709
5710         /* the import table */
5711         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5712         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5713         /* patch imported dll RVA name and other entries in the dir */
5714         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5715         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5716         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5717         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5718         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5719         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5720
5721         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5722         value = (assembly->text_rva + assembly->imp_names_offset);
5723         *p++ = (value) & 0xff;
5724         *p++ = (value >> 8) & (0xff);
5725         *p++ = (value >> 16) & (0xff);
5726         *p++ = (value >> 24) & (0xff);
5727
5728         /* the CLI header info */
5729         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5730         cli_header->ch_size = GUINT32_FROM_LE (72);
5731         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5732         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5733         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5734         if (assemblyb->entry_point) {
5735                 guint32 table_idx = 0;
5736                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5737                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5738                         table_idx = methodb->table_idx;
5739                 } else {
5740                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5741                 }
5742                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5743         } else {
5744                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5745         }
5746         /* The embedded managed resources */
5747         text_offset = assembly->text_rva + assembly->code.index;
5748         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5749         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5750         text_offset += assembly->resources.index;
5751         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5752         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5753         text_offset += assembly->meta_size;
5754         if (assembly->strong_name_size) {
5755                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5756                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5757                 text_offset += assembly->strong_name_size;
5758         }
5759
5760         /* write the section tables and section content */
5761         section = (MonoSectionTable*)(pefile->data + section_start);
5762         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5763                 static const char section_names [][7] = {
5764                         ".text", ".rsrc", ".reloc"
5765                 };
5766                 if (!assembly->sections [i].size)
5767                         continue;
5768                 strcpy (section->st_name, section_names [i]);
5769                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5770                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5771                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5772                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5773                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5774                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5775                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5776                 section ++;
5777         }
5778         
5779         checked_write_file (file, pefile->data, pefile->index);
5780         
5781         mono_dynamic_stream_reset (pefile);
5782         
5783         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5784                 if (!assembly->sections [i].size)
5785                         continue;
5786                 
5787                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5788                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5789                 
5790                 switch (i) {
5791                 case MONO_SECTION_TEXT:
5792                         /* patch entry point */
5793                         p = (guchar*)(assembly->code.data + 2);
5794                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5795                         *p++ = (value) & 0xff;
5796                         *p++ = (value >> 8) & 0xff;
5797                         *p++ = (value >> 16) & 0xff;
5798                         *p++ = (value >> 24) & 0xff;
5799                 
5800                         checked_write_file (file, assembly->code.data, assembly->code.index);
5801                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5802                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5803                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5804                                 
5805
5806                         g_free (assembly->image.raw_metadata);
5807                         break;
5808                 case MONO_SECTION_RELOC: {
5809                         struct {
5810                                 guint32 page_rva;
5811                                 guint32 block_size;
5812                                 guint16 type_and_offset;
5813                                 guint16 term;
5814                         } reloc;
5815                         
5816                         g_assert (sizeof (reloc) == 12);
5817                         
5818                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5819                         reloc.block_size = GUINT32_FROM_LE (12);
5820                         
5821                         /* 
5822                          * the entrypoint is always at the start of the text section 
5823                          * 3 is IMAGE_REL_BASED_HIGHLOW
5824                          * 2 is patch_size_rva - text_rva
5825                          */
5826                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5827                         reloc.term = 0;
5828                         
5829                         checked_write_file (file, &reloc, sizeof (reloc));
5830                         
5831                         break;
5832                 }
5833                 case MONO_SECTION_RSRC:
5834                         if (assembly->win32_res) {
5835
5836                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5837                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5838                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5839                         }
5840                         break;
5841                 default:
5842                         g_assert_not_reached ();
5843                 }
5844         }
5845         
5846         /* check that the file is properly padded */
5847         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5848                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5849         if (! SetEndOfFile (file))
5850                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5851         
5852         mono_dynamic_stream_reset (&assembly->code);
5853         mono_dynamic_stream_reset (&assembly->us);
5854         mono_dynamic_stream_reset (&assembly->blob);
5855         mono_dynamic_stream_reset (&assembly->guid);
5856         mono_dynamic_stream_reset (&assembly->sheap);
5857
5858         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5859         g_hash_table_destroy (assembly->blob_cache);
5860         assembly->blob_cache = NULL;
5861 }
5862
5863 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5864
5865 void
5866 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5867 {
5868         g_assert_not_reached ();
5869 }
5870
5871 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5872
5873 #ifndef DISABLE_REFLECTION_EMIT
5874
5875 MonoReflectionModule *
5876 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5877 {
5878         char *name;
5879         MonoImage *image;
5880         MonoImageOpenStatus status;
5881         MonoDynamicAssembly *assembly;
5882         guint32 module_count;
5883         MonoImage **new_modules;
5884         gboolean *new_modules_loaded;
5885         
5886         name = mono_string_to_utf8 (fileName);
5887
5888         image = mono_image_open (name, &status);
5889         if (!image) {
5890                 MonoException *exc;
5891                 if (status == MONO_IMAGE_ERROR_ERRNO)
5892                         exc = mono_get_exception_file_not_found (fileName);
5893                 else
5894                         exc = mono_get_exception_bad_image_format (name);
5895                 g_free (name);
5896                 mono_raise_exception (exc);
5897         }
5898
5899         g_free (name);
5900
5901         assembly = ab->dynamic_assembly;
5902         image->assembly = (MonoAssembly*)assembly;
5903
5904         module_count = image->assembly->image->module_count;
5905         new_modules = g_new0 (MonoImage *, module_count + 1);
5906         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5907
5908         if (image->assembly->image->modules)
5909                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5910         if (image->assembly->image->modules_loaded)
5911                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5912         new_modules [module_count] = image;
5913         new_modules_loaded [module_count] = TRUE;
5914         mono_image_addref (image);
5915
5916         g_free (image->assembly->image->modules);
5917         image->assembly->image->modules = new_modules;
5918         image->assembly->image->modules_loaded = new_modules_loaded;
5919         image->assembly->image->module_count ++;
5920
5921         mono_assembly_load_references (image, &status);
5922         if (status) {
5923                 mono_image_close (image);
5924                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5925         }
5926
5927         return mono_module_get_object (mono_domain_get (), image);
5928 }
5929
5930 #endif /* DISABLE_REFLECTION_EMIT */
5931
5932 /*
5933  * We need to return always the same object for MethodInfo, FieldInfo etc..
5934  * but we need to consider the reflected type.
5935  * type uses a different hash, since it uses custom hash/equal functions.
5936  */
5937
5938 typedef struct {
5939         gpointer item;
5940         MonoClass *refclass;
5941 } ReflectedEntry;
5942
5943 static gboolean
5944 reflected_equal (gconstpointer a, gconstpointer b) {
5945         const ReflectedEntry *ea = a;
5946         const ReflectedEntry *eb = b;
5947
5948         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5949 }
5950
5951 static guint
5952 reflected_hash (gconstpointer a) {
5953         const ReflectedEntry *ea = a;
5954         return mono_aligned_addr_hash (ea->item);
5955 }
5956
5957 #define CHECK_OBJECT(t,p,k)     \
5958         do {    \
5959                 t _obj; \
5960                 ReflectedEntry e;       \
5961                 e.item = (p);   \
5962                 e.refclass = (k);       \
5963                 mono_domain_lock (domain);      \
5964                 if (!domain->refobject_hash)    \
5965                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5966                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
5967                         mono_domain_unlock (domain);    \
5968                         return _obj;    \
5969                 }       \
5970         mono_domain_unlock (domain); \
5971         } while (0)
5972
5973 #ifdef HAVE_BOEHM_GC
5974 /* ReflectedEntry doesn't need to be GC tracked */
5975 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5976 #define FREE_REFENTRY(entry) g_free ((entry))
5977 #define REFENTRY_REQUIRES_CLEANUP
5978 #else
5979 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5980 /* FIXME: */
5981 #define FREE_REFENTRY(entry)
5982 #endif
5983
5984 #define CACHE_OBJECT(t,p,o,k)   \
5985         do {    \
5986                 t _obj; \
5987         ReflectedEntry pe; \
5988         pe.item = (p); \
5989         pe.refclass = (k); \
5990         mono_domain_lock (domain); \
5991                 if (!domain->refobject_hash)    \
5992                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
5993         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5994         if (!_obj) { \
5995                     ReflectedEntry *e = ALLOC_REFENTRY;         \
5996                     e->item = (p);      \
5997                     e->refclass = (k);  \
5998                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
5999             _obj = o; \
6000         } \
6001                 mono_domain_unlock (domain);    \
6002         return _obj; \
6003         } while (0)
6004
6005 static void
6006 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6007 {
6008         mono_domain_lock (domain);
6009         if (domain->refobject_hash) {
6010         ReflectedEntry pe;
6011                 gpointer orig_pe, orig_value;
6012
6013                 pe.item = o;
6014                 pe.refclass = klass;
6015                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6016                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6017                         FREE_REFENTRY (orig_pe);
6018                 }
6019         }
6020         mono_domain_unlock (domain);
6021 }
6022
6023 #ifdef REFENTRY_REQUIRES_CLEANUP
6024 static void
6025 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6026 {
6027         FREE_REFENTRY (key);
6028 }
6029 #endif
6030
6031 void
6032 mono_reflection_cleanup_domain (MonoDomain *domain)
6033 {
6034         if (domain->refobject_hash) {
6035 /*let's avoid scanning the whole hashtable if not needed*/
6036 #ifdef REFENTRY_REQUIRES_CLEANUP
6037                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6038 #endif
6039                 mono_g_hash_table_destroy (domain->refobject_hash);
6040                 domain->refobject_hash = NULL;
6041         }
6042 }
6043
6044 #ifndef DISABLE_REFLECTION_EMIT
6045 static gpointer
6046 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6047 {
6048         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6049 }
6050
6051 static gpointer
6052 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6053 {
6054         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6055 }
6056
6057 void
6058 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6059 {
6060         MonoDynamicImage *image = moduleb->dynamic_image;
6061         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6062         if (!image) {
6063                 MonoError error;
6064                 int module_count;
6065                 MonoImage **new_modules;
6066                 MonoImage *ass;
6067                 char *name, *fqname;
6068                 /*
6069                  * FIXME: we already created an image in mono_image_basic_init (), but
6070                  * we don't know which module it belongs to, since that is only 
6071                  * determined at assembly save time.
6072                  */
6073                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6074                 name = mono_string_to_utf8 (ab->name);
6075                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6076                 if (!mono_error_ok (&error)) {
6077                         g_free (name);
6078                         mono_error_raise_exception (&error);
6079                 }
6080                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6081
6082                 moduleb->module.image = &image->image;
6083                 moduleb->dynamic_image = image;
6084                 register_module (mono_object_domain (moduleb), moduleb, image);
6085
6086                 /* register the module with the assembly */
6087                 ass = ab->dynamic_assembly->assembly.image;
6088                 module_count = ass->module_count;
6089                 new_modules = g_new0 (MonoImage *, module_count + 1);
6090
6091                 if (ass->modules)
6092                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6093                 new_modules [module_count] = &image->image;
6094                 mono_image_addref (&image->image);
6095
6096                 g_free (ass->modules);
6097                 ass->modules = new_modules;
6098                 ass->module_count ++;
6099         }
6100 }
6101
6102 void
6103 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6104 {
6105         MonoDynamicImage *image = moduleb->dynamic_image;
6106
6107         g_assert (type->type);
6108         image->wrappers_type = mono_class_from_mono_type (type->type);
6109 }
6110
6111 #endif
6112
6113 /*
6114  * mono_assembly_get_object:
6115  * @domain: an app domain
6116  * @assembly: an assembly
6117  *
6118  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6119  */
6120 MonoReflectionAssembly*
6121 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6122 {
6123         static MonoClass *assembly_type;
6124         MonoReflectionAssembly *res;
6125         
6126         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6127         if (!assembly_type) {
6128                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6129                 if (class == NULL)
6130                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6131                 g_assert (class);
6132                 assembly_type = class;
6133         }
6134         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6135         res->assembly = assembly;
6136
6137         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6138 }
6139
6140
6141
6142 MonoReflectionModule*   
6143 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6144 {
6145         static MonoClass *module_type;
6146         MonoReflectionModule *res;
6147         char* basename;
6148         
6149         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6150         if (!module_type) {
6151                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6152                 if (class == NULL)
6153                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6154                 g_assert (class);
6155                 module_type = class;
6156         }
6157         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6158
6159         res->image = image;
6160         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6161
6162         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6163         basename = g_path_get_basename (image->name);
6164         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6165         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6166         
6167         g_free (basename);
6168
6169         if (image->assembly->image == image) {
6170                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6171         } else {
6172                 int i;
6173                 res->token = 0;
6174                 if (image->assembly->image->modules) {
6175                         for (i = 0; i < image->assembly->image->module_count; i++) {
6176                                 if (image->assembly->image->modules [i] == image)
6177                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6178                         }
6179                         g_assert (res->token);
6180                 }
6181         }
6182
6183         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6184 }
6185
6186 MonoReflectionModule*   
6187 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6188 {
6189         static MonoClass *module_type;
6190         MonoReflectionModule *res;
6191         MonoTableInfo *table;
6192         guint32 cols [MONO_FILE_SIZE];
6193         const char *name;
6194         guint32 i, name_idx;
6195         const char *val;
6196         
6197         if (!module_type) {
6198                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6199                 if (class == NULL)
6200                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6201                 g_assert (class);
6202                 module_type = class;
6203         }
6204         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6205
6206         table = &image->tables [MONO_TABLE_FILE];
6207         g_assert (table_index < table->rows);
6208         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6209
6210         res->image = NULL;
6211         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6212         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6213
6214         /* Check whenever the row has a corresponding row in the moduleref table */
6215         table = &image->tables [MONO_TABLE_MODULEREF];
6216         for (i = 0; i < table->rows; ++i) {
6217                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6218                 val = mono_metadata_string_heap (image, name_idx);
6219                 if (strcmp (val, name) == 0)
6220                         res->image = image->modules [i];
6221         }
6222
6223         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6224         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6225         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6226         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6227         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6228
6229         return res;
6230 }
6231
6232 static gboolean
6233 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6234 {
6235         if ((t1->type != t2->type) ||
6236             (t1->byref != t2->byref))
6237                 return FALSE;
6238
6239         switch (t1->type) {
6240         case MONO_TYPE_VOID:
6241         case MONO_TYPE_BOOLEAN:
6242         case MONO_TYPE_CHAR:
6243         case MONO_TYPE_I1:
6244         case MONO_TYPE_U1:
6245         case MONO_TYPE_I2:
6246         case MONO_TYPE_U2:
6247         case MONO_TYPE_I4:
6248         case MONO_TYPE_U4:
6249         case MONO_TYPE_I8:
6250         case MONO_TYPE_U8:
6251         case MONO_TYPE_R4:
6252         case MONO_TYPE_R8:
6253         case MONO_TYPE_STRING:
6254         case MONO_TYPE_I:
6255         case MONO_TYPE_U:
6256         case MONO_TYPE_OBJECT:
6257         case MONO_TYPE_TYPEDBYREF:
6258                 return TRUE;
6259         case MONO_TYPE_VALUETYPE:
6260         case MONO_TYPE_CLASS:
6261         case MONO_TYPE_SZARRAY:
6262                 return t1->data.klass == t2->data.klass;
6263         case MONO_TYPE_PTR:
6264                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6265         case MONO_TYPE_ARRAY:
6266                 if (t1->data.array->rank != t2->data.array->rank)
6267                         return FALSE;
6268                 return t1->data.array->eklass == t2->data.array->eklass;
6269         case MONO_TYPE_GENERICINST: {
6270                 int i;
6271                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6272                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6273                 if (i1->type_argc != i2->type_argc)
6274                         return FALSE;
6275                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6276                                                &t2->data.generic_class->container_class->byval_arg))
6277                         return FALSE;
6278                 /* FIXME: we should probably just compare the instance pointers directly.  */
6279                 for (i = 0; i < i1->type_argc; ++i) {
6280                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6281                                 return FALSE;
6282                 }
6283                 return TRUE;
6284         }
6285         case MONO_TYPE_VAR:
6286         case MONO_TYPE_MVAR:
6287                 return t1->data.generic_param == t2->data.generic_param;
6288         default:
6289                 g_error ("implement type compare for %0x!", t1->type);
6290                 return FALSE;
6291         }
6292
6293         return FALSE;
6294 }
6295
6296 static guint
6297 mymono_metadata_type_hash (MonoType *t1)
6298 {
6299         guint hash;
6300
6301         hash = t1->type;
6302
6303         hash |= t1->byref << 6; /* do not collide with t1->type values */
6304         switch (t1->type) {
6305         case MONO_TYPE_VALUETYPE:
6306         case MONO_TYPE_CLASS:
6307         case MONO_TYPE_SZARRAY:
6308                 /* check if the distribution is good enough */
6309                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6310         case MONO_TYPE_PTR:
6311                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6312         case MONO_TYPE_GENERICINST: {
6313                 int i;
6314                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6315                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6316                 hash *= 13;
6317                 for (i = 0; i < inst->type_argc; ++i) {
6318                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6319                         hash *= 13;
6320                 }
6321                 return hash;
6322         }
6323         }
6324         return hash;
6325 }
6326
6327 static MonoReflectionGenericClass*
6328 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6329 {
6330         static MonoClass *System_Reflection_MonoGenericClass;
6331         MonoReflectionGenericClass *res;
6332         MonoClass *klass, *gklass;
6333         MonoGenericInst *ginst;
6334         MonoArray *type_args;
6335         int i;
6336         MonoObject *tb;
6337
6338         g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
6339
6340         if (!System_Reflection_MonoGenericClass) {
6341                 System_Reflection_MonoGenericClass = mono_class_from_name (
6342                         mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6343                 g_assert (System_Reflection_MonoGenericClass);
6344         }
6345
6346         klass = mono_class_from_mono_type (geninst);
6347         gklass = klass->generic_class->container_class;
6348
6349         mono_class_init (klass);
6350
6351 #ifdef HAVE_SGEN_GC
6352         res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6353 #else
6354         res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6355 #endif
6356
6357         res->type.type = geninst;
6358         tb = mono_class_get_ref_info (gklass);
6359         g_assert (tb);
6360         g_assert (!strcmp (tb->vtable->klass->name, "TypeBuilder"));
6361         MONO_OBJECT_SETREF (res, generic_type, tb);
6362
6363         ginst = klass->generic_class->context.class_inst;
6364         type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6365         for (i = 0; i < ginst->type_argc; ++i)
6366                 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6367         MONO_OBJECT_SETREF (res, type_arguments, type_args);
6368
6369         return res;
6370 }
6371
6372 static gboolean
6373 verify_safe_for_managed_space (MonoType *type)
6374 {
6375         switch (type->type) {
6376 #ifdef DEBUG_HARDER
6377         case MONO_TYPE_ARRAY:
6378                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6379         case MONO_TYPE_PTR:
6380                 return verify_safe_for_managed_space (type->data.type);
6381         case MONO_TYPE_SZARRAY:
6382                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6383         case MONO_TYPE_GENERICINST: {
6384                 MonoGenericInst *inst = type->data.generic_class->inst;
6385                 int i;
6386                 if (!inst->is_open)
6387                         break;
6388                 for (i = 0; i < inst->type_argc; ++i)
6389                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6390                                 return FALSE;
6391                 break;
6392         }
6393 #endif
6394         case MONO_TYPE_VAR:
6395         case MONO_TYPE_MVAR:
6396                 return TRUE;
6397         }
6398         return TRUE;
6399 }
6400
6401 static MonoType*
6402 mono_type_normalize (MonoType *type)
6403 {
6404         int i;
6405         MonoGenericClass *gclass;
6406         MonoGenericInst *ginst;
6407         MonoClass *gtd;
6408         MonoGenericContainer *gcontainer;
6409         MonoType **argv = NULL;
6410         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6411
6412         if (type->type != MONO_TYPE_GENERICINST)
6413                 return type;
6414
6415         gclass = type->data.generic_class;
6416         ginst = gclass->context.class_inst;
6417         if (!ginst->is_open)
6418                 return type;
6419
6420         gtd = gclass->container_class;
6421         gcontainer = gtd->generic_container;
6422         argv = g_newa (MonoType*, ginst->type_argc);
6423
6424         for (i = 0; i < ginst->type_argc; ++i) {
6425                 MonoType *t = ginst->type_argv [i], *norm;
6426                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6427                         is_denorm_gtd = FALSE;
6428                 norm = mono_type_normalize (t);
6429                 argv [i] = norm;
6430                 if (norm != t)
6431                         requires_rebind = TRUE;
6432         }
6433
6434         if (is_denorm_gtd)
6435                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6436
6437         if (requires_rebind) {
6438                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6439                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6440         }
6441
6442         return type;
6443 }
6444 /*
6445  * mono_type_get_object:
6446  * @domain: an app domain
6447  * @type: a type
6448  *
6449  * Return an System.MonoType object representing the type @type.
6450  */
6451 MonoReflectionType*
6452 mono_type_get_object (MonoDomain *domain, MonoType *type)
6453 {
6454         MonoType *norm_type;
6455         MonoReflectionType *res;
6456         MonoClass *klass = mono_class_from_mono_type (type);
6457
6458         /*we must avoid using @type as it might have come
6459          * from a mono_metadata_type_dup and the caller
6460          * expects that is can be freed.
6461          * Using the right type from 
6462          */
6463         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6464
6465         /* void is very common */
6466         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6467                 return (MonoReflectionType*)domain->typeof_void;
6468
6469         /*
6470          * If the vtable of the given class was already created, we can use
6471          * the MonoType from there and avoid all locking and hash table lookups.
6472          * 
6473          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6474          * that the resulting object is different.   
6475          */
6476         if (type == &klass->byval_arg && !klass->image->dynamic) {
6477                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6478                 if (vtable && vtable->type)
6479                         return vtable->type;
6480         }
6481
6482         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6483         mono_domain_lock (domain);
6484         if (!domain->type_hash)
6485                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6486                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6487         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6488                 mono_domain_unlock (domain);
6489                 mono_loader_unlock ();
6490                 return res;
6491         }
6492
6493         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6494          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6495          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6496          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6497          * artifact of how generics are encoded and should be transparent to managed code so we
6498          * need to weed out this diference when retrieving managed System.Type objects.
6499          */
6500         norm_type = mono_type_normalize (type);
6501         if (norm_type != type) {
6502                 res = mono_type_get_object (domain, norm_type);
6503                 mono_g_hash_table_insert (domain->type_hash, type, res);
6504                 mono_domain_unlock (domain);
6505                 mono_loader_unlock ();
6506                 return res;
6507         }
6508
6509         /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6510         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6511                 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6512                 mono_g_hash_table_insert (domain->type_hash, type, res);
6513                 mono_domain_unlock (domain);
6514                 mono_loader_unlock ();
6515                 return res;
6516         }
6517
6518         if (!verify_safe_for_managed_space (type)) {
6519                 mono_domain_unlock (domain);
6520                 mono_loader_unlock ();
6521                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6522         }
6523
6524         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6525                 gboolean is_type_done = TRUE;
6526                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6527                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6528                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6529                 */
6530                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6531                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6532
6533                         if (gparam->owner && gparam->owner->is_method) {
6534                                 MonoMethod *method = gparam->owner->owner.method;
6535                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6536                                         is_type_done = FALSE;
6537                         } else if (gparam->owner && !gparam->owner->is_method) {
6538                                 MonoClass *klass = gparam->owner->owner.klass;
6539                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6540                                         is_type_done = FALSE;
6541                         }
6542                 } 
6543
6544                 /* g_assert_not_reached (); */
6545                 /* should this be considered an error condition? */
6546                 if (is_type_done && !type->byref) {
6547                         mono_domain_unlock (domain);
6548                         mono_loader_unlock ();
6549                         return mono_class_get_ref_info (klass);
6550                 }
6551         }
6552         // FIXME: Get rid of this, do it in the icalls for Type
6553         mono_class_init (klass);
6554 #ifdef HAVE_SGEN_GC
6555         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6556 #else
6557         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6558 #endif
6559         res->type = type;
6560         mono_g_hash_table_insert (domain->type_hash, type, res);
6561
6562         if (type->type == MONO_TYPE_VOID)
6563                 domain->typeof_void = (MonoObject*)res;
6564
6565         mono_domain_unlock (domain);
6566         mono_loader_unlock ();
6567         return res;
6568 }
6569
6570 /*
6571  * mono_method_get_object:
6572  * @domain: an app domain
6573  * @method: a method
6574  * @refclass: the reflected type (can be NULL)
6575  *
6576  * Return an System.Reflection.MonoMethod object representing the method @method.
6577  */
6578 MonoReflectionMethod*
6579 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6580 {
6581         /*
6582          * We use the same C representation for methods and constructors, but the type 
6583          * name in C# is different.
6584          */
6585         static MonoClass *System_Reflection_MonoMethod = NULL;
6586         static MonoClass *System_Reflection_MonoCMethod = NULL;
6587         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6588         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6589         MonoClass *klass;
6590         MonoReflectionMethod *ret;
6591
6592         if (method->is_inflated) {
6593                 MonoReflectionGenericMethod *gret;
6594
6595                 refclass = method->klass;
6596                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6598                         if (!System_Reflection_MonoGenericCMethod)
6599                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6600                         klass = System_Reflection_MonoGenericCMethod;
6601                 } else {
6602                         if (!System_Reflection_MonoGenericMethod)
6603                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6604                         klass = System_Reflection_MonoGenericMethod;
6605                 }
6606                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6607                 gret->method.method = method;
6608                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6609                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6611         }
6612
6613         if (!refclass)
6614                 refclass = method->klass;
6615
6616         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6617         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6618                 if (!System_Reflection_MonoCMethod)
6619                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6620                 klass = System_Reflection_MonoCMethod;
6621         }
6622         else {
6623                 if (!System_Reflection_MonoMethod)
6624                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6625                 klass = System_Reflection_MonoMethod;
6626         }
6627         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6628         ret->method = method;
6629         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6630         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6631 }
6632
6633 /*
6634  * mono_method_clear_object:
6635  *
6636  *   Clear the cached reflection objects for the dynamic method METHOD.
6637  */
6638 void
6639 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6640 {
6641         MonoClass *klass;
6642         g_assert (method->dynamic);
6643
6644         klass = method->klass;
6645         while (klass) {
6646                 clear_cached_object (domain, method, klass);
6647                 klass = klass->parent;
6648         }
6649         /* Added by mono_param_get_objects () */
6650         clear_cached_object (domain, &(method->signature), NULL);
6651         klass = method->klass;
6652         while (klass) {
6653                 clear_cached_object (domain, &(method->signature), klass);
6654                 klass = klass->parent;
6655         }
6656 }
6657
6658 /*
6659  * mono_field_get_object:
6660  * @domain: an app domain
6661  * @klass: a type
6662  * @field: a field
6663  *
6664  * Return an System.Reflection.MonoField object representing the field @field
6665  * in class @klass.
6666  */
6667 MonoReflectionField*
6668 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6669 {
6670         MonoReflectionField *res;
6671         static MonoClass *monofield_klass;
6672
6673         CHECK_OBJECT (MonoReflectionField *, field, klass);
6674         if (!monofield_klass)
6675                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6676         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6677         res->klass = klass;
6678         res->field = field;
6679         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6680         if (is_field_on_inst (field))
6681                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6682         else
6683                 res->attrs = field->type->attrs;
6684         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6685         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6686 }
6687
6688 /*
6689  * mono_property_get_object:
6690  * @domain: an app domain
6691  * @klass: a type
6692  * @property: a property
6693  *
6694  * Return an System.Reflection.MonoProperty object representing the property @property
6695  * in class @klass.
6696  */
6697 MonoReflectionProperty*
6698 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6699 {
6700         MonoReflectionProperty *res;
6701         static MonoClass *monoproperty_klass;
6702
6703         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6704         if (!monoproperty_klass)
6705                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6706         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6707         res->klass = klass;
6708         res->property = property;
6709         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6710 }
6711
6712 /*
6713  * mono_event_get_object:
6714  * @domain: an app domain
6715  * @klass: a type
6716  * @event: a event
6717  *
6718  * Return an System.Reflection.MonoEvent object representing the event @event
6719  * in class @klass.
6720  */
6721 MonoReflectionEvent*
6722 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6723 {
6724         MonoReflectionEvent *res;
6725         MonoReflectionMonoEvent *mono_event;
6726         static MonoClass *monoevent_klass;
6727
6728         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6729         if (!monoevent_klass)
6730                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6731         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6732         mono_event->klass = klass;
6733         mono_event->event = event;
6734         res = (MonoReflectionEvent*)mono_event;
6735         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6736 }
6737
6738 /**
6739  * mono_get_reflection_missing_object:
6740  * @domain: Domain where the object lives
6741  *
6742  * Returns the System.Reflection.Missing.Value singleton object
6743  * (of type System.Reflection.Missing).
6744  *
6745  * Used as the value for ParameterInfo.DefaultValue when Optional
6746  * is present
6747  */
6748 static MonoObject *
6749 mono_get_reflection_missing_object (MonoDomain *domain)
6750 {
6751         MonoObject *obj;
6752         static MonoClassField *missing_value_field = NULL;
6753         
6754         if (!missing_value_field) {
6755                 MonoClass *missing_klass;
6756                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6757                 mono_class_init (missing_klass);
6758                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6759                 g_assert (missing_value_field);
6760         }
6761         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6762         g_assert (obj);
6763         return obj;
6764 }
6765
6766 static MonoObject*
6767 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6768 {
6769         if (!*dbnull)
6770                 *dbnull = mono_get_dbnull_object (domain);
6771         return *dbnull;
6772 }
6773
6774 static MonoObject*
6775 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6776 {
6777         if (!*reflection_missing)
6778                 *reflection_missing = mono_get_reflection_missing_object (domain);
6779         return *reflection_missing;
6780 }
6781
6782 /*
6783  * mono_param_get_objects:
6784  * @domain: an app domain
6785  * @method: a method
6786  *
6787  * Return an System.Reflection.ParameterInfo array object representing the parameters
6788  * in the method @method.
6789  */
6790 MonoArray*
6791 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6792 {
6793         static MonoClass *System_Reflection_ParameterInfo;
6794         static MonoClass *System_Reflection_ParameterInfo_array;
6795         MonoArray *res = NULL;
6796         MonoReflectionMethod *member = NULL;
6797         MonoReflectionParameter *param = NULL;
6798         char **names, **blobs = NULL;
6799         guint32 *types = NULL;
6800         MonoType *type = NULL;
6801         MonoObject *dbnull = NULL;
6802         MonoObject *missing = NULL;
6803         MonoMarshalSpec **mspecs;
6804         MonoMethodSignature *sig;
6805         MonoVTable *pinfo_vtable;
6806         int i;
6807
6808         if (!System_Reflection_ParameterInfo_array) {
6809                 MonoClass *klass;
6810
6811                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6812                 mono_memory_barrier ();
6813                 System_Reflection_ParameterInfo = klass; 
6814         
6815                 klass = mono_array_class_get (klass, 1);
6816                 mono_memory_barrier ();
6817                 System_Reflection_ParameterInfo_array = klass;
6818         }
6819         
6820         if (!mono_method_signature (method)->param_count)
6821                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6822
6823         /* Note: the cache is based on the address of the signature into the method
6824          * since we already cache MethodInfos with the method as keys.
6825          */
6826         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6827
6828         sig = mono_method_signature (method);
6829         member = mono_method_get_object (domain, method, refclass);
6830         names = g_new (char *, sig->param_count);
6831         mono_method_get_param_names (method, (const char **) names);
6832
6833         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6834         mono_method_get_marshal_info (method, mspecs);
6835
6836         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6837         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6838         for (i = 0; i < sig->param_count; ++i) {
6839                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6840                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6841                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6842                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6843                 param->PositionImpl = i;
6844                 param->AttrsImpl = sig->params [i]->attrs;
6845
6846                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6847                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6848                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6849                         else
6850                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6851                 } else {
6852
6853                         if (!blobs) {
6854                                 blobs = g_new0 (char *, sig->param_count);
6855                                 types = g_new0 (guint32, sig->param_count);
6856                                 get_default_param_value_blobs (method, blobs, types); 
6857                         }
6858
6859                         /* Build MonoType for the type from the Constant Table */
6860                         if (!type)
6861                                 type = g_new0 (MonoType, 1);
6862                         type->type = types [i];
6863                         type->data.klass = NULL;
6864                         if (types [i] == MONO_TYPE_CLASS)
6865                                 type->data.klass = mono_defaults.object_class;
6866                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6867                                 /* For enums, types [i] contains the base type */
6868
6869                                         type->type = MONO_TYPE_VALUETYPE;
6870                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6871                         } else
6872                                 type->data.klass = mono_class_from_mono_type (type);
6873
6874                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6875
6876                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6877                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6878                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6879                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6880                                 else
6881                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6882                         }
6883                         
6884                 }
6885
6886                 if (mspecs [i + 1])
6887                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6888                 
6889                 mono_array_setref (res, i, param);
6890         }
6891         g_free (names);
6892         g_free (blobs);
6893         g_free (types);
6894         g_free (type);
6895
6896         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6897                 if (mspecs [i])
6898                         mono_metadata_free_marshal_spec (mspecs [i]);
6899         g_free (mspecs);
6900         
6901         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6902 }
6903
6904 MonoArray*
6905 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6906 {
6907         return mono_param_get_objects_internal (domain, method, NULL);
6908 }
6909
6910 /*
6911  * mono_method_body_get_object:
6912  * @domain: an app domain
6913  * @method: a method
6914  *
6915  * Return an System.Reflection.MethodBody object representing the method @method.
6916  */
6917 MonoReflectionMethodBody*
6918 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6919 {
6920         static MonoClass *System_Reflection_MethodBody = NULL;
6921         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6922         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6923         MonoReflectionMethodBody *ret;
6924         MonoMethodHeader *header;
6925         guint32 method_rva, local_var_sig_token;
6926     char *ptr;
6927         unsigned char format, flags;
6928         int i;
6929
6930         if (!System_Reflection_MethodBody)
6931                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6932         if (!System_Reflection_LocalVariableInfo)
6933                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6934         if (!System_Reflection_ExceptionHandlingClause)
6935                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6936
6937         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6938
6939         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6940                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6941             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6942             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6943                 return NULL;
6944         header = mono_method_get_header (method);
6945         
6946         /* Obtain local vars signature token */
6947         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6948         ptr = mono_image_rva_map (method->klass->image, method_rva);
6949         flags = *(const unsigned char *) ptr;
6950         format = flags & METHOD_HEADER_FORMAT_MASK;
6951         switch (format){
6952         case METHOD_HEADER_TINY_FORMAT:
6953                 local_var_sig_token = 0;
6954                 break;
6955         case METHOD_HEADER_FAT_FORMAT:
6956                 ptr += 2;
6957                 ptr += 2;
6958                 ptr += 4;
6959                 local_var_sig_token = read32 (ptr);
6960                 break;
6961         default:
6962                 g_assert_not_reached ();
6963         }
6964
6965         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6966
6967         ret->init_locals = header->init_locals;
6968         ret->max_stack = header->max_stack;
6969         ret->local_var_sig_token = local_var_sig_token;
6970         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6971         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6972
6973         /* Locals */
6974         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6975         for (i = 0; i < header->num_locals; ++i) {
6976                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6977                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6978                 info->is_pinned = header->locals [i]->pinned;
6979                 info->local_index = i;
6980                 mono_array_setref (ret->locals, i, info);
6981         }
6982
6983         /* Exceptions */
6984         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6985         for (i = 0; i < header->num_clauses; ++i) {
6986                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6987                 MonoExceptionClause *clause = &header->clauses [i];
6988
6989                 info->flags = clause->flags;
6990                 info->try_offset = clause->try_offset;
6991                 info->try_length = clause->try_len;
6992                 info->handler_offset = clause->handler_offset;
6993                 info->handler_length = clause->handler_len;
6994                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6995                         info->filter_offset = clause->data.filter_offset;
6996                 else if (clause->data.catch_class)
6997                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6998
6999                 mono_array_setref (ret->clauses, i, info);
7000         }
7001
7002         mono_metadata_free_mh (header);
7003         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7004         return ret;
7005 }
7006
7007 /**
7008  * mono_get_dbnull_object:
7009  * @domain: Domain where the object lives
7010  *
7011  * Returns the System.DBNull.Value singleton object
7012  *
7013  * Used as the value for ParameterInfo.DefaultValue 
7014  */
7015 MonoObject *
7016 mono_get_dbnull_object (MonoDomain *domain)
7017 {
7018         MonoObject *obj;
7019         static MonoClassField *dbnull_value_field = NULL;
7020         
7021         if (!dbnull_value_field) {
7022                 MonoClass *dbnull_klass;
7023                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7024                 mono_class_init (dbnull_klass);
7025                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7026                 g_assert (dbnull_value_field);
7027         }
7028         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7029         g_assert (obj);
7030         return obj;
7031 }
7032
7033 static void
7034 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7035 {
7036         guint32 param_index, i, lastp, crow = 0;
7037         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7038         gint32 idx;
7039
7040         MonoClass *klass = method->klass;
7041         MonoImage *image = klass->image;
7042         MonoMethodSignature *methodsig = mono_method_signature (method);
7043
7044         MonoTableInfo *constt;
7045         MonoTableInfo *methodt;
7046         MonoTableInfo *paramt;
7047
7048         if (!methodsig->param_count)
7049                 return;
7050
7051         mono_class_init (klass);
7052
7053         if (klass->image->dynamic) {
7054                 MonoReflectionMethodAux *aux;
7055                 if (method->is_inflated)
7056                         method = ((MonoMethodInflated*)method)->declaring;
7057                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7058                 if (aux && aux->param_defaults) {
7059                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7060                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7061                 }
7062                 return;
7063         }
7064
7065         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7066         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7067         constt = &image->tables [MONO_TABLE_CONSTANT];
7068
7069         idx = mono_method_get_index (method) - 1;
7070         g_assert (idx != -1);
7071
7072         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7073         if (idx + 1 < methodt->rows)
7074                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7075         else
7076                 lastp = paramt->rows + 1;
7077
7078         for (i = param_index; i < lastp; ++i) {
7079                 guint32 paramseq;
7080
7081                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7082                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7083
7084                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7085                         continue;
7086
7087                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7088                 if (!crow) {
7089                         continue;
7090                 }
7091         
7092                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7093                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7094                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7095         }
7096
7097         return;
7098 }
7099
7100 MonoObject *
7101 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7102 {
7103         void *retval;
7104         MonoClass *klass;
7105         MonoObject *object;
7106         MonoType *basetype = type;
7107
7108         if (!blob)
7109                 return NULL;
7110         
7111         klass = mono_class_from_mono_type (type);
7112         if (klass->valuetype) {
7113                 object = mono_object_new (domain, klass);
7114                 retval = ((gchar *) object + sizeof (MonoObject));
7115                 if (klass->enumtype)
7116                         basetype = mono_class_enum_basetype (klass);
7117         } else {
7118                 retval = &object;
7119         }
7120                         
7121         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7122                 return object;
7123         else
7124                 return NULL;
7125 }
7126
7127 static int
7128 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7129         int found_sep;
7130         char *s;
7131
7132         memset (assembly, 0, sizeof (MonoAssemblyName));
7133         assembly->name = p;
7134         assembly->culture = "";
7135         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7136
7137         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7138                 p++;
7139         found_sep = 0;
7140         while (g_ascii_isspace (*p) || *p == ',') {
7141                 *p++ = 0;
7142                 found_sep = 1;
7143                 continue;
7144         }
7145         /* failed */
7146         if (!found_sep)
7147                 return 1;
7148         while (*p) {
7149                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7150                         p += 8;
7151                         assembly->major = strtoul (p, &s, 10);
7152                         if (s == p || *s != '.')
7153                                 return 1;
7154                         p = ++s;
7155                         assembly->minor = strtoul (p, &s, 10);
7156                         if (s == p || *s != '.')
7157                                 return 1;
7158                         p = ++s;
7159                         assembly->build = strtoul (p, &s, 10);
7160                         if (s == p || *s != '.')
7161                                 return 1;
7162                         p = ++s;
7163                         assembly->revision = strtoul (p, &s, 10);
7164                         if (s == p)
7165                                 return 1;
7166                         p = s;
7167                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7168                         p += 8;
7169                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7170                                 assembly->culture = "";
7171                                 p += 7;
7172                         } else {
7173                                 assembly->culture = p;
7174                                 while (*p && *p != ',') {
7175                                         p++;
7176                                 }
7177                         }
7178                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7179                         p += 15;
7180                         if (strncmp (p, "null", 4) == 0) {
7181                                 p += 4;
7182                         } else {
7183                                 int len;
7184                                 gchar *start = p;
7185                                 while (*p && *p != ',') {
7186                                         p++;
7187                                 }
7188                                 len = (p - start + 1);
7189                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7190                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7191                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7192                         }
7193                 } else {
7194                         while (*p && *p != ',')
7195                                 p++;
7196                 }
7197                 found_sep = 0;
7198                 while (g_ascii_isspace (*p) || *p == ',') {
7199                         *p++ = 0;
7200                         found_sep = 1;
7201                         continue;
7202                 }
7203                 /* failed */
7204                 if (!found_sep)
7205                         return 1;
7206         }
7207
7208         return 0;
7209 }
7210
7211 /*
7212  * mono_reflection_parse_type:
7213  * @name: type name
7214  *
7215  * Parse a type name as accepted by the GetType () method and output the info
7216  * extracted in the info structure.
7217  * the name param will be mangled, so, make a copy before passing it to this function.
7218  * The fields in info will be valid until the memory pointed to by name is valid.
7219  *
7220  * See also mono_type_get_name () below.
7221  *
7222  * Returns: 0 on parse error.
7223  */
7224 static int
7225 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7226                              MonoTypeNameParse *info)
7227 {
7228         char *start, *p, *w, *temp, *last_point, *startn;
7229         int in_modifiers = 0;
7230         int isbyref = 0, rank, arity = 0, i;
7231
7232         start = p = w = name;
7233
7234         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7235         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7236         info->name = info->name_space = NULL;
7237         info->nested = NULL;
7238         info->modifiers = NULL;
7239         info->type_arguments = NULL;
7240
7241         /* last_point separates the namespace from the name */
7242         last_point = NULL;
7243         /* Skips spaces */
7244         while (*p == ' ') p++, start++, w++, name++;
7245
7246         while (*p) {
7247                 switch (*p) {
7248                 case '+':
7249                         *p = 0; /* NULL terminate the name */
7250                         startn = p + 1;
7251                         info->nested = g_list_append (info->nested, startn);
7252                         /* we have parsed the nesting namespace + name */
7253                         if (info->name)
7254                                 break;
7255                         if (last_point) {
7256                                 info->name_space = start;
7257                                 *last_point = 0;
7258                                 info->name = last_point + 1;
7259                         } else {
7260                                 info->name_space = (char *)"";
7261                                 info->name = start;
7262                         }
7263                         break;
7264                 case '.':
7265                         last_point = p;
7266                         break;
7267                 case '\\':
7268                         ++p;
7269                         break;
7270                 case '&':
7271                 case '*':
7272                 case '[':
7273                 case ',':
7274                 case ']':
7275                         in_modifiers = 1;
7276                         break;
7277                 case '`':
7278                         ++p;
7279                         i = strtol (p, &temp, 10);
7280                         arity += i;
7281                         if (p == temp)
7282                                 return 0;
7283                         p = temp-1;
7284                         break;
7285                 default:
7286                         break;
7287                 }
7288                 if (in_modifiers)
7289                         break;
7290                 // *w++ = *p++;
7291                 p++;
7292         }
7293         
7294         if (!info->name) {
7295                 if (last_point) {
7296                         info->name_space = start;
7297                         *last_point = 0;
7298                         info->name = last_point + 1;
7299                 } else {
7300                         info->name_space = (char *)"";
7301                         info->name = start;
7302                 }
7303         }
7304         while (*p) {
7305                 switch (*p) {
7306                 case '&':
7307                         if (isbyref) /* only one level allowed by the spec */
7308                                 return 0;
7309                         isbyref = 1;
7310                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7311                         *p++ = 0;
7312                         break;
7313                 case '*':
7314                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7315                         *p++ = 0;
7316                         break;
7317                 case '[':
7318                         if (arity != 0) {
7319                                 *p++ = 0;
7320                                 info->type_arguments = g_ptr_array_new ();
7321                                 for (i = 0; i < arity; i++) {
7322                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7323                                         gboolean fqname = FALSE;
7324
7325                                         g_ptr_array_add (info->type_arguments, subinfo);
7326
7327                                         if (*p == '[') {
7328                                                 p++;
7329                                                 fqname = TRUE;
7330                                         }
7331
7332                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7333                                                 return 0;
7334
7335                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7336                                         if (fqname && (*p != ']')) {
7337                                                 char *aname;
7338
7339                                                 if (*p != ',')
7340                                                         return 0;
7341                                                 *p++ = 0;
7342
7343                                                 aname = p;
7344                                                 while (*p && (*p != ']'))
7345                                                         p++;
7346
7347                                                 if (*p != ']')
7348                                                         return 0;
7349
7350                                                 *p++ = 0;
7351                                                 while (*aname) {
7352                                                         if (g_ascii_isspace (*aname)) {
7353                                                                 ++aname;
7354                                                                 continue;
7355                                                         }
7356                                                         break;
7357                                                 }
7358                                                 if (!*aname ||
7359                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7360                                                         return 0;
7361                                         } else if (fqname && (*p == ']')) {
7362                                                 *p++ = 0;
7363                                         }
7364
7365                                         if (i + 1 < arity) {
7366                                                 if (*p != ',')
7367                                                         return 0;
7368                                         } else {
7369                                                 if (*p != ']')
7370                                                         return 0;
7371                                         }
7372                                         *p++ = 0;
7373                                 }
7374
7375                                 arity = 0;
7376                                 break;
7377                         }
7378                         rank = 1;
7379                         *p++ = 0;
7380                         while (*p) {
7381                                 if (*p == ']')
7382                                         break;
7383                                 if (*p == ',')
7384                                         rank++;
7385                                 else if (*p == '*') /* '*' means unknown lower bound */
7386                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7387                                 else
7388                                         return 0;
7389                                 ++p;
7390                         }
7391                         if (*p++ != ']')
7392                                 return 0;
7393                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7394                         break;
7395                 case ']':
7396                         if (is_recursed)
7397                                 goto end;
7398                         return 0;
7399                 case ',':
7400                         if (is_recursed)
7401                                 goto end;
7402                         *p++ = 0;
7403                         while (*p) {
7404                                 if (g_ascii_isspace (*p)) {
7405                                         ++p;
7406                                         continue;
7407                                 }
7408                                 break;
7409                         }
7410                         if (!*p)
7411                                 return 0; /* missing assembly name */
7412                         if (!assembly_name_to_aname (&info->assembly, p))
7413                                 return 0;
7414                         break;
7415                 default:
7416                         return 0;
7417                 }
7418                 if (info->assembly.name)
7419                         break;
7420         }
7421         // *w = 0; /* terminate class name */
7422  end:
7423         if (!info->name || !*info->name)
7424                 return 0;
7425         if (endptr)
7426                 *endptr = p;
7427         /* add other consistency checks */
7428         return 1;
7429 }
7430
7431 int
7432 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7433 {
7434         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7435 }
7436
7437 static MonoType*
7438 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7439 {
7440         gboolean type_resolve = FALSE;
7441         MonoType *type;
7442         MonoImage *rootimage = image;
7443
7444         if (info->assembly.name) {
7445                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7446                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7447                         /* 
7448                          * This could happen in the AOT compiler case when the search hook is not
7449                          * installed.
7450                          */
7451                         assembly = image->assembly;
7452                 if (!assembly) {
7453                         /* then we must load the assembly ourselve - see #60439 */
7454                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7455                         if (!assembly)
7456                                 return NULL;
7457                 }
7458                 image = assembly->image;
7459         } else if (!image) {
7460                 image = mono_defaults.corlib;
7461         }
7462
7463         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7465                 image = mono_defaults.corlib;
7466                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7467         }
7468
7469         return type;
7470 }
7471
7472 static MonoType*
7473 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7474 {
7475         MonoClass *klass;
7476         GList *mod;
7477         int modval;
7478         gboolean bounded = FALSE;
7479         
7480         if (!image)
7481                 image = mono_defaults.corlib;
7482
7483         if (ignorecase)
7484                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7485         else
7486                 klass = mono_class_from_name (image, info->name_space, info->name);
7487         if (!klass)
7488                 return NULL;
7489         for (mod = info->nested; mod; mod = mod->next) {
7490                 gpointer iter = NULL;
7491                 MonoClass *parent;
7492
7493                 parent = klass;
7494                 mono_class_init (parent);
7495
7496                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7497                         if (ignorecase) {
7498                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7499                                         break;
7500                         } else {
7501                                 if (strcmp (klass->name, mod->data) == 0)
7502                                         break;
7503                         }
7504                 }
7505                 if (!klass)
7506                         break;
7507         }
7508         if (!klass)
7509                 return NULL;
7510         mono_class_init (klass);
7511
7512         if (info->type_arguments) {
7513                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7514                 MonoReflectionType *the_type;
7515                 MonoType *instance;
7516                 int i;
7517
7518                 for (i = 0; i < info->type_arguments->len; i++) {
7519                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7520
7521                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7522                         if (!type_args [i]) {
7523                                 g_free (type_args);
7524                                 return NULL;
7525                         }
7526                 }
7527
7528                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7529
7530                 instance = mono_reflection_bind_generic_parameters (
7531                         the_type, info->type_arguments->len, type_args);
7532
7533                 g_free (type_args);
7534                 if (!instance)
7535                         return NULL;
7536
7537                 klass = mono_class_from_mono_type (instance);
7538         }
7539
7540         for (mod = info->modifiers; mod; mod = mod->next) {
7541                 modval = GPOINTER_TO_UINT (mod->data);
7542                 if (!modval) { /* byref: must be last modifier */
7543                         return &klass->this_arg;
7544                 } else if (modval == -1) {
7545                         klass = mono_ptr_class_get (&klass->byval_arg);
7546                 } else if (modval == -2) {
7547                         bounded = TRUE;
7548                 } else { /* array rank */
7549                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7550                 }
7551                 mono_class_init (klass);
7552         }
7553
7554         return &klass->byval_arg;
7555 }
7556
7557 /*
7558  * mono_reflection_get_type:
7559  * @image: a metadata context
7560  * @info: type description structure
7561  * @ignorecase: flag for case-insensitive string compares
7562  * @type_resolve: whenever type resolve was already tried
7563  *
7564  * Build a MonoType from the type description in @info.
7565  * 
7566  */
7567
7568 MonoType*
7569 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7570         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7571 }
7572
7573 static MonoType*
7574 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7575 {
7576         MonoReflectionAssemblyBuilder *abuilder;
7577         MonoType *type;
7578         int i;
7579
7580         g_assert (assembly->dynamic);
7581         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7582
7583         /* Enumerate all modules */
7584
7585         type = NULL;
7586         if (abuilder->modules) {
7587                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7588                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7589                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7590                         if (type)
7591                                 break;
7592                 }
7593         }
7594
7595         if (!type && abuilder->loaded_modules) {
7596                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7597                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7598                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7599                         if (type)
7600                                 break;
7601                 }
7602         }
7603
7604         return type;
7605 }
7606         
7607 MonoType*
7608 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7609 {
7610         MonoType *type;
7611         MonoReflectionAssembly *assembly;
7612         GString *fullName;
7613         GList *mod;
7614
7615         if (image && image->dynamic)
7616                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7617         else
7618                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7619         if (type)
7620                 return type;
7621         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7622                 return NULL;
7623
7624         if (type_resolve) {
7625                 if (*type_resolve) 
7626                         return NULL;
7627                 else
7628                         *type_resolve = TRUE;
7629         }
7630         
7631         /* Reconstruct the type name */
7632         fullName = g_string_new ("");
7633         if (info->name_space && (info->name_space [0] != '\0'))
7634                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7635         else
7636                 g_string_printf (fullName, "%s", info->name);
7637         for (mod = info->nested; mod; mod = mod->next)
7638                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7639
7640         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7641         if (assembly) {
7642                 if (assembly->assembly->dynamic)
7643                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7644                 else
7645                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7646                                                                                                           info, ignorecase);
7647         }
7648         g_string_free (fullName, TRUE);
7649         return type;
7650 }
7651
7652 void
7653 mono_reflection_free_type_info (MonoTypeNameParse *info)
7654 {
7655         g_list_free (info->modifiers);
7656         g_list_free (info->nested);
7657
7658         if (info->type_arguments) {
7659                 int i;
7660
7661                 for (i = 0; i < info->type_arguments->len; i++) {
7662                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7663
7664                         mono_reflection_free_type_info (subinfo);
7665                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7666                         g_free (subinfo);
7667                 }
7668
7669                 g_ptr_array_free (info->type_arguments, TRUE);
7670         }
7671 }
7672
7673 /*
7674  * mono_reflection_type_from_name:
7675  * @name: type name.
7676  * @image: a metadata context (can be NULL).
7677  *
7678  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7679  * it defaults to get the type from @image or, if @image is NULL or loading
7680  * from it fails, uses corlib.
7681  * 
7682  */
7683 MonoType*
7684 mono_reflection_type_from_name (char *name, MonoImage *image)
7685 {
7686         MonoType *type = NULL;
7687         MonoTypeNameParse info;
7688         char *tmp;
7689
7690         /* Make a copy since parse_type modifies its argument */
7691         tmp = g_strdup (name);
7692         
7693         /*g_print ("requested type %s\n", str);*/
7694         if (mono_reflection_parse_type (tmp, &info)) {
7695                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7696         }
7697
7698         g_free (tmp);
7699         mono_reflection_free_type_info (&info);
7700         return type;
7701 }
7702
7703 /*
7704  * mono_reflection_get_token:
7705  *
7706  *   Return the metadata token of OBJ which should be an object
7707  * representing a metadata element.
7708  */
7709 guint32
7710 mono_reflection_get_token (MonoObject *obj)
7711 {
7712         MonoClass *klass;
7713         guint32 token = 0;
7714
7715         klass = obj->vtable->klass;
7716
7717         if (strcmp (klass->name, "MethodBuilder") == 0) {
7718                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7719
7720                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7721         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7722                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7723
7724                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7725         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7726                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7727
7728                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7729                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7730         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7731                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7732                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7733         } else if (strcmp (klass->name, "MonoType") == 0) {
7734                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7735                 token = mono_class_from_mono_type (type)->type_token;
7736         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7737                    strcmp (klass->name, "MonoMethod") == 0 ||
7738                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7739                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7740                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7741                 if (m->method->is_inflated) {
7742                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7743                         return inflated->declaring->token;
7744                 } else {
7745                         token = m->method->token;
7746                 }
7747         } else if (strcmp (klass->name, "MonoField") == 0) {
7748                 MonoReflectionField *f = (MonoReflectionField*)obj;
7749
7750                 if (is_field_on_inst (f->field)) {
7751                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7752                         int field_index = f->field - dgclass->fields;
7753                         MonoObject *obj;
7754
7755                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7756                         obj = dgclass->field_objects [field_index];
7757                         return mono_reflection_get_token (obj);
7758                 }
7759                 token = mono_class_get_field_token (f->field);
7760         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7761                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7762
7763                 token = mono_class_get_property_token (p->property);
7764         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7765                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7766
7767                 token = mono_class_get_event_token (p->event);
7768         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7769                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7770                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7771                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7772
7773                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7774         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7775                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7776
7777                 token = m->token;
7778         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7779                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7780         } else {
7781                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7782                 MonoException *ex = mono_get_exception_not_implemented (msg);
7783                 g_free (msg);
7784                 mono_raise_exception (ex);
7785         }
7786
7787         return token;
7788 }
7789
7790 static void*
7791 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7792 {
7793         int slen, type = t->type;
7794         MonoClass *tklass = t->data.klass;
7795
7796 handle_enum:
7797         switch (type) {
7798         case MONO_TYPE_U1:
7799         case MONO_TYPE_I1:
7800         case MONO_TYPE_BOOLEAN: {
7801                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7802                 *bval = *p;
7803                 *end = p + 1;
7804                 return bval;
7805         }
7806         case MONO_TYPE_CHAR:
7807         case MONO_TYPE_U2:
7808         case MONO_TYPE_I2: {
7809                 guint16 *val = g_malloc (sizeof (guint16));
7810                 *val = read16 (p);
7811                 *end = p + 2;
7812                 return val;
7813         }
7814 #if SIZEOF_VOID_P == 4
7815         case MONO_TYPE_U:
7816         case MONO_TYPE_I:
7817 #endif
7818         case MONO_TYPE_R4:
7819         case MONO_TYPE_U4:
7820         case MONO_TYPE_I4: {
7821                 guint32 *val = g_malloc (sizeof (guint32));
7822                 *val = read32 (p);
7823                 *end = p + 4;
7824                 return val;
7825         }
7826 #if SIZEOF_VOID_P == 8
7827         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7828         case MONO_TYPE_I:
7829 #endif
7830         case MONO_TYPE_U8:
7831         case MONO_TYPE_I8: {
7832                 guint64 *val = g_malloc (sizeof (guint64));
7833                 *val = read64 (p);
7834                 *end = p + 8;
7835                 return val;
7836         }
7837         case MONO_TYPE_R8: {
7838                 double *val = g_malloc (sizeof (double));
7839                 readr8 (p, val);
7840                 *end = p + 8;
7841                 return val;
7842         }
7843         case MONO_TYPE_VALUETYPE:
7844                 if (t->data.klass->enumtype) {
7845                         type = mono_class_enum_basetype (t->data.klass)->type;
7846                         goto handle_enum;
7847                 } else {
7848                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7849                 }
7850                 break;
7851         case MONO_TYPE_STRING:
7852                 if (*p == (char)0xFF) {
7853                         *end = p + 1;
7854                         return NULL;
7855                 }
7856                 slen = mono_metadata_decode_value (p, &p);
7857                 *end = p + slen;
7858                 return mono_string_new_len (mono_domain_get (), p, slen);
7859         case MONO_TYPE_CLASS: {
7860                 char *n;
7861                 MonoType *t;
7862                 if (*p == (char)0xFF) {
7863                         *end = p + 1;
7864                         return NULL;
7865                 }
7866 handle_type:
7867                 slen = mono_metadata_decode_value (p, &p);
7868                 n = g_memdup (p, slen + 1);
7869                 n [slen] = 0;
7870                 t = mono_reflection_type_from_name (n, image);
7871                 if (!t)
7872                         g_warning ("Cannot load type '%s'", n);
7873                 g_free (n);
7874                 *end = p + slen;
7875                 if (t)
7876                         return mono_type_get_object (mono_domain_get (), t);
7877                 else
7878                         return NULL;
7879         }
7880         case MONO_TYPE_OBJECT: {
7881                 char subt = *p++;
7882                 MonoObject *obj;
7883                 MonoClass *subc = NULL;
7884                 void *val;
7885
7886                 if (subt == 0x50) {
7887                         goto handle_type;
7888                 } else if (subt == 0x0E) {
7889                         type = MONO_TYPE_STRING;
7890                         goto handle_enum;
7891                 } else if (subt == 0x1D) {
7892                         MonoType simple_type = {{0}};
7893                         int etype = *p;
7894                         p ++;
7895
7896                         if (etype == 0x51)
7897                                 /* See Partition II, Appendix B3 */
7898                                 etype = MONO_TYPE_OBJECT;
7899                         type = MONO_TYPE_SZARRAY;
7900                         simple_type.type = etype;
7901                         tklass = mono_class_from_mono_type (&simple_type);
7902                         goto handle_enum;
7903                 } else if (subt == 0x55) {
7904                         char *n;
7905                         MonoType *t;
7906                         slen = mono_metadata_decode_value (p, &p);
7907                         n = g_memdup (p, slen + 1);
7908                         n [slen] = 0;
7909                         t = mono_reflection_type_from_name (n, image);
7910                         if (!t)
7911                                 g_error ("Cannot load type '%s'", n);
7912                         g_free (n);
7913                         p += slen;
7914                         subc = mono_class_from_mono_type (t);
7915                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7916                         MonoType simple_type = {{0}};
7917                         simple_type.type = subt;
7918                         subc = mono_class_from_mono_type (&simple_type);
7919                 } else {
7920                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7921                 }
7922                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7923                 obj = mono_object_new (mono_domain_get (), subc);
7924                 g_assert (!subc->has_references);
7925                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7926                 g_free (val);
7927                 return obj;
7928         }
7929         case MONO_TYPE_SZARRAY: {
7930                 MonoArray *arr;
7931                 guint32 i, alen, basetype;
7932                 alen = read32 (p);
7933                 p += 4;
7934                 if (alen == 0xffffffff) {
7935                         *end = p;
7936                         return NULL;
7937                 }
7938                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7939                 basetype = tklass->byval_arg.type;
7940                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7941                         basetype = mono_class_enum_basetype (tklass)->type;
7942                 switch (basetype)
7943                 {
7944                         case MONO_TYPE_U1:
7945                         case MONO_TYPE_I1:
7946                         case MONO_TYPE_BOOLEAN:
7947                                 for (i = 0; i < alen; i++) {
7948                                         MonoBoolean val = *p++;
7949                                         mono_array_set (arr, MonoBoolean, i, val);
7950                                 }
7951                                 break;
7952                         case MONO_TYPE_CHAR:
7953                         case MONO_TYPE_U2:
7954                         case MONO_TYPE_I2:
7955                                 for (i = 0; i < alen; i++) {
7956                                         guint16 val = read16 (p);
7957                                         mono_array_set (arr, guint16, i, val);
7958                                         p += 2;
7959                                 }
7960                                 break;
7961                         case MONO_TYPE_R4:
7962                         case MONO_TYPE_U4:
7963                         case MONO_TYPE_I4:
7964                                 for (i = 0; i < alen; i++) {
7965                                         guint32 val = read32 (p);
7966                                         mono_array_set (arr, guint32, i, val);
7967                                         p += 4;
7968                                 }
7969                                 break;
7970                         case MONO_TYPE_R8:
7971                                 for (i = 0; i < alen; i++) {
7972                                         double val;
7973                                         readr8 (p, &val);
7974                                         mono_array_set (arr, double, i, val);
7975                                         p += 8;
7976                                 }
7977                                 break;
7978                         case MONO_TYPE_U8:
7979                         case MONO_TYPE_I8:
7980                                 for (i = 0; i < alen; i++) {
7981                                         guint64 val = read64 (p);
7982                                         mono_array_set (arr, guint64, i, val);
7983                                         p += 8;
7984                                 }
7985                                 break;
7986                         case MONO_TYPE_CLASS:
7987                         case MONO_TYPE_OBJECT:
7988                         case MONO_TYPE_STRING:
7989                                 for (i = 0; i < alen; i++) {
7990                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7991                                         mono_array_setref (arr, i, item);
7992                                 }
7993                                 break;
7994                         default:
7995                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7996                 }
7997                 *end=p;
7998                 return arr;
7999         }
8000         default:
8001                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8002         }
8003         return NULL;
8004 }
8005
8006 static MonoObject*
8007 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8008 {
8009         static MonoClass *klass;
8010         static MonoMethod *ctor;
8011         MonoObject *retval;
8012         void *params [2], *unboxed;
8013
8014         if (!klass)
8015                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8016         if (!ctor)
8017                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8018         
8019         params [0] = mono_type_get_object (mono_domain_get (), t);
8020         params [1] = val;
8021         retval = mono_object_new (mono_domain_get (), klass);
8022         unboxed = mono_object_unbox (retval);
8023         mono_runtime_invoke (ctor, unboxed, params, NULL);
8024
8025         return retval;
8026 }
8027
8028 static MonoObject*
8029 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8030 {
8031         static MonoClass *klass;
8032         static MonoMethod *ctor;
8033         MonoObject *retval;
8034         void *unboxed, *params [2];
8035
8036         if (!klass)
8037                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8038         if (!ctor)
8039                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8040
8041         params [0] = minfo;
8042         params [1] = typedarg;
8043         retval = mono_object_new (mono_domain_get (), klass);
8044         unboxed = mono_object_unbox (retval);
8045         mono_runtime_invoke (ctor, unboxed, params, NULL);
8046
8047         return retval;
8048 }
8049
8050 static gboolean
8051 type_is_reference (MonoType *type)
8052 {
8053         switch (type->type) {
8054         case MONO_TYPE_BOOLEAN:
8055         case MONO_TYPE_CHAR:
8056         case MONO_TYPE_U:
8057         case MONO_TYPE_I:
8058         case MONO_TYPE_U1:
8059         case MONO_TYPE_I1:
8060         case MONO_TYPE_U2:
8061         case MONO_TYPE_I2:
8062         case MONO_TYPE_U4:
8063         case MONO_TYPE_I4:
8064         case MONO_TYPE_U8:
8065         case MONO_TYPE_I8:
8066         case MONO_TYPE_R8:
8067         case MONO_TYPE_R4:
8068         case MONO_TYPE_VALUETYPE:
8069                 return FALSE;
8070         default:
8071                 return TRUE;
8072         }
8073 }
8074
8075 static void
8076 free_param_data (MonoMethodSignature *sig, void **params) {
8077         int i;
8078         for (i = 0; i < sig->param_count; ++i) {
8079                 if (!type_is_reference (sig->params [i]))
8080                         g_free (params [i]);
8081         }
8082 }
8083
8084 /*
8085  * Find the field index in the metadata FieldDef table.
8086  */
8087 static guint32
8088 find_field_index (MonoClass *klass, MonoClassField *field) {
8089         int i;
8090
8091         for (i = 0; i < klass->field.count; ++i) {
8092                 if (field == &klass->fields [i])
8093                         return klass->field.first + 1 + i;
8094         }
8095         return 0;
8096 }
8097
8098 /*
8099  * Find the property index in the metadata Property table.
8100  */
8101 static guint32
8102 find_property_index (MonoClass *klass, MonoProperty *property) {
8103         int i;
8104
8105         for (i = 0; i < klass->ext->property.count; ++i) {
8106                 if (property == &klass->ext->properties [i])
8107                         return klass->ext->property.first + 1 + i;
8108         }
8109         return 0;
8110 }
8111
8112 /*
8113  * Find the event index in the metadata Event table.
8114  */
8115 static guint32
8116 find_event_index (MonoClass *klass, MonoEvent *event) {
8117         int i;
8118
8119         for (i = 0; i < klass->ext->event.count; ++i) {
8120                 if (event == &klass->ext->events [i])
8121                         return klass->ext->event.first + 1 + i;
8122         }
8123         return 0;
8124 }
8125
8126 static MonoObject*
8127 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8128 {
8129         const char *p = (const char*)data;
8130         const char *named;
8131         guint32 i, j, num_named;
8132         MonoObject *attr;
8133         void *params_buf [32];
8134         void **params;
8135         MonoMethodSignature *sig;
8136
8137         mono_class_init (method->klass);
8138
8139         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8140                 return NULL;
8141
8142         if (len == 0) {
8143                 attr = mono_object_new (mono_domain_get (), method->klass);
8144                 mono_runtime_invoke (method, attr, NULL, NULL);
8145                 return attr;
8146         }
8147
8148         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8149                 return NULL;
8150
8151         /*g_print ("got attr %s\n", method->klass->name);*/
8152
8153         sig = mono_method_signature (method);
8154         if (sig->param_count < 32)
8155                 params = params_buf;
8156         else
8157                 /* Allocate using GC so it gets GC tracking */
8158                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8159
8160         /* skip prolog */
8161         p += 2;
8162         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8163                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8164         }
8165
8166         named = p;
8167         attr = mono_object_new (mono_domain_get (), method->klass);
8168         mono_runtime_invoke (method, attr, params, NULL);
8169         free_param_data (method->signature, params);
8170         num_named = read16 (named);
8171         named += 2;
8172         for (j = 0; j < num_named; j++) {
8173                 gint name_len;
8174                 char *name, named_type, data_type;
8175                 named_type = *named++;
8176                 data_type = *named++; /* type of data */
8177                 if (data_type == MONO_TYPE_SZARRAY)
8178                         data_type = *named++;
8179                 if (data_type == MONO_TYPE_ENUM) {
8180                         gint type_len;
8181                         char *type_name;
8182                         type_len = mono_metadata_decode_blob_size (named, &named);
8183                         type_name = g_malloc (type_len + 1);
8184                         memcpy (type_name, named, type_len);
8185                         type_name [type_len] = 0;
8186                         named += type_len;
8187                         /* FIXME: lookup the type and check type consistency */
8188                         g_free (type_name);
8189                 }
8190                 name_len = mono_metadata_decode_blob_size (named, &named);
8191                 name = g_malloc (name_len + 1);
8192                 memcpy (name, named, name_len);
8193                 name [name_len] = 0;
8194                 named += name_len;
8195                 if (named_type == 0x53) {
8196                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8197                         void *val = load_cattr_value (image, field->type, named, &named);
8198                         mono_field_set_value (attr, field, val);
8199                         if (!type_is_reference (field->type))
8200                                 g_free (val);
8201                 } else if (named_type == 0x54) {
8202                         MonoProperty *prop;
8203                         void *pparams [1];
8204                         MonoType *prop_type;
8205
8206                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8207                         /* can we have more that 1 arg in a custom attr named property? */
8208                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8209                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8210                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8211                         mono_property_set_value (prop, attr, pparams, NULL);
8212                         if (!type_is_reference (prop_type))
8213                                 g_free (pparams [0]);
8214                 }
8215                 g_free (name);
8216         }
8217
8218         if (params != params_buf)
8219                 mono_gc_free_fixed (params);
8220
8221         return attr;
8222 }
8223         
8224 /*
8225  * mono_reflection_create_custom_attr_data_args:
8226  *
8227  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8228  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8229  * NAMED_ARG_INFO will contain information about the named arguments.
8230  */
8231 void
8232 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)
8233 {
8234         MonoArray *typedargs, *namedargs;
8235         MonoClass *attrklass;
8236         MonoDomain *domain;
8237         const char *p = (const char*)data;
8238         const char *named;
8239         guint32 i, j, num_named;
8240         CattrNamedArg *arginfo = NULL;
8241
8242         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8243                 return;
8244
8245         mono_class_init (method->klass);
8246
8247         *typed_args = NULL;
8248         *named_args = NULL;
8249         *named_arg_info = NULL;
8250         
8251         domain = mono_domain_get ();
8252
8253         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8254                 return;
8255
8256         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8257         
8258         /* skip prolog */
8259         p += 2;
8260         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8261                 MonoObject *obj;
8262                 void *val;
8263
8264                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8265                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8266                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8267                 mono_array_setref (typedargs, i, obj);
8268
8269                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8270                         g_free (val);
8271         }
8272
8273         named = p;
8274         num_named = read16 (named);
8275         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8276         named += 2;
8277         attrklass = method->klass;
8278
8279         arginfo = g_new0 (CattrNamedArg, num_named);
8280         *named_arg_info = arginfo;
8281
8282         for (j = 0; j < num_named; j++) {
8283                 gint name_len;
8284                 char *name, named_type, data_type;
8285                 named_type = *named++;
8286                 data_type = *named++; /* type of data */
8287                 if (data_type == MONO_TYPE_SZARRAY)
8288                         data_type = *named++;
8289                 if (data_type == MONO_TYPE_ENUM) {
8290                         gint type_len;
8291                         char *type_name;
8292                         type_len = mono_metadata_decode_blob_size (named, &named);
8293                         type_name = g_malloc (type_len + 1);
8294                         memcpy (type_name, named, type_len);
8295                         type_name [type_len] = 0;
8296                         named += type_len;
8297                         /* FIXME: lookup the type and check type consistency */
8298                         g_free (type_name);
8299                 }
8300                 name_len = mono_metadata_decode_blob_size (named, &named);
8301                 name = g_malloc (name_len + 1);
8302                 memcpy (name, named, name_len);
8303                 name [name_len] = 0;
8304                 named += name_len;
8305                 if (named_type == 0x53) {
8306                         MonoObject *obj;
8307                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8308                         void *val;
8309
8310                         arginfo [j].type = field->type;
8311                         arginfo [j].field = field;
8312
8313                         val = load_cattr_value (image, field->type, named, &named);
8314                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8315                         mono_array_setref (namedargs, j, obj);
8316                         if (!type_is_reference (field->type))
8317                                 g_free (val);
8318                 } else if (named_type == 0x54) {
8319                         MonoObject *obj;
8320                         MonoType *prop_type;
8321                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8322                         void *val;
8323
8324                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8325                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8326
8327                         arginfo [j].type = prop_type;
8328                         arginfo [j].prop = prop;
8329
8330                         val = load_cattr_value (image, prop_type, named, &named);
8331                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8332                         mono_array_setref (namedargs, j, obj);
8333                         if (!type_is_reference (prop_type))
8334                                 g_free (val);
8335                 }
8336                 g_free (name);
8337         }
8338
8339         *typed_args = typedargs;
8340         *named_args = namedargs;
8341 }
8342
8343 static MonoObject*
8344 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8345 {
8346         MonoArray *typedargs, *namedargs;
8347         static MonoMethod *ctor;
8348         MonoDomain *domain;
8349         MonoObject *attr;
8350         void *params [3];
8351         CattrNamedArg *arginfo;
8352         int i;
8353
8354         mono_class_init (method->klass);
8355
8356         if (!ctor)
8357                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8358
8359         domain = mono_domain_get ();
8360         if (len == 0) {
8361                 /* This is for Attributes with no parameters */
8362                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8363                 params [0] = mono_method_get_object (domain, method, NULL);
8364                 params [1] = params [2] = NULL;
8365                 mono_runtime_invoke (method, attr, params, NULL);
8366                 return attr;
8367         }
8368
8369         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8370         if (!typedargs || !namedargs)
8371                 return NULL;
8372
8373         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8374                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8375                 MonoObject *typedarg;
8376
8377                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8378                 mono_array_setref (typedargs, i, typedarg);
8379         }
8380
8381         for (i = 0; i < mono_array_length (namedargs); ++i) {
8382                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8383                 MonoObject *typedarg, *namedarg, *minfo;
8384
8385                 if (arginfo [i].prop)
8386                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8387                 else
8388                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8389
8390                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8391                 namedarg = create_cattr_named_arg (minfo, typedarg);
8392
8393                 mono_array_setref (namedargs, i, namedarg);
8394         }
8395
8396         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8397         params [0] = mono_method_get_object (domain, method, NULL);
8398         params [1] = typedargs;
8399         params [2] = namedargs;
8400         mono_runtime_invoke (ctor, attr, params, NULL);
8401         return attr;
8402 }
8403
8404 MonoArray*
8405 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8406 {
8407         MonoArray *result;
8408         MonoObject *attr;
8409         int i;
8410
8411         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8412         for (i = 0; i < cinfo->num_attrs; ++i) {
8413                 if (!cinfo->attrs [i].ctor)
8414                         /* The cattr type is not finished yet */
8415                         /* We should include the type name but cinfo doesn't contain it */
8416                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8417                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8418                 mono_array_setref (result, i, attr);
8419         }
8420         return result;
8421 }
8422
8423 static MonoArray*
8424 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8425 {
8426         MonoArray *result;
8427         MonoObject *attr;
8428         int i, n;
8429
8430         n = 0;
8431         for (i = 0; i < cinfo->num_attrs; ++i) {
8432                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8433                         n ++;
8434         }
8435
8436         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8437         n = 0;
8438         for (i = 0; i < cinfo->num_attrs; ++i) {
8439                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8440                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8441                         mono_array_setref (result, n, attr);
8442                         n ++;
8443                 }
8444         }
8445         return result;
8446 }
8447
8448 static MonoArray*
8449 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8450 {
8451         MonoArray *result;
8452         MonoObject *attr;
8453         int i;
8454         
8455         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8456         for (i = 0; i < cinfo->num_attrs; ++i) {
8457                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8458                 mono_array_setref (result, i, attr);
8459         }
8460         return result;
8461 }
8462
8463 /**
8464  * mono_custom_attrs_from_index:
8465  *
8466  * Returns: NULL if no attributes are found or if a loading error occurs.
8467  */
8468 MonoCustomAttrInfo*
8469 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8470 {
8471         guint32 mtoken, i, len;
8472         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8473         MonoTableInfo *ca;
8474         MonoCustomAttrInfo *ainfo;
8475         GList *tmp, *list = NULL;
8476         const char *data;
8477
8478         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8479
8480         i = mono_metadata_custom_attrs_from_index (image, idx);
8481         if (!i)
8482                 return NULL;
8483         i --;
8484         while (i < ca->rows) {
8485                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8486                         break;
8487                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8488                 ++i;
8489         }
8490         len = g_list_length (list);
8491         if (!len)
8492                 return NULL;
8493         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8494         ainfo->num_attrs = len;
8495         ainfo->image = image;
8496         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8497                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8498                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8499                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8500                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8501                         mtoken |= MONO_TOKEN_METHOD_DEF;
8502                         break;
8503                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8504                         mtoken |= MONO_TOKEN_MEMBER_REF;
8505                         break;
8506                 default:
8507                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8508                         break;
8509                 }
8510                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8511                 if (!ainfo->attrs [i].ctor) {
8512                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8513                         g_list_free (list);
8514                         g_free (ainfo);
8515                         return NULL;
8516                 }
8517
8518                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8519                         /*FIXME raising an exception here doesn't make any sense*/
8520                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8521                         g_list_free (list);
8522                         g_free (ainfo);
8523                         return NULL;
8524                 }
8525                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8526                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8527                 ainfo->attrs [i].data = (guchar*)data;
8528         }
8529         g_list_free (list);
8530
8531         return ainfo;
8532 }
8533
8534 MonoCustomAttrInfo*
8535 mono_custom_attrs_from_method (MonoMethod *method)
8536 {
8537         guint32 idx;
8538
8539         /*
8540          * An instantiated method has the same cattrs as the generic method definition.
8541          *
8542          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8543          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8544          */
8545         if (method->is_inflated)
8546                 method = ((MonoMethodInflated *) method)->declaring;
8547         
8548         if (method->dynamic || method->klass->image->dynamic)
8549                 return lookup_custom_attr (method->klass->image, method);
8550
8551         if (!method->token)
8552                 /* Synthetic methods */
8553                 return NULL;
8554
8555         idx = mono_method_get_index (method);
8556         idx <<= MONO_CUSTOM_ATTR_BITS;
8557         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8558         return mono_custom_attrs_from_index (method->klass->image, idx);
8559 }
8560
8561 MonoCustomAttrInfo*
8562 mono_custom_attrs_from_class (MonoClass *klass)
8563 {
8564         guint32 idx;
8565
8566         if (klass->generic_class)
8567                 klass = klass->generic_class->container_class;
8568
8569         if (klass->image->dynamic)
8570                 return lookup_custom_attr (klass->image, klass);
8571
8572         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8573                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8574                 idx <<= MONO_CUSTOM_ATTR_BITS;
8575                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8576         } else {
8577                 idx = mono_metadata_token_index (klass->type_token);
8578                 idx <<= MONO_CUSTOM_ATTR_BITS;
8579                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8580         }
8581         return mono_custom_attrs_from_index (klass->image, idx);
8582 }
8583
8584 MonoCustomAttrInfo*
8585 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8586 {
8587         guint32 idx;
8588         
8589         if (assembly->image->dynamic)
8590                 return lookup_custom_attr (assembly->image, assembly);
8591         idx = 1; /* there is only one assembly */
8592         idx <<= MONO_CUSTOM_ATTR_BITS;
8593         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8594         return mono_custom_attrs_from_index (assembly->image, idx);
8595 }
8596
8597 static MonoCustomAttrInfo*
8598 mono_custom_attrs_from_module (MonoImage *image)
8599 {
8600         guint32 idx;
8601         
8602         if (image->dynamic)
8603                 return lookup_custom_attr (image, image);
8604         idx = 1; /* there is only one module */
8605         idx <<= MONO_CUSTOM_ATTR_BITS;
8606         idx |= MONO_CUSTOM_ATTR_MODULE;
8607         return mono_custom_attrs_from_index (image, idx);
8608 }
8609
8610 MonoCustomAttrInfo*
8611 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8612 {
8613         guint32 idx;
8614         
8615         if (klass->image->dynamic) {
8616                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8617                 return lookup_custom_attr (klass->image, property);
8618         }
8619         idx = find_property_index (klass, property);
8620         idx <<= MONO_CUSTOM_ATTR_BITS;
8621         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8622         return mono_custom_attrs_from_index (klass->image, idx);
8623 }
8624
8625 MonoCustomAttrInfo*
8626 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8627 {
8628         guint32 idx;
8629         
8630         if (klass->image->dynamic) {
8631                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8632                 return lookup_custom_attr (klass->image, event);
8633         }
8634         idx = find_event_index (klass, event);
8635         idx <<= MONO_CUSTOM_ATTR_BITS;
8636         idx |= MONO_CUSTOM_ATTR_EVENT;
8637         return mono_custom_attrs_from_index (klass->image, idx);
8638 }
8639
8640 MonoCustomAttrInfo*
8641 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8642 {
8643         guint32 idx;
8644         if (klass->image->dynamic) {
8645                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8646                 return lookup_custom_attr (klass->image, field);
8647         }
8648         idx = find_field_index (klass, field);
8649         idx <<= MONO_CUSTOM_ATTR_BITS;
8650         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8651         return mono_custom_attrs_from_index (klass->image, idx);
8652 }
8653
8654 MonoCustomAttrInfo*
8655 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8656 {
8657         MonoTableInfo *ca;
8658         guint32 i, idx, method_index;
8659         guint32 param_list, param_last, param_pos, found;
8660         MonoImage *image;
8661         MonoReflectionMethodAux *aux;
8662
8663         /*
8664          * An instantiated method has the same cattrs as the generic method definition.
8665          *
8666          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8667          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8668          */
8669         if (method->is_inflated)
8670                 method = ((MonoMethodInflated *) method)->declaring;
8671
8672         if (method->klass->image->dynamic) {
8673                 MonoCustomAttrInfo *res, *ainfo;
8674                 int size;
8675
8676                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8677                 if (!aux || !aux->param_cattr)
8678                         return NULL;
8679
8680                 /* Need to copy since it will be freed later */
8681                 ainfo = aux->param_cattr [param];
8682                 if (!ainfo)
8683                         return NULL;
8684                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8685                 res = g_malloc0 (size);
8686                 memcpy (res, ainfo, size);
8687                 return res;
8688         }
8689
8690         image = method->klass->image;
8691         method_index = mono_method_get_index (method);
8692         ca = &image->tables [MONO_TABLE_METHOD];
8693
8694         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8695         if (method_index == ca->rows) {
8696                 ca = &image->tables [MONO_TABLE_PARAM];
8697                 param_last = ca->rows + 1;
8698         } else {
8699                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8700                 ca = &image->tables [MONO_TABLE_PARAM];
8701         }
8702         found = FALSE;
8703         for (i = param_list; i < param_last; ++i) {
8704                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8705                 if (param_pos == param) {
8706                         found = TRUE;
8707                         break;
8708                 }
8709         }
8710         if (!found)
8711                 return NULL;
8712         idx = i;
8713         idx <<= MONO_CUSTOM_ATTR_BITS;
8714         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8715         return mono_custom_attrs_from_index (image, idx);
8716 }
8717
8718 gboolean
8719 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8720 {
8721         int i;
8722         MonoClass *klass;
8723         for (i = 0; i < ainfo->num_attrs; ++i) {
8724                 klass = ainfo->attrs [i].ctor->klass;
8725                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8726                         return TRUE;
8727         }
8728         return FALSE;
8729 }
8730
8731 MonoObject*
8732 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8733 {
8734         int i, attr_index;
8735         MonoClass *klass;
8736         MonoArray *attrs;
8737
8738         attr_index = -1;
8739         for (i = 0; i < ainfo->num_attrs; ++i) {
8740                 klass = ainfo->attrs [i].ctor->klass;
8741                 if (mono_class_has_parent (klass, attr_klass)) {
8742                         attr_index = i;
8743                         break;
8744                 }
8745         }
8746         if (attr_index == -1)
8747                 return NULL;
8748
8749         attrs = mono_custom_attrs_construct (ainfo);
8750         if (attrs)
8751                 return mono_array_get (attrs, MonoObject*, attr_index);
8752         else
8753                 return NULL;
8754 }
8755
8756 /*
8757  * mono_reflection_get_custom_attrs_info:
8758  * @obj: a reflection object handle
8759  *
8760  * Return the custom attribute info for attributes defined for the
8761  * reflection handle @obj. The objects.
8762  *
8763  * FIXME this function leaks like a sieve for SRE objects.
8764  */
8765 MonoCustomAttrInfo*
8766 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8767 {
8768         MonoClass *klass;
8769         MonoCustomAttrInfo *cinfo = NULL;
8770         
8771         klass = obj->vtable->klass;
8772         if (klass == mono_defaults.monotype_class) {
8773                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8774                 klass = mono_class_from_mono_type (type);
8775                 cinfo = mono_custom_attrs_from_class (klass);
8776         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8777                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8778                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8779         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8780                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8781                 cinfo = mono_custom_attrs_from_module (module->image);
8782         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8783                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8784                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8785         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8786                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8787                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8788         } else if (strcmp ("MonoField", klass->name) == 0) {
8789                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8790                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8791         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8792                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8793                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8794         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8795                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8796                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8797         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8798                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8799                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8800                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8801                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8802                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8803                 } else if (is_sr_mono_property (member_class)) {
8804                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8805                         MonoMethod *method;
8806                         if (!(method = prop->property->get))
8807                                 method = prop->property->set;
8808                         g_assert (method);
8809
8810                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8811                 } 
8812 #ifndef DISABLE_REFLECTION_EMIT
8813                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8814                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8815                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8816                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8817                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8818                         MonoMethod *method = NULL;
8819                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8820                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8821                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8822                                 method = ((MonoReflectionMethod *)c->cb)->method;
8823                         else
8824                                 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));
8825
8826                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8827                 } 
8828 #endif
8829                 else {
8830                         char *type_name = mono_type_get_full_name (member_class);
8831                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8832                         MonoException *ex = mono_get_exception_not_supported  (msg);
8833                         g_free (type_name);
8834                         g_free (msg);
8835                         mono_raise_exception (ex);
8836                 }
8837         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8838                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8839                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8840         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8841                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8842                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8843         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8844                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8845                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8846         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8847                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8848                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8849         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8850                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8851                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8852         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8853                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8854                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8855         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8856                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8857                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8858         } else { /* handle other types here... */
8859                 g_error ("get custom attrs not yet supported for %s", klass->name);
8860         }
8861
8862         return cinfo;
8863 }
8864
8865 /*
8866  * mono_reflection_get_custom_attrs_by_type:
8867  * @obj: a reflection object handle
8868  *
8869  * Return an array with all the custom attributes defined of the
8870  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8871  * of that type are returned. The objects are fully build. Return NULL if a loading error
8872  * occurs.
8873  */
8874 MonoArray*
8875 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8876 {
8877         MonoArray *result;
8878         MonoCustomAttrInfo *cinfo;
8879
8880         cinfo = mono_reflection_get_custom_attrs_info (obj);
8881         if (cinfo) {
8882                 if (attr_klass)
8883                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8884                 else
8885                         result = mono_custom_attrs_construct (cinfo);
8886                 if (!cinfo->cached)
8887                         mono_custom_attrs_free (cinfo);
8888         } else {
8889                 if (mono_loader_get_last_error ())
8890                         return NULL;
8891                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8892         }
8893
8894         return result;
8895 }
8896
8897 /*
8898  * mono_reflection_get_custom_attrs:
8899  * @obj: a reflection object handle
8900  *
8901  * Return an array with all the custom attributes defined of the
8902  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8903  * occurs.
8904  */
8905 MonoArray*
8906 mono_reflection_get_custom_attrs (MonoObject *obj)
8907 {
8908         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8909 }
8910
8911 /*
8912  * mono_reflection_get_custom_attrs_data:
8913  * @obj: a reflection obj handle
8914  *
8915  * Returns an array of System.Reflection.CustomAttributeData,
8916  * which include information about attributes reflected on
8917  * types loaded using the Reflection Only methods
8918  */
8919 MonoArray*
8920 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8921 {
8922         MonoArray *result;
8923         MonoCustomAttrInfo *cinfo;
8924
8925         cinfo = mono_reflection_get_custom_attrs_info (obj);
8926         if (cinfo) {
8927                 result = mono_custom_attrs_data_construct (cinfo);
8928                 if (!cinfo->cached)
8929                         mono_custom_attrs_free (cinfo);
8930         } else
8931                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8932
8933         return result;
8934 }
8935
8936 static MonoReflectionType*
8937 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8938 {
8939         static MonoMethod *method_get_underlying_system_type = NULL;
8940         MonoMethod *usertype_method;
8941
8942         if (!method_get_underlying_system_type)
8943                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8944         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8945         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8946 }
8947
8948
8949 static gboolean
8950 is_corlib_type (MonoClass *class)
8951 {
8952         return class->image == mono_defaults.corlib;
8953 }
8954
8955 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8956         static MonoClass *cached_class; \
8957         if (cached_class) \
8958                 return cached_class == _class; \
8959         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8960                 cached_class = _class; \
8961                 return TRUE; \
8962         } \
8963         return FALSE; \
8964 } while (0) \
8965
8966
8967 #ifndef DISABLE_REFLECTION_EMIT
8968 static gboolean
8969 is_sre_array (MonoClass *class)
8970 {
8971         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8972 }
8973
8974 static gboolean
8975 is_sre_byref (MonoClass *class)
8976 {
8977         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8978 }
8979
8980 static gboolean
8981 is_sre_pointer (MonoClass *class)
8982 {
8983         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8984 }
8985
8986 static gboolean
8987 is_sre_generic_instance (MonoClass *class)
8988 {
8989         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8990 }
8991
8992 static gboolean
8993 is_sre_type_builder (MonoClass *class)
8994 {
8995         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8996 }
8997
8998 static gboolean
8999 is_sre_method_builder (MonoClass *class)
9000 {
9001         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9002 }
9003
9004 static gboolean
9005 is_sre_ctor_builder (MonoClass *class)
9006 {
9007         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9008 }
9009
9010 static gboolean
9011 is_sre_field_builder (MonoClass *class)
9012 {
9013         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9014 }
9015
9016 static gboolean
9017 is_sre_method_on_tb_inst (MonoClass *class)
9018 {
9019         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9020 }
9021
9022 static gboolean
9023 is_sre_ctor_on_tb_inst (MonoClass *class)
9024 {
9025         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9026 }
9027
9028 MonoType*
9029 mono_reflection_type_get_handle (MonoReflectionType* ref)
9030 {
9031         MonoClass *class;
9032         if (!ref)
9033                 return NULL;
9034         if (ref->type)
9035                 return ref->type;
9036
9037         if (is_usertype (ref)) {
9038                 ref = mono_reflection_type_get_underlying_system_type (ref);
9039                 if (ref == NULL || is_usertype (ref))
9040                         return NULL;
9041                 if (ref->type)
9042                         return ref->type;
9043         }
9044
9045         class = mono_object_class (ref);
9046
9047         if (is_sre_array (class)) {
9048                 MonoType *res;
9049                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9050                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9051                 g_assert (base);
9052                 if (sre_array->rank == 0) //single dimentional array
9053                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9054                 else
9055                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9056                 sre_array->type.type = res;
9057                 return res;
9058         } else if (is_sre_byref (class)) {
9059                 MonoType *res;
9060                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9061                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9062                 g_assert (base);
9063                 res = &mono_class_from_mono_type (base)->this_arg;
9064                 sre_byref->type.type = res;
9065                 return res;
9066         } else if (is_sre_pointer (class)) {
9067                 MonoType *res;
9068                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9069                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9070                 g_assert (base);
9071                 res = &mono_ptr_class_get (base)->byval_arg;
9072                 sre_pointer->type.type = res;
9073                 return res;
9074         } else if (is_sre_generic_instance (class)) {
9075                 MonoType *res, **types;
9076                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9077                 int i, count;
9078
9079                 count = mono_array_length (gclass->type_arguments);
9080                 types = g_new0 (MonoType*, count);
9081                 for (i = 0; i < count; ++i) {
9082                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9083                         types [i] = mono_reflection_type_get_handle (t);
9084                         if (!types[i]) {
9085                                 g_free (types);
9086                                 return NULL;
9087                         }
9088                 }
9089
9090                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9091                 g_free (types);
9092                 g_assert (res);
9093                 gclass->type.type = res;
9094                 return res;
9095         }
9096
9097         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9098         return NULL;
9099 }
9100
9101
9102
9103 void
9104 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9105 {
9106         mono_reflection_type_get_handle (type);
9107 }
9108
9109 void
9110 mono_reflection_register_with_runtime (MonoReflectionType *type)
9111 {
9112         MonoType *res = mono_reflection_type_get_handle (type);
9113         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9114         MonoClass *class;
9115
9116         if (!res)
9117                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9118
9119         class = mono_class_from_mono_type (res);
9120
9121         mono_loader_lock (); /*same locking as mono_type_get_object*/
9122         mono_domain_lock (domain);
9123
9124         if (!class->image->dynamic) {
9125                 mono_class_setup_supertypes (class);
9126         } else {
9127                 if (!domain->type_hash)
9128                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
9129                                         (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9130                 mono_g_hash_table_insert (domain->type_hash, res, type);
9131         }
9132         mono_domain_unlock (domain);
9133         mono_loader_unlock ();
9134 }
9135
9136 /**
9137  * LOCKING: Assumes the loader lock is held.
9138  */
9139 static MonoMethodSignature*
9140 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9141         MonoMethodSignature *sig;
9142         int count, i;
9143
9144         count = parameters? mono_array_length (parameters): 0;
9145
9146         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9147         sig->param_count = count;
9148         sig->sentinelpos = -1; /* FIXME */
9149         for (i = 0; i < count; ++i)
9150                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9151         return sig;
9152 }
9153
9154 /**
9155  * LOCKING: Assumes the loader lock is held.
9156  */
9157 static MonoMethodSignature*
9158 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9159         MonoMethodSignature *sig;
9160
9161         sig = parameters_to_signature (image, ctor->parameters);
9162         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9163         sig->ret = &mono_defaults.void_class->byval_arg;
9164         return sig;
9165 }
9166
9167 /**
9168  * LOCKING: Assumes the loader lock is held.
9169  */
9170 static MonoMethodSignature*
9171 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9172         MonoMethodSignature *sig;
9173
9174         sig = parameters_to_signature (image, method->parameters);
9175         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9176         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9177         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9178         return sig;
9179 }
9180
9181 static MonoMethodSignature*
9182 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9183         MonoMethodSignature *sig;
9184
9185         sig = parameters_to_signature (NULL, method->parameters);
9186         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9187         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9188         sig->generic_param_count = 0;
9189         return sig;
9190 }
9191
9192 static void
9193 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9194 {
9195         MonoClass *klass = mono_object_class (prop);
9196         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9197                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9198                 *name = mono_string_to_utf8 (pb->name);
9199                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9200         } else {
9201                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9202                 *name = g_strdup (p->property->name);
9203                 if (p->property->get)
9204                         *type = mono_method_signature (p->property->get)->ret;
9205                 else
9206                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9207         }
9208 }
9209
9210 static void
9211 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9212 {
9213         MonoClass *klass = mono_object_class (field);
9214         if (strcmp (klass->name, "FieldBuilder") == 0) {
9215                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9216                 *name = mono_string_to_utf8 (fb->name);
9217                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9218         } else {
9219                 MonoReflectionField *f = (MonoReflectionField *)field;
9220                 *name = g_strdup (mono_field_get_name (f->field));
9221                 *type = f->field->type;
9222         }
9223 }
9224
9225 #else /* DISABLE_REFLECTION_EMIT */
9226
9227 void
9228 mono_reflection_register_with_runtime (MonoReflectionType *type)
9229 {
9230         /* This is empty */
9231 }
9232
9233 static gboolean
9234 is_sre_type_builder (MonoClass *class)
9235 {
9236         return FALSE;
9237 }
9238
9239 static gboolean
9240 is_sre_generic_instance (MonoClass *class)
9241 {
9242         return FALSE;
9243 }
9244
9245 #endif /* !DISABLE_REFLECTION_EMIT */
9246
9247
9248 static gboolean
9249 is_sr_mono_field (MonoClass *class)
9250 {
9251         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9252 }
9253
9254 static gboolean
9255 is_sr_mono_property (MonoClass *class)
9256 {
9257         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9258 }
9259
9260 static gboolean
9261 is_sr_mono_method (MonoClass *class)
9262 {
9263         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9264 }
9265
9266 static gboolean
9267 is_sr_mono_cmethod (MonoClass *class)
9268 {
9269         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9270 }
9271
9272 static gboolean
9273 is_sr_mono_generic_method (MonoClass *class)
9274 {
9275         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9276 }
9277
9278 static gboolean
9279 is_sr_mono_generic_cmethod (MonoClass *class)
9280 {
9281         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9282 }
9283
9284 gboolean
9285 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9286 {
9287         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9288 }
9289
9290 static gboolean
9291 is_usertype (MonoReflectionType *ref)
9292 {
9293         MonoClass *class = mono_object_class (ref);
9294         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9295 }
9296
9297 static MonoReflectionType*
9298 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9299 {
9300         if (!type || type->type)
9301                 return type;
9302
9303         if (is_usertype (type)) {
9304                 type = mono_reflection_type_get_underlying_system_type (type);
9305                 if (is_usertype (type))
9306                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9307         }
9308
9309         return type;
9310 }
9311 /*
9312  * Encode a value in a custom attribute stream of bytes.
9313  * The value to encode is either supplied as an object in argument val
9314  * (valuetypes are boxed), or as a pointer to the data in the
9315  * argument argval.
9316  * @type represents the type of the value
9317  * @buffer is the start of the buffer
9318  * @p the current position in the buffer
9319  * @buflen contains the size of the buffer and is used to return the new buffer size
9320  * if this needs to be realloced.
9321  * @retbuffer and @retp return the start and the position of the buffer
9322  */
9323 static void
9324 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9325 {
9326         MonoTypeEnum simple_type;
9327         
9328         if ((p-buffer) + 10 >= *buflen) {
9329                 char *newbuf;
9330                 *buflen *= 2;
9331                 newbuf = g_realloc (buffer, *buflen);
9332                 p = newbuf + (p-buffer);
9333                 buffer = newbuf;
9334         }
9335         if (!argval)
9336                 argval = ((char*)arg + sizeof (MonoObject));
9337         simple_type = type->type;
9338 handle_enum:
9339         switch (simple_type) {
9340         case MONO_TYPE_BOOLEAN:
9341         case MONO_TYPE_U1:
9342         case MONO_TYPE_I1:
9343                 *p++ = *argval;
9344                 break;
9345         case MONO_TYPE_CHAR:
9346         case MONO_TYPE_U2:
9347         case MONO_TYPE_I2:
9348                 swap_with_size (p, argval, 2, 1);
9349                 p += 2;
9350                 break;
9351         case MONO_TYPE_U4:
9352         case MONO_TYPE_I4:
9353         case MONO_TYPE_R4:
9354                 swap_with_size (p, argval, 4, 1);
9355                 p += 4;
9356                 break;
9357         case MONO_TYPE_R8:
9358 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9359                 p [0] = argval [4];
9360                 p [1] = argval [5];
9361                 p [2] = argval [6];
9362                 p [3] = argval [7];
9363                 p [4] = argval [0];
9364                 p [5] = argval [1];
9365                 p [6] = argval [2];
9366                 p [7] = argval [3];
9367 #else
9368                 swap_with_size (p, argval, 8, 1);
9369 #endif
9370                 p += 8;
9371                 break;
9372         case MONO_TYPE_U8:
9373         case MONO_TYPE_I8:
9374                 swap_with_size (p, argval, 8, 1);
9375                 p += 8;
9376                 break;
9377         case MONO_TYPE_VALUETYPE:
9378                 if (type->data.klass->enumtype) {
9379                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9380                         goto handle_enum;
9381                 } else {
9382                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9383                 }
9384                 break;
9385         case MONO_TYPE_STRING: {
9386                 char *str;
9387                 guint32 slen;
9388                 if (!arg) {
9389                         *p++ = 0xFF;
9390                         break;
9391                 }
9392                 str = mono_string_to_utf8 ((MonoString*)arg);
9393                 slen = strlen (str);
9394                 if ((p-buffer) + 10 + slen >= *buflen) {
9395                         char *newbuf;
9396                         *buflen *= 2;
9397                         *buflen += slen;
9398                         newbuf = g_realloc (buffer, *buflen);
9399                         p = newbuf + (p-buffer);
9400                         buffer = newbuf;
9401                 }
9402                 mono_metadata_encode_value (slen, p, &p);
9403                 memcpy (p, str, slen);
9404                 p += slen;
9405                 g_free (str);
9406                 break;
9407         }
9408         case MONO_TYPE_CLASS: {
9409                 char *str;
9410                 guint32 slen;
9411                 if (!arg) {
9412                         *p++ = 0xFF;
9413                         break;
9414                 }
9415 handle_type:
9416                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9417                 slen = strlen (str);
9418                 if ((p-buffer) + 10 + slen >= *buflen) {
9419                         char *newbuf;
9420                         *buflen *= 2;
9421                         *buflen += slen;
9422                         newbuf = g_realloc (buffer, *buflen);
9423                         p = newbuf + (p-buffer);
9424                         buffer = newbuf;
9425                 }
9426                 mono_metadata_encode_value (slen, p, &p);
9427                 memcpy (p, str, slen);
9428                 p += slen;
9429                 g_free (str);
9430                 break;
9431         }
9432         case MONO_TYPE_SZARRAY: {
9433                 int len, i;
9434                 MonoClass *eclass, *arg_eclass;
9435
9436                 if (!arg) {
9437                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9438                         break;
9439                 }
9440                 len = mono_array_length ((MonoArray*)arg);
9441                 *p++ = len & 0xff;
9442                 *p++ = (len >> 8) & 0xff;
9443                 *p++ = (len >> 16) & 0xff;
9444                 *p++ = (len >> 24) & 0xff;
9445                 *retp = p;
9446                 *retbuffer = buffer;
9447                 eclass = type->data.klass;
9448                 arg_eclass = mono_object_class (arg)->element_class;
9449
9450                 if (!eclass) {
9451                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9452                         eclass = mono_defaults.object_class;
9453                 }
9454                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9455                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9456                         int elsize = mono_class_array_element_size (arg_eclass);
9457                         for (i = 0; i < len; ++i) {
9458                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9459                                 elptr += elsize;
9460                         }
9461                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9462                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9463                         int elsize = mono_class_array_element_size (eclass);
9464                         for (i = 0; i < len; ++i) {
9465                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9466                                 elptr += elsize;
9467                         }
9468                 } else {
9469                         for (i = 0; i < len; ++i) {
9470                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9471                         }
9472                 }
9473                 break;
9474         }
9475         case MONO_TYPE_OBJECT: {
9476                 MonoClass *klass;
9477                 char *str;
9478                 guint32 slen;
9479
9480                 /*
9481                  * The parameter type is 'object' but the type of the actual
9482                  * argument is not. So we have to add type information to the blob
9483                  * too. This is completely undocumented in the spec.
9484                  */
9485
9486                 if (arg == NULL) {
9487                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9488                         *p++ = 0xFF;
9489                         break;
9490                 }
9491                 
9492                 klass = mono_object_class (arg);
9493
9494                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9495                         *p++ = 0x50;
9496                         goto handle_type;
9497                 } else if (klass->enumtype) {
9498                         *p++ = 0x55;
9499                 } else if (klass == mono_defaults.string_class) {
9500                         simple_type = MONO_TYPE_STRING;
9501                         *p++ = 0x0E;
9502                         goto handle_enum;
9503                 } else if (klass->rank == 1) {
9504                         *p++ = 0x1D;
9505                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9506                                 /* See Partition II, Appendix B3 */
9507                                 *p++ = 0x51;
9508                         else
9509                                 *p++ = klass->element_class->byval_arg.type;
9510                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9511                         break;
9512                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9513                         *p++ = simple_type = klass->byval_arg.type;
9514                         goto handle_enum;
9515                 } else {
9516                         g_error ("unhandled type in custom attr");
9517                 }
9518                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9519                 slen = strlen (str);
9520                 if ((p-buffer) + 10 + slen >= *buflen) {
9521                         char *newbuf;
9522                         *buflen *= 2;
9523                         *buflen += slen;
9524                         newbuf = g_realloc (buffer, *buflen);
9525                         p = newbuf + (p-buffer);
9526                         buffer = newbuf;
9527                 }
9528                 mono_metadata_encode_value (slen, p, &p);
9529                 memcpy (p, str, slen);
9530                 p += slen;
9531                 g_free (str);
9532                 simple_type = mono_class_enum_basetype (klass)->type;
9533                 goto handle_enum;
9534         }
9535         default:
9536                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9537         }
9538         *retp = p;
9539         *retbuffer = buffer;
9540 }
9541
9542 static void
9543 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9544 {
9545         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9546                 char *str = type_get_qualified_name (type, NULL);
9547                 int slen = strlen (str);
9548
9549                 *p++ = 0x55;
9550                 /*
9551                  * This seems to be optional...
9552                  * *p++ = 0x80;
9553                  */
9554                 mono_metadata_encode_value (slen, p, &p);
9555                 memcpy (p, str, slen);
9556                 p += slen;
9557                 g_free (str);
9558         } else if (type->type == MONO_TYPE_OBJECT) {
9559                 *p++ = 0x51;
9560         } else if (type->type == MONO_TYPE_CLASS) {
9561                 /* it should be a type: encode_cattr_value () has the check */
9562                 *p++ = 0x50;
9563         } else {
9564                 mono_metadata_encode_value (type->type, p, &p);
9565                 if (type->type == MONO_TYPE_SZARRAY)
9566                         /* See the examples in Partition VI, Annex B */
9567                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9568         }
9569
9570         *retp = p;
9571 }
9572
9573 #ifndef DISABLE_REFLECTION_EMIT
9574 static void
9575 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9576 {
9577         int len;
9578         /* Preallocate a large enough buffer */
9579         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9580                 char *str = type_get_qualified_name (type, NULL);
9581                 len = strlen (str);
9582                 g_free (str);
9583         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9584                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9585                 len = strlen (str);
9586                 g_free (str);
9587         } else {
9588                 len = 0;
9589         }
9590         len += strlen (name);
9591
9592         if ((p-buffer) + 20 + len >= *buflen) {
9593                 char *newbuf;
9594                 *buflen *= 2;
9595                 *buflen += len;
9596                 newbuf = g_realloc (buffer, *buflen);
9597                 p = newbuf + (p-buffer);
9598                 buffer = newbuf;
9599         }
9600
9601         encode_field_or_prop_type (type, p, &p);
9602
9603         len = strlen (name);
9604         mono_metadata_encode_value (len, p, &p);
9605         memcpy (p, name, len);
9606         p += len;
9607         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9608         *retp = p;
9609         *retbuffer = buffer;
9610 }
9611
9612 /*
9613  * mono_reflection_get_custom_attrs_blob:
9614  * @ctor: custom attribute constructor
9615  * @ctorArgs: arguments o the constructor
9616  * @properties:
9617  * @propValues:
9618  * @fields:
9619  * @fieldValues:
9620  * 
9621  * Creates the blob of data that needs to be saved in the metadata and that represents
9622  * the custom attributed described by @ctor, @ctorArgs etc.
9623  * Returns: a Byte array representing the blob of data.
9624  */
9625 MonoArray*
9626 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9627 {
9628         MonoArray *result;
9629         MonoMethodSignature *sig;
9630         MonoObject *arg;
9631         char *buffer, *p;
9632         guint32 buflen, i;
9633
9634         MONO_ARCH_SAVE_REGS;
9635
9636         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9637                 /* sig is freed later so allocate it in the heap */
9638                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9639         } else {
9640                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9641         }
9642
9643         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9644         buflen = 256;
9645         p = buffer = g_malloc (buflen);
9646         /* write the prolog */
9647         *p++ = 1;
9648         *p++ = 0;
9649         for (i = 0; i < sig->param_count; ++i) {
9650                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9651                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9652         }
9653         i = 0;
9654         if (properties)
9655                 i += mono_array_length (properties);
9656         if (fields)
9657                 i += mono_array_length (fields);
9658         *p++ = i & 0xff;
9659         *p++ = (i >> 8) & 0xff;
9660         if (properties) {
9661                 MonoObject *prop;
9662                 for (i = 0; i < mono_array_length (properties); ++i) {
9663                         MonoType *ptype;
9664                         char *pname;
9665
9666                         prop = mono_array_get (properties, gpointer, i);
9667                         get_prop_name_and_type (prop, &pname, &ptype);
9668                         *p++ = 0x54; /* PROPERTY signature */
9669                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9670                         g_free (pname);
9671                 }
9672         }
9673
9674         if (fields) {
9675                 MonoObject *field;
9676                 for (i = 0; i < mono_array_length (fields); ++i) {
9677                         MonoType *ftype;
9678                         char *fname;
9679
9680                         field = mono_array_get (fields, gpointer, i);
9681                         get_field_name_and_type (field, &fname, &ftype);
9682                         *p++ = 0x53; /* FIELD signature */
9683                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9684                         g_free (fname);
9685                 }
9686         }
9687
9688         g_assert (p - buffer <= buflen);
9689         buflen = p - buffer;
9690         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9691         p = mono_array_addr (result, char, 0);
9692         memcpy (p, buffer, buflen);
9693         g_free (buffer);
9694         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9695                 g_free (sig);
9696         return result;
9697 }
9698
9699 /*
9700  * mono_reflection_setup_internal_class:
9701  * @tb: a TypeBuilder object
9702  *
9703  * Creates a MonoClass that represents the TypeBuilder.
9704  * This is a trick that lets us simplify a lot of reflection code
9705  * (and will allow us to support Build and Run assemblies easier).
9706  */
9707 void
9708 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9709 {
9710         MonoError error;
9711         MonoClass *klass, *parent;
9712
9713         MONO_ARCH_SAVE_REGS;
9714
9715         RESOLVE_TYPE (tb->parent);
9716
9717         mono_loader_lock ();
9718
9719         if (tb->parent) {
9720                 /* check so we can compile corlib correctly */
9721                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9722                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9723                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9724                 } else {
9725                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9726                 }
9727         } else {
9728                 parent = NULL;
9729         }
9730         
9731         /* the type has already being created: it means we just have to change the parent */
9732         if (tb->type.type) {
9733                 klass = mono_class_from_mono_type (tb->type.type);
9734                 klass->parent = NULL;
9735                 /* fool mono_class_setup_parent */
9736                 klass->supertypes = NULL;
9737                 mono_class_setup_parent (klass, parent);
9738                 mono_class_setup_mono_type (klass);
9739                 mono_loader_unlock ();
9740                 return;
9741         }
9742
9743         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9744
9745         klass->image = &tb->module->dynamic_image->image;
9746
9747         klass->inited = 1; /* we lie to the runtime */
9748         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9749         if (!mono_error_ok (&error))
9750                 goto failure;
9751         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9752         if (!mono_error_ok (&error))
9753                 goto failure;
9754         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9755         klass->flags = tb->attrs;
9756         
9757         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9758
9759         klass->element_class = klass;
9760
9761         if (mono_class_get_ref_info (klass) == NULL) {
9762
9763                 mono_class_set_ref_info (klass, tb);
9764
9765                 /* Put into cache so mono_class_get () will find it.
9766                 Skip nested types as those should not be available on the global scope. */
9767                 if (!tb->nesting_type) {
9768                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9769                 } else {
9770                         klass->image->reflection_info_unregister_classes =
9771                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9772                 }
9773         } else {
9774                 g_assert (mono_class_get_ref_info (klass) == tb);
9775         }
9776
9777         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9778                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9779
9780         if (parent != NULL) {
9781                 mono_class_setup_parent (klass, parent);
9782         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9783                 const char *old_n = klass->name;
9784                 /* trick to get relative numbering right when compiling corlib */
9785                 klass->name = "BuildingObject";
9786                 mono_class_setup_parent (klass, mono_defaults.object_class);
9787                 klass->name = old_n;
9788         }
9789
9790         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9791                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9792                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9793                 klass->instance_size = sizeof (MonoObject);
9794                 klass->size_inited = 1;
9795                 mono_class_setup_vtable_general (klass, NULL, 0);
9796         }
9797
9798         mono_class_setup_mono_type (klass);
9799
9800         mono_class_setup_supertypes (klass);
9801
9802         /*
9803          * FIXME: handle interfaces.
9804          */
9805
9806         tb->type.type = &klass->byval_arg;
9807
9808         if (tb->nesting_type) {
9809                 g_assert (tb->nesting_type->type);
9810                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9811         }
9812
9813         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9814
9815         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9816         
9817         mono_loader_unlock ();
9818         return;
9819
9820 failure:
9821         mono_loader_unlock ();
9822         mono_error_raise_exception (&error);
9823 }
9824
9825 /*
9826  * mono_reflection_setup_generic_class:
9827  * @tb: a TypeBuilder object
9828  *
9829  * Setup the generic class before adding the first generic parameter.
9830  */
9831 void
9832 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9833 {
9834 }
9835
9836 /*
9837  * mono_reflection_create_generic_class:
9838  * @tb: a TypeBuilder object
9839  *
9840  * Creates the generic class after all generic parameters have been added.
9841  */
9842 void
9843 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9844 {
9845         MonoClass *klass;
9846         int count, i;
9847
9848         MONO_ARCH_SAVE_REGS;
9849
9850         klass = mono_class_from_mono_type (tb->type.type);
9851
9852         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9853
9854         if (klass->generic_container || (count == 0))
9855                 return;
9856
9857         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9858
9859         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9860
9861         klass->generic_container->owner.klass = klass;
9862         klass->generic_container->type_argc = count;
9863         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9864
9865         klass->is_generic = 1;
9866
9867         for (i = 0; i < count; i++) {
9868                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9869                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9870                 klass->generic_container->type_params [i] = *param;
9871                 /*Make sure we are a diferent type instance */
9872                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9873                 klass->generic_container->type_params [i].info.pklass = NULL;
9874                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9875
9876                 g_assert (klass->generic_container->type_params [i].param.owner);
9877         }
9878
9879         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9880 }
9881
9882 /*
9883  * mono_reflection_create_internal_class:
9884  * @tb: a TypeBuilder object
9885  *
9886  * Actually create the MonoClass that is associated with the TypeBuilder.
9887  */
9888 void
9889 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9890 {
9891         MonoClass *klass;
9892
9893         MONO_ARCH_SAVE_REGS;
9894
9895         klass = mono_class_from_mono_type (tb->type.type);
9896
9897         mono_loader_lock ();
9898         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9899                 MonoReflectionFieldBuilder *fb;
9900                 MonoClass *ec;
9901                 MonoType *enum_basetype;
9902
9903                 g_assert (tb->fields != NULL);
9904                 g_assert (mono_array_length (tb->fields) >= 1);
9905
9906                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9907
9908                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9909                         mono_loader_unlock ();
9910                         return;
9911                 }
9912
9913                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9914                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9915                 if (!klass->element_class)
9916                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9917
9918                 /*
9919                  * get the element_class from the current corlib.
9920                  */
9921                 ec = default_class_from_mono_type (enum_basetype);
9922                 klass->instance_size = ec->instance_size;
9923                 klass->size_inited = 1;
9924                 /* 
9925                  * this is almost safe to do with enums and it's needed to be able
9926                  * to create objects of the enum type (for use in SetConstant).
9927                  */
9928                 /* FIXME: Does this mean enums can't have method overrides ? */
9929                 mono_class_setup_vtable_general (klass, NULL, 0);
9930         }
9931         mono_loader_unlock ();
9932 }
9933
9934 static MonoMarshalSpec*
9935 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9936                                                                 MonoReflectionMarshal *minfo)
9937 {
9938         MonoMarshalSpec *res;
9939
9940         res = image_g_new0 (image, MonoMarshalSpec, 1);
9941         res->native = minfo->type;
9942
9943         switch (minfo->type) {
9944         case MONO_NATIVE_LPARRAY:
9945                 res->data.array_data.elem_type = minfo->eltype;
9946                 if (minfo->has_size) {
9947                         res->data.array_data.param_num = minfo->param_num;
9948                         res->data.array_data.num_elem = minfo->count;
9949                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9950                 }
9951                 else {
9952                         res->data.array_data.param_num = -1;
9953                         res->data.array_data.num_elem = -1;
9954                         res->data.array_data.elem_mult = -1;
9955                 }
9956                 break;
9957
9958         case MONO_NATIVE_BYVALTSTR:
9959         case MONO_NATIVE_BYVALARRAY:
9960                 res->data.array_data.num_elem = minfo->count;
9961                 break;
9962
9963         case MONO_NATIVE_CUSTOM:
9964                 if (minfo->marshaltyperef)
9965                         res->data.custom_data.custom_name =
9966                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9967                 if (minfo->mcookie)
9968                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9969                 break;
9970
9971         default:
9972                 break;
9973         }
9974
9975         return res;
9976 }
9977 #endif /* !DISABLE_REFLECTION_EMIT */
9978
9979 MonoReflectionMarshal*
9980 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9981                                                                                    MonoMarshalSpec *spec)
9982 {
9983         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9984         MonoReflectionMarshal *minfo;
9985         MonoType *mtype;
9986
9987         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9988                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9989                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9990                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9991         }
9992
9993         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9994         minfo->type = spec->native;
9995
9996         switch (minfo->type) {
9997         case MONO_NATIVE_LPARRAY:
9998                 minfo->eltype = spec->data.array_data.elem_type;
9999                 minfo->count = spec->data.array_data.num_elem;
10000                 minfo->param_num = spec->data.array_data.param_num;
10001                 break;
10002
10003         case MONO_NATIVE_BYVALTSTR:
10004         case MONO_NATIVE_BYVALARRAY:
10005                 minfo->count = spec->data.array_data.num_elem;
10006                 break;
10007
10008         case MONO_NATIVE_CUSTOM:
10009                 if (spec->data.custom_data.custom_name) {
10010                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10011                         if (mtype)
10012                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10013
10014                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10015                 }
10016                 if (spec->data.custom_data.cookie)
10017                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10018                 break;
10019
10020         default:
10021                 break;
10022         }
10023
10024         return minfo;
10025 }
10026
10027 #ifndef DISABLE_REFLECTION_EMIT
10028 static MonoMethod*
10029 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10030                                          ReflectionMethodBuilder *rmb,
10031                                          MonoMethodSignature *sig)
10032 {
10033         MonoError error;
10034         MonoMethod *m;
10035         MonoMethodWrapper *wrapperm;
10036         MonoMarshalSpec **specs;
10037         MonoReflectionMethodAux *method_aux;
10038         MonoImage *image;
10039         gboolean dynamic;
10040         int i;
10041
10042         mono_error_init (&error);
10043         /*
10044          * Methods created using a MethodBuilder should have their memory allocated
10045          * inside the image mempool, while dynamic methods should have their memory
10046          * malloc'd.
10047          */
10048         dynamic = rmb->refs != NULL;
10049         image = dynamic ? NULL : klass->image;
10050
10051         if (!dynamic)
10052                 g_assert (!klass->generic_class);
10053
10054         mono_loader_lock ();
10055
10056         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10057                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10058                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10059         else
10060                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10061
10062         wrapperm = (MonoMethodWrapper*)m;
10063
10064         m->dynamic = dynamic;
10065         m->slot = -1;
10066         m->flags = rmb->attrs;
10067         m->iflags = rmb->iattrs;
10068         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10069         g_assert (mono_error_ok (&error));
10070         m->klass = klass;
10071         m->signature = sig;
10072         m->sre_method = TRUE;
10073         m->skip_visibility = rmb->skip_visibility;
10074         if (rmb->table_idx)
10075                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10076
10077         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10078                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10079                         m->string_ctor = 1;
10080
10081                 m->signature->pinvoke = 1;
10082         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10083                 m->signature->pinvoke = 1;
10084
10085                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10086
10087                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10088                 g_assert (mono_error_ok (&error));
10089                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10090                 g_assert (mono_error_ok (&error));
10091                 
10092                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10093
10094                 if (klass->image->dynamic)
10095                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10096
10097                 mono_loader_unlock ();
10098
10099                 return m;
10100         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10101                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10102                 MonoMethodHeader *header;
10103                 guint32 code_size;
10104                 gint32 max_stack, i;
10105                 gint32 num_locals = 0;
10106                 gint32 num_clauses = 0;
10107                 guint8 *code;
10108
10109                 if (rmb->ilgen) {
10110                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10111                         code_size = rmb->ilgen->code_len;
10112                         max_stack = rmb->ilgen->max_stack;
10113                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10114                         if (rmb->ilgen->ex_handlers)
10115                                 num_clauses = method_count_clauses (rmb->ilgen);
10116                 } else {
10117                         if (rmb->code) {
10118                                 code = mono_array_addr (rmb->code, guint8, 0);
10119                                 code_size = mono_array_length (rmb->code);
10120                                 /* we probably need to run a verifier on the code... */
10121                                 max_stack = 8; 
10122                         }
10123                         else {
10124                                 code = NULL;
10125                                 code_size = 0;
10126                                 max_stack = 8;
10127                         }
10128                 }
10129
10130                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10131                 header->code_size = code_size;
10132                 header->code = image_g_malloc (image, code_size);
10133                 memcpy ((char*)header->code, code, code_size);
10134                 header->max_stack = max_stack;
10135                 header->init_locals = rmb->init_locals;
10136                 header->num_locals = num_locals;
10137
10138                 for (i = 0; i < num_locals; ++i) {
10139                         MonoReflectionLocalBuilder *lb = 
10140                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10141
10142                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10143                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10144                 }
10145
10146                 header->num_clauses = num_clauses;
10147                 if (num_clauses) {
10148                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10149                                  rmb->ilgen, num_clauses);
10150                 }
10151
10152                 wrapperm->header = header;
10153         }
10154
10155         if (rmb->generic_params) {
10156                 int count = mono_array_length (rmb->generic_params);
10157                 MonoGenericContainer *container = rmb->generic_container;
10158
10159                 g_assert (container);
10160
10161                 container->type_argc = count;
10162                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10163                 container->owner.method = m;
10164
10165                 m->is_generic = TRUE;
10166                 mono_method_set_generic_container (m, container);
10167
10168                 for (i = 0; i < count; i++) {
10169                         MonoReflectionGenericParam *gp =
10170                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10171                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10172                         container->type_params [i] = *param;
10173                 }
10174
10175                 if (klass->generic_container) {
10176                         container->parent = klass->generic_container;
10177                         container->context.class_inst = klass->generic_container->context.class_inst;
10178                 }
10179                 container->context.method_inst = mono_get_shared_generic_inst (container);
10180         }
10181
10182         if (rmb->refs) {
10183                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10184                 int i;
10185                 void **data;
10186
10187                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10188
10189                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10190                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10191                 for (i = 0; i < rmb->nrefs; ++i)
10192                         data [i + 1] = rmb->refs [i];
10193         }
10194
10195         method_aux = NULL;
10196
10197         /* Parameter info */
10198         if (rmb->pinfo) {
10199                 if (!method_aux)
10200                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10201                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10202                 for (i = 0; i <= m->signature->param_count; ++i) {
10203                         MonoReflectionParamBuilder *pb;
10204                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10205                                 if ((i > 0) && (pb->attrs)) {
10206                                         /* Make a copy since it might point to a shared type structure */
10207                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10208                                         m->signature->params [i - 1]->attrs = pb->attrs;
10209                                 }
10210
10211                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10212                                         MonoDynamicImage *assembly;
10213                                         guint32 idx, def_type, len;
10214                                         char *p;
10215                                         const char *p2;
10216
10217                                         if (!method_aux->param_defaults) {
10218                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10219                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10220                                         }
10221                                         assembly = (MonoDynamicImage*)klass->image;
10222                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10223                                         /* Copy the data from the blob since it might get realloc-ed */
10224                                         p = assembly->blob.data + idx;
10225                                         len = mono_metadata_decode_blob_size (p, &p2);
10226                                         len += p2 - p;
10227                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10228                                         method_aux->param_default_types [i] = def_type;
10229                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10230                                 }
10231
10232                                 if (pb->name) {
10233                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10234                                         g_assert (mono_error_ok (&error));
10235                                 }
10236                                 if (pb->cattrs) {
10237                                         if (!method_aux->param_cattr)
10238                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10239                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10240                                 }
10241                         }
10242                 }
10243         }
10244
10245         /* Parameter marshalling */
10246         specs = NULL;
10247         if (rmb->pinfo)         
10248                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10249                         MonoReflectionParamBuilder *pb;
10250                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10251                                 if (pb->marshal_info) {
10252                                         if (specs == NULL)
10253                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10254                                         specs [pb->position] = 
10255                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10256                                 }
10257                         }
10258                 }
10259         if (specs != NULL) {
10260                 if (!method_aux)
10261                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10262                 method_aux->param_marshall = specs;
10263         }
10264
10265         if (klass->image->dynamic && method_aux)
10266                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10267
10268         mono_loader_unlock ();
10269
10270         return m;
10271 }       
10272
10273 static MonoMethod*
10274 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10275 {
10276         ReflectionMethodBuilder rmb;
10277         MonoMethodSignature *sig;
10278
10279         mono_loader_lock ();
10280         sig = ctor_builder_to_signature (klass->image, mb);
10281         mono_loader_unlock ();
10282
10283         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10284
10285         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10286         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10287
10288         /* If we are in a generic class, we might be called multiple times from inflate_method */
10289         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10290                 /* ilgen is no longer needed */
10291                 mb->ilgen = NULL;
10292         }
10293
10294         return mb->mhandle;
10295 }
10296
10297 static MonoMethod*
10298 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10299 {
10300         ReflectionMethodBuilder rmb;
10301         MonoMethodSignature *sig;
10302
10303         mono_loader_lock ();
10304         sig = method_builder_to_signature (klass->image, mb);
10305         mono_loader_unlock ();
10306
10307         reflection_methodbuilder_from_method_builder (&rmb, mb);
10308
10309         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10310         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10311
10312         /* If we are in a generic class, we might be called multiple times from inflate_method */
10313         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10314                 /* ilgen is no longer needed */
10315                 mb->ilgen = NULL;
10316         }
10317         return mb->mhandle;
10318 }
10319
10320 static MonoClassField*
10321 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10322 {
10323         MonoClassField *field;
10324         MonoType *custom;
10325
10326         field = g_new0 (MonoClassField, 1);
10327
10328         field->name = mono_string_to_utf8 (fb->name);
10329         if (fb->attrs || fb->modreq || fb->modopt) {
10330                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10331                 field->type->attrs = fb->attrs;
10332
10333                 g_assert (klass->image->dynamic);
10334                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10335                 g_free (field->type);
10336                 field->type = custom;
10337         } else {
10338                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10339         }
10340         if (fb->offset != -1)
10341                 field->offset = fb->offset;
10342         field->parent = klass;
10343         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10344
10345         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10346
10347         return field;
10348 }
10349 #endif
10350
10351 MonoType*
10352 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10353 {
10354         MonoClass *klass;
10355         MonoReflectionTypeBuilder *tb = NULL;
10356         gboolean is_dynamic = FALSE;
10357         MonoDomain *domain;
10358         MonoClass *geninst;
10359
10360         mono_loader_lock ();
10361
10362         domain = mono_object_domain (type);
10363
10364         if (is_sre_type_builder (mono_object_class (type))) {
10365                 tb = (MonoReflectionTypeBuilder *) type;
10366
10367                 is_dynamic = TRUE;
10368         } else if (is_sre_generic_instance (mono_object_class (type))) {
10369                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10370                 MonoReflectionType *gtd = rgi->generic_type;
10371
10372                 if (is_sre_type_builder (mono_object_class (gtd))) {
10373                         tb = (MonoReflectionTypeBuilder *)gtd;
10374                         is_dynamic = TRUE;
10375                 }
10376         }
10377
10378         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10379         if (tb && tb->generic_container)
10380                 mono_reflection_create_generic_class (tb);
10381
10382         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10383         if (!klass->generic_container) {
10384                 mono_loader_unlock ();
10385                 return NULL;
10386         }
10387
10388         if (klass->wastypebuilder) {
10389                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10390
10391                 is_dynamic = TRUE;
10392         }
10393
10394         mono_loader_unlock ();
10395
10396         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10397
10398         return &geninst->byval_arg;
10399 }
10400
10401 MonoClass*
10402 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10403 {
10404         MonoGenericClass *gclass;
10405         MonoGenericInst *inst;
10406
10407         g_assert (klass->generic_container);
10408
10409         inst = mono_metadata_get_generic_inst (type_argc, types);
10410         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10411
10412         return mono_generic_class_get_class (gclass);
10413 }
10414
10415 MonoReflectionMethod*
10416 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10417 {
10418         MonoClass *klass;
10419         MonoMethod *method, *inflated;
10420         MonoMethodInflated *imethod;
10421         MonoGenericContext tmp_context;
10422         MonoGenericInst *ginst;
10423         MonoType **type_argv;
10424         int count, i;
10425
10426         MONO_ARCH_SAVE_REGS;
10427
10428         /*FIXME but this no longer should happen*/
10429         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10430 #ifndef DISABLE_REFLECTION_EMIT
10431                 MonoReflectionMethodBuilder *mb = NULL;
10432                 MonoReflectionTypeBuilder *tb;
10433                 MonoClass *klass;
10434
10435                 mb = (MonoReflectionMethodBuilder *) rmethod;
10436                 tb = (MonoReflectionTypeBuilder *) mb->type;
10437                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10438
10439                 method = methodbuilder_to_mono_method (klass, mb);
10440 #else
10441                 g_assert_not_reached ();
10442                 method = NULL;
10443 #endif
10444         } else {
10445                 method = rmethod->method;
10446         }
10447
10448         klass = method->klass;
10449
10450         if (method->is_inflated)
10451                 method = ((MonoMethodInflated *) method)->declaring;
10452
10453         count = mono_method_signature (method)->generic_param_count;
10454         if (count != mono_array_length (types))
10455                 return NULL;
10456
10457         type_argv = g_new0 (MonoType *, count);
10458         for (i = 0; i < count; i++) {
10459                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10460                 type_argv [i] = mono_reflection_type_get_handle (garg);
10461         }
10462         ginst = mono_metadata_get_generic_inst (count, type_argv);
10463         g_free (type_argv);
10464
10465         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10466         tmp_context.method_inst = ginst;
10467
10468         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10469         imethod = (MonoMethodInflated *) inflated;
10470
10471         /*FIXME but I think this is no longer necessary*/
10472         if (method->klass->image->dynamic) {
10473                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10474                 /*
10475                  * This table maps metadata structures representing inflated methods/fields
10476                  * to the reflection objects representing their generic definitions.
10477                  */
10478                 mono_loader_lock ();
10479                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10480                 mono_loader_unlock ();
10481         }
10482         
10483         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10484 }
10485
10486 #ifndef DISABLE_REFLECTION_EMIT
10487
10488 static MonoMethod *
10489 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10490 {
10491         MonoMethodInflated *imethod;
10492         MonoGenericContext *context;
10493         int i;
10494
10495         /*
10496          * With generic code sharing the klass might not be inflated.
10497          * This can happen because classes inflated with their own
10498          * type arguments are "normalized" to the uninflated class.
10499          */
10500         if (!klass->generic_class)
10501                 return method;
10502
10503         context = mono_class_get_context (klass);
10504
10505         if (klass->method.count) {
10506                 /* Find the already created inflated method */
10507                 for (i = 0; i < klass->method.count; ++i) {
10508                         g_assert (klass->methods [i]->is_inflated);
10509                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10510                                 break;
10511                 }
10512                 g_assert (i < klass->method.count);
10513                 imethod = (MonoMethodInflated*)klass->methods [i];
10514         } else {
10515                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10516         }
10517
10518         if (method->is_generic && method->klass->image->dynamic) {
10519                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10520
10521                 mono_loader_lock ();
10522                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10523                 mono_loader_unlock ();
10524         }
10525         return (MonoMethod *) imethod;
10526 }
10527
10528 static MonoMethod *
10529 inflate_method (MonoReflectionType *type, MonoObject *obj)
10530 {
10531         MonoMethod *method;
10532         MonoClass *gklass;
10533
10534         MonoClass *type_class = mono_object_class (type);
10535
10536         if (is_sre_generic_instance (type_class)) {
10537                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10538                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10539         } else if (is_sre_type_builder (type_class)) {
10540                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10541         } else if (type->type) {
10542                 gklass = mono_class_from_mono_type (type->type);
10543                 gklass = mono_class_get_generic_type_definition (gklass);
10544         } else {
10545                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10546         }
10547
10548         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10549                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10550                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10551                 else
10552                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10553         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10554                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10555         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10556                 method = ((MonoReflectionMethod *) obj)->method;
10557         else {
10558                 method = NULL; /* prevent compiler warning */
10559                 g_error ("can't handle type %s", obj->vtable->klass->name);
10560         }
10561
10562         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10563 }
10564
10565 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10566 void
10567 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10568                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10569                                           MonoArray *events)
10570 {
10571         MonoGenericClass *gclass;
10572         MonoDynamicGenericClass *dgclass;
10573         MonoClass *klass, *gklass;
10574         MonoType *gtype;
10575         int i;
10576
10577         MONO_ARCH_SAVE_REGS;
10578
10579         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10580         klass = mono_class_from_mono_type (gtype);
10581         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10582         gclass = gtype->data.generic_class;
10583
10584         if (!gclass->is_dynamic)
10585                 return;
10586
10587         dgclass = (MonoDynamicGenericClass *) gclass;
10588
10589         if (dgclass->initialized)
10590                 return;
10591
10592         gklass = gclass->container_class;
10593         mono_class_init (gklass);
10594
10595         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10596         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10597         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10598
10599         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10600         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10601         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10602         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10603         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10604
10605         for (i = 0; i < dgclass->count_methods; i++) {
10606                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10607
10608                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10609         }
10610
10611         for (i = 0; i < dgclass->count_ctors; i++) {
10612                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10613
10614                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10615         }
10616
10617         for (i = 0; i < dgclass->count_fields; i++) {
10618                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10619                 MonoClassField *field, *inflated_field = NULL;
10620
10621                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10622                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10623                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10624                         field = ((MonoReflectionField *) obj)->field;
10625                 else {
10626                         field = NULL; /* prevent compiler warning */
10627                         g_assert_not_reached ();
10628                 }
10629
10630                 dgclass->fields [i] = *field;
10631                 dgclass->fields [i].parent = klass;
10632                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10633                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10634                 dgclass->field_generic_types [i] = field->type;
10635                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10636                 dgclass->field_objects [i] = obj;
10637
10638                 if (inflated_field) {
10639                         g_free (inflated_field);
10640                 } else {
10641                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10642                 }
10643         }
10644
10645         dgclass->initialized = TRUE;
10646 }
10647
10648 static void
10649 fix_partial_generic_class (MonoClass *klass)
10650 {
10651         MonoClass *gklass = klass->generic_class->container_class;
10652         MonoDynamicGenericClass *dgclass;
10653         int i;
10654
10655         if (klass->wastypebuilder)
10656                 return;
10657
10658         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10659
10660         if (!dgclass->initialized)
10661                 return;
10662
10663         if (klass->method.count != gklass->method.count) {
10664                 klass->method.count = gklass->method.count;
10665                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10666
10667                 for (i = 0; i < klass->method.count; i++) {
10668                         klass->methods [i] = mono_class_inflate_generic_method_full (
10669                                 gklass->methods [i], klass, mono_class_get_context (klass));
10670                 }
10671         }
10672
10673         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10674                 klass->interface_count = gklass->interface_count;
10675                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10676                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10677
10678                 for (i = 0; i < gklass->interface_count; ++i) {
10679                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10680                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10681                         mono_metadata_free_type (iface_type);
10682
10683                         ensure_runtime_vtable (klass->interfaces [i]);
10684                 }
10685                 klass->interfaces_inited = 1;
10686         }
10687
10688         if (klass->field.count != gklass->field.count) {
10689                 klass->field.count = gklass->field.count;
10690                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10691
10692                 for (i = 0; i < klass->field.count; i++) {
10693                         klass->fields [i] = gklass->fields [i];
10694                         klass->fields [i].parent = klass;
10695                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10696                 }
10697         }
10698
10699         /*We can only finish with this klass once it's parent has as well*/
10700         if (gklass->wastypebuilder)
10701                 klass->wastypebuilder = TRUE;
10702         return;
10703 }
10704
10705 static void
10706 ensure_generic_class_runtime_vtable (MonoClass *klass)
10707 {
10708         MonoClass *gklass = klass->generic_class->container_class;
10709
10710         ensure_runtime_vtable (gklass); 
10711
10712         fix_partial_generic_class (klass);
10713 }
10714
10715 static void
10716 ensure_runtime_vtable (MonoClass *klass)
10717 {
10718         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10719         int i, num, j;
10720
10721         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10722                 return;
10723         if (klass->parent)
10724                 ensure_runtime_vtable (klass->parent);
10725
10726         if (tb) {
10727                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10728                 num += tb->num_methods;
10729                 klass->method.count = num;
10730                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10731                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10732                 for (i = 0; i < num; ++i)
10733                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10734                 num = tb->num_methods;
10735                 j = i;
10736                 for (i = 0; i < num; ++i)
10737                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10738         
10739                 if (tb->interfaces) {
10740                         klass->interface_count = mono_array_length (tb->interfaces);
10741                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10742                         for (i = 0; i < klass->interface_count; ++i) {
10743                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10744                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10745                                 ensure_runtime_vtable (klass->interfaces [i]);
10746                         }
10747                         klass->interfaces_inited = 1;
10748                 }
10749         } else if (klass->generic_class){
10750                 ensure_generic_class_runtime_vtable (klass);
10751         }
10752
10753         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10754                 for (i = 0; i < klass->method.count; ++i)
10755                         klass->methods [i]->slot = i;
10756                 
10757                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10758                 mono_class_setup_interface_offsets (klass);
10759                 mono_class_setup_interface_id (klass);
10760         }
10761
10762         /*
10763          * The generic vtable is needed even if image->run is not set since some
10764          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10765          * method->slot being defined.
10766          */
10767
10768         /* 
10769          * tb->methods could not be freed since it is used for determining 
10770          * overrides during dynamic vtable construction.
10771          */
10772 }
10773
10774 static MonoMethod*
10775 mono_reflection_method_get_handle (MonoObject *method)
10776 {
10777         MonoClass *class = mono_object_class (method);
10778         if (is_sr_mono_method (class)) {
10779                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10780                 return sr_method->method;
10781         }
10782         if (is_sre_method_builder (class)) {
10783                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10784                 return mb->mhandle;
10785         }
10786         if (is_sre_method_on_tb_inst (class)) {
10787                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10788                 MonoMethod *result;
10789                 /*FIXME move this to a proper method and unify with resolve_object*/
10790                 if (m->method_args) {
10791                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10792                 } else {
10793                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10794                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10795                         MonoMethod *mono_method;
10796
10797                         if (is_sre_method_builder (mono_object_class (m->mb)))
10798                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10799                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10800                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10801                         else
10802                                 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)));
10803
10804                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10805                 }
10806                 return result;
10807         }
10808
10809         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10810         return NULL;
10811 }
10812
10813 void
10814 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10815 {
10816         MonoReflectionTypeBuilder *tb;
10817         int i, onum;
10818
10819         *overrides = NULL;
10820         *num_overrides = 0;
10821
10822         g_assert (klass->image->dynamic);
10823
10824         if (!mono_class_get_ref_info (klass))
10825                 return;
10826
10827         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10828
10829         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10830
10831         onum = 0;
10832         if (tb->methods) {
10833                 for (i = 0; i < tb->num_methods; ++i) {
10834                         MonoReflectionMethodBuilder *mb = 
10835                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10836                         if (mb->override_method)
10837                                 onum ++;
10838                 }
10839         }
10840
10841         if (onum) {
10842                 *overrides = g_new0 (MonoMethod*, onum * 2);
10843
10844                 onum = 0;
10845                 for (i = 0; i < tb->num_methods; ++i) {
10846                         MonoReflectionMethodBuilder *mb = 
10847                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10848                         if (mb->override_method) {
10849                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10850                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10851
10852                                 g_assert (mb->mhandle);
10853
10854                                 onum ++;
10855                         }
10856                 }
10857         }
10858
10859         *num_overrides = onum;
10860 }
10861
10862 static void
10863 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10864 {
10865         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10866         MonoReflectionFieldBuilder *fb;
10867         MonoClassField *field;
10868         MonoImage *image = klass->image;
10869         const char *p, *p2;
10870         int i;
10871         guint32 len, idx, real_size = 0;
10872
10873         klass->field.count = tb->num_fields;
10874         klass->field.first = 0;
10875
10876         mono_error_init (error);
10877
10878         if (tb->class_size) {
10879                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10880                 klass->packing_size = tb->packing_size;
10881                 real_size = klass->instance_size + tb->class_size;
10882         }
10883
10884         if (!klass->field.count) {
10885                 klass->instance_size = MAX (klass->instance_size, real_size);
10886                 return;
10887         }
10888         
10889         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10890         mono_class_alloc_ext (klass);
10891         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10892         /*
10893         This is, guess what, a hack.
10894         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10895         On the static path no field class is resolved, only types are built. This is the right thing to do
10896         but we suck.
10897         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10898         */
10899         klass->size_inited = 1;
10900
10901         for (i = 0; i < klass->field.count; ++i) {
10902                 fb = mono_array_get (tb->fields, gpointer, i);
10903                 field = &klass->fields [i];
10904                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10905                 if (!mono_error_ok (error))
10906                         return;
10907                 if (fb->attrs) {
10908                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10909                         field->type->attrs = fb->attrs;
10910                 } else {
10911                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10912                 }
10913                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10914                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10915                 if (fb->offset != -1)
10916                         field->offset = fb->offset;
10917                 field->parent = klass;
10918                 fb->handle = field;
10919                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10920
10921                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10922                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10923                 }
10924                 if (fb->def_value) {
10925                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10926                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10927                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10928                         /* Copy the data from the blob since it might get realloc-ed */
10929                         p = assembly->blob.data + idx;
10930                         len = mono_metadata_decode_blob_size (p, &p2);
10931                         len += p2 - p;
10932                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10933                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10934                 }
10935         }
10936
10937         klass->instance_size = MAX (klass->instance_size, real_size);
10938         mono_class_layout_fields (klass);
10939 }
10940
10941 static void
10942 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10943 {
10944         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10945         MonoReflectionPropertyBuilder *pb;
10946         MonoImage *image = klass->image;
10947         MonoProperty *properties;
10948         int i;
10949
10950         mono_error_init (error);
10951
10952         if (!klass->ext)
10953                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10954
10955         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10956         klass->ext->property.first = 0;
10957
10958         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10959         klass->ext->properties = properties;
10960         for (i = 0; i < klass->ext->property.count; ++i) {
10961                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10962                 properties [i].parent = klass;
10963                 properties [i].attrs = pb->attrs;
10964                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10965                 if (!mono_error_ok (error))
10966                         return;
10967                 if (pb->get_method)
10968                         properties [i].get = pb->get_method->mhandle;
10969                 if (pb->set_method)
10970                         properties [i].set = pb->set_method->mhandle;
10971
10972                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10973         }
10974 }
10975
10976 MonoReflectionEvent *
10977 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10978 {
10979         MonoEvent *event = g_new0 (MonoEvent, 1);
10980         MonoClass *klass;
10981
10982         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10983
10984         event->parent = klass;
10985         event->attrs = eb->attrs;
10986         event->name = mono_string_to_utf8 (eb->name);
10987         if (eb->add_method)
10988                 event->add = eb->add_method->mhandle;
10989         if (eb->remove_method)
10990                 event->remove = eb->remove_method->mhandle;
10991         if (eb->raise_method)
10992                 event->raise = eb->raise_method->mhandle;
10993
10994 #ifndef MONO_SMALL_CONFIG
10995         if (eb->other_methods) {
10996                 int j;
10997                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10998                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10999                         MonoReflectionMethodBuilder *mb = 
11000                                 mono_array_get (eb->other_methods,
11001                                                 MonoReflectionMethodBuilder*, j);
11002                         event->other [j] = mb->mhandle;
11003                 }
11004         }
11005 #endif
11006
11007         return mono_event_get_object (mono_object_domain (tb), klass, event);
11008 }
11009
11010 static void
11011 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11012 {
11013         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11014         MonoReflectionEventBuilder *eb;
11015         MonoImage *image = klass->image;
11016         MonoEvent *events;
11017         int i;
11018
11019         mono_error_init (error);
11020
11021         if (!klass->ext)
11022                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11023
11024         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11025         klass->ext->event.first = 0;
11026
11027         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11028         klass->ext->events = events;
11029         for (i = 0; i < klass->ext->event.count; ++i) {
11030                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11031                 events [i].parent = klass;
11032                 events [i].attrs = eb->attrs;
11033                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11034                 if (!mono_error_ok (error))
11035                         return;
11036                 if (eb->add_method)
11037                         events [i].add = eb->add_method->mhandle;
11038                 if (eb->remove_method)
11039                         events [i].remove = eb->remove_method->mhandle;
11040                 if (eb->raise_method)
11041                         events [i].raise = eb->raise_method->mhandle;
11042
11043 #ifndef MONO_SMALL_CONFIG
11044                 if (eb->other_methods) {
11045                         int j;
11046                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11047                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11048                                 MonoReflectionMethodBuilder *mb = 
11049                                         mono_array_get (eb->other_methods,
11050                                                                         MonoReflectionMethodBuilder*, j);
11051                                 events [i].other [j] = mb->mhandle;
11052                         }
11053                 }
11054 #endif
11055                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11056         }
11057 }
11058
11059 static gboolean
11060 remove_instantiations_of_and_ensure_contents (gpointer key,
11061                                                   gpointer value,
11062                                                   gpointer user_data)
11063 {
11064         MonoType *type = (MonoType*)key;
11065         MonoClass *klass = (MonoClass*)user_data;
11066
11067         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11068                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11069                 return TRUE;
11070         } else
11071                 return FALSE;
11072 }
11073
11074 static void
11075 check_array_for_usertypes (MonoArray *arr)
11076 {
11077         int i;
11078
11079         if (!arr)
11080                 return;
11081
11082         for (i = 0; i < mono_array_length (arr); ++i)
11083                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11084 }
11085
11086 MonoReflectionType*
11087 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11088 {
11089         MonoError error;
11090         MonoClass *klass;
11091         MonoDomain* domain;
11092         MonoReflectionType* res;
11093         int i, j;
11094
11095         MONO_ARCH_SAVE_REGS;
11096
11097         domain = mono_object_domain (tb);
11098         klass = mono_class_from_mono_type (tb->type.type);
11099
11100         /*
11101          * Check for user defined Type subclasses.
11102          */
11103         RESOLVE_TYPE (tb->parent);
11104         check_array_for_usertypes (tb->interfaces);
11105         if (tb->fields) {
11106                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11107                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11108                         if (fb) {
11109                                 RESOLVE_TYPE (fb->type);
11110                                 check_array_for_usertypes (fb->modreq);
11111                                 check_array_for_usertypes (fb->modopt);
11112                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11113                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11114                         }
11115                 }
11116         }
11117         if (tb->methods) {
11118                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11119                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11120                         if (mb) {
11121                                 RESOLVE_TYPE (mb->rtype);
11122                                 check_array_for_usertypes (mb->return_modreq);
11123                                 check_array_for_usertypes (mb->return_modopt);
11124                                 check_array_for_usertypes (mb->parameters);
11125                                 if (mb->param_modreq)
11126                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11127                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11128                                 if (mb->param_modopt)
11129                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11130                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11131                         }
11132                 }
11133         }
11134         if (tb->ctors) {
11135                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11136                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11137                         if (mb) {
11138                                 check_array_for_usertypes (mb->parameters);
11139                                 if (mb->param_modreq)
11140                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11141                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11142                                 if (mb->param_modopt)
11143                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11144                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11145                         }
11146                 }
11147         }
11148
11149         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11150
11151         /* 
11152          * we need to lock the domain because the lock will be taken inside
11153          * So, we need to keep the locking order correct.
11154          */
11155         mono_loader_lock ();
11156         mono_domain_lock (domain);
11157         if (klass->wastypebuilder) {
11158                 mono_domain_unlock (domain);
11159                 mono_loader_unlock ();
11160                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11161         }
11162         /*
11163          * Fields to set in klass:
11164          * the various flags: delegate/unicode/contextbound etc.
11165          */
11166         klass->flags = tb->attrs;
11167         klass->has_cctor = 1;
11168         klass->has_finalize = 1;
11169
11170         /* fool mono_class_setup_parent */
11171         klass->supertypes = NULL;
11172         mono_class_setup_parent (klass, klass->parent);
11173         mono_class_setup_mono_type (klass);
11174
11175 #if 0
11176         if (!((MonoDynamicImage*)klass->image)->run) {
11177                 if (klass->generic_container) {
11178                         /* FIXME: The code below can't handle generic classes */
11179                         klass->wastypebuilder = TRUE;
11180                         mono_loader_unlock ();
11181                         mono_domain_unlock (domain);
11182                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11183                 }
11184         }
11185 #endif
11186
11187         /* enums are done right away */
11188         if (!klass->enumtype)
11189                 ensure_runtime_vtable (klass);
11190
11191         if (tb->subtypes) {
11192                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11193                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11194                         mono_class_alloc_ext (klass);
11195                         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)));
11196                 }
11197         }
11198
11199         klass->nested_classes_inited = TRUE;
11200
11201         /* fields and object layout */
11202         if (klass->parent) {
11203                 if (!klass->parent->size_inited)
11204                         mono_class_init (klass->parent);
11205                 klass->instance_size = klass->parent->instance_size;
11206                 klass->sizes.class_size = 0;
11207                 klass->min_align = klass->parent->min_align;
11208                 /* if the type has no fields we won't call the field_setup
11209                  * routine which sets up klass->has_references.
11210                  */
11211                 klass->has_references |= klass->parent->has_references;
11212         } else {
11213                 klass->instance_size = sizeof (MonoObject);
11214                 klass->min_align = 1;
11215         }
11216
11217         /* FIXME: handle packing_size and instance_size */
11218         typebuilder_setup_fields (klass, &error);
11219         if (!mono_error_ok (&error))
11220                 goto failure;
11221         typebuilder_setup_properties (klass, &error);
11222         if (!mono_error_ok (&error))
11223                 goto failure;
11224
11225         typebuilder_setup_events (klass, &error);
11226         if (!mono_error_ok (&error))
11227                 goto failure;
11228
11229         klass->wastypebuilder = TRUE;
11230
11231         /* 
11232          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11233          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11234          * we want to return normal System.MonoType objects, so clear these out from the cache.
11235          *
11236          * Together with this we must ensure the contents of all instances to match the created type.
11237          */
11238         if (domain->type_hash && klass->generic_container)
11239                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11240
11241         mono_domain_unlock (domain);
11242         mono_loader_unlock ();
11243
11244         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11245                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11246                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11247         }
11248
11249         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11250         g_assert (res != (MonoReflectionType*)tb);
11251
11252         return res;
11253
11254 failure:
11255         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11256         klass->wastypebuilder = TRUE;
11257         mono_domain_unlock (domain);
11258         mono_loader_unlock ();
11259         mono_error_raise_exception (&error);
11260         return NULL;
11261 }
11262
11263 void
11264 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11265 {
11266         MonoGenericParamFull *param;
11267         MonoImage *image;
11268         MonoClass *pklass;
11269
11270         MONO_ARCH_SAVE_REGS;
11271
11272         param = g_new0 (MonoGenericParamFull, 1);
11273
11274         if (gparam->mbuilder) {
11275                 if (!gparam->mbuilder->generic_container) {
11276                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11277                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11278                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11279                         gparam->mbuilder->generic_container->is_method = TRUE;
11280                         /* 
11281                          * Cannot set owner.method, since the MonoMethod is not created yet.
11282                          * Set the image field instead, so type_in_image () works.
11283                          */
11284                         gparam->mbuilder->generic_container->image = klass->image;
11285                 }
11286                 param->param.owner = gparam->mbuilder->generic_container;
11287         } else if (gparam->tbuilder) {
11288                 if (!gparam->tbuilder->generic_container) {
11289                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11290                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11291                         gparam->tbuilder->generic_container->owner.klass = klass;
11292                 }
11293                 param->param.owner = gparam->tbuilder->generic_container;
11294         }
11295
11296         param->info.name = mono_string_to_utf8 (gparam->name);
11297         param->param.num = gparam->index;
11298
11299         image = &gparam->tbuilder->module->dynamic_image->image;
11300         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11301
11302         gparam->type.type = &pklass->byval_arg;
11303
11304         mono_class_set_ref_info (pklass, gparam);
11305         mono_image_lock (image);
11306         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11307         mono_image_unlock (image);
11308 }
11309
11310 MonoArray *
11311 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11312 {
11313         MonoReflectionModuleBuilder *module = sig->module;
11314         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11315         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11316         guint32 buflen, i;
11317         MonoArray *result;
11318         SigBuffer buf;
11319
11320         check_array_for_usertypes (sig->arguments);
11321
11322         sigbuffer_init (&buf, 32);
11323
11324         sigbuffer_add_value (&buf, 0x07);
11325         sigbuffer_add_value (&buf, na);
11326         if (assembly != NULL){
11327                 for (i = 0; i < na; ++i) {
11328                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11329                         encode_reflection_type (assembly, type, &buf);
11330                 }
11331         }
11332
11333         buflen = buf.p - buf.buf;
11334         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11335         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11336         sigbuffer_free (&buf);
11337
11338         return result;
11339 }
11340
11341 MonoArray *
11342 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11343 {
11344         MonoDynamicImage *assembly = sig->module->dynamic_image;
11345         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11346         guint32 buflen, i;
11347         MonoArray *result;
11348         SigBuffer buf;
11349
11350         check_array_for_usertypes (sig->arguments);
11351
11352         sigbuffer_init (&buf, 32);
11353
11354         sigbuffer_add_value (&buf, 0x06);
11355         for (i = 0; i < na; ++i) {
11356                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11357                 encode_reflection_type (assembly, type, &buf);
11358         }
11359
11360         buflen = buf.p - buf.buf;
11361         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11362         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11363         sigbuffer_free (&buf);
11364
11365         return result;
11366 }
11367
11368 void 
11369 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11370 {
11371         ReflectionMethodBuilder rmb;
11372         MonoMethodSignature *sig;
11373         MonoClass *klass;
11374         GSList *l;
11375         int i;
11376
11377         sig = dynamic_method_to_signature (mb);
11378
11379         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11380
11381         /*
11382          * Resolve references.
11383          */
11384         /* 
11385          * Every second entry in the refs array is reserved for storing handle_class,
11386          * which is needed by the ldtoken implementation in the JIT.
11387          */
11388         rmb.nrefs = mb->nrefs;
11389         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11390         for (i = 0; i < mb->nrefs; i += 2) {
11391                 MonoClass *handle_class;
11392                 gpointer ref;
11393                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11394
11395                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11396                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11397                         /*
11398                          * The referenced DynamicMethod should already be created by the managed
11399                          * code, except in the case of circular references. In that case, we store
11400                          * method in the refs array, and fix it up later when the referenced 
11401                          * DynamicMethod is created.
11402                          */
11403                         if (method->mhandle) {
11404                                 ref = method->mhandle;
11405                         } else {
11406                                 /* FIXME: GC object stored in unmanaged memory */
11407                                 ref = method;
11408
11409                                 /* FIXME: GC object stored in unmanaged memory */
11410                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11411                         }
11412                         handle_class = mono_defaults.methodhandle_class;
11413                 } else {
11414                         MonoException *ex = NULL;
11415                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11416                         if (!ref)
11417                                 ex = mono_get_exception_type_load (NULL, NULL);
11418                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11419                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11420
11421                         if (ex) {
11422                                 g_free (rmb.refs);
11423                                 mono_raise_exception (ex);
11424                                 return;
11425                         }
11426                 }
11427
11428                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11429                 rmb.refs [i + 1] = handle_class;
11430         }               
11431
11432         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11433
11434         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11435
11436         /* Fix up refs entries pointing at us */
11437         for (l = mb->referenced_by; l; l = l->next) {
11438                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11439                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11440                 gpointer *data;
11441                 
11442                 g_assert (method->mhandle);
11443
11444                 data = (gpointer*)wrapper->method_data;
11445                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11446                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11447                                 data [i + 1] = mb->mhandle;
11448                 }
11449         }
11450         g_slist_free (mb->referenced_by);
11451
11452         g_free (rmb.refs);
11453
11454         /* ilgen is no longer needed */
11455         mb->ilgen = NULL;
11456 }
11457
11458 #endif /* DISABLE_REFLECTION_EMIT */
11459
11460 void
11461 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11462 {
11463         g_assert (mb);
11464
11465         if (mb->mhandle)
11466                 mono_runtime_free_method (
11467                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11468 }
11469
11470 /**
11471  * 
11472  * mono_reflection_is_valid_dynamic_token:
11473  * 
11474  * Returns TRUE if token is valid.
11475  * 
11476  */
11477 gboolean
11478 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11479 {
11480         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11481 }
11482
11483 #ifndef DISABLE_REFLECTION_EMIT
11484
11485 /**
11486  * mono_reflection_lookup_dynamic_token:
11487  *
11488  * Finish the Builder object pointed to by TOKEN and return the corresponding
11489  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11490  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11491  * mapping table.
11492  *
11493  * LOCKING: Take the loader lock
11494  */
11495 gpointer
11496 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11497 {
11498         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11499         MonoObject *obj;
11500         MonoClass *klass;
11501
11502         mono_loader_lock ();
11503         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11504         mono_loader_unlock ();
11505         if (!obj) {
11506                 if (valid_token)
11507                         g_error ("Could not find required dynamic token 0x%08x", token);
11508                 else
11509                         return NULL;
11510         }
11511
11512         if (!handle_class)
11513                 handle_class = &klass;
11514         return resolve_object (image, obj, handle_class, context);
11515 }
11516
11517 /*
11518  * ensure_complete_type:
11519  *
11520  *   Ensure that KLASS is completed if it is a dynamic type, or references
11521  * dynamic types.
11522  */
11523 static void
11524 ensure_complete_type (MonoClass *klass)
11525 {
11526         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11527                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11528
11529                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11530
11531                 // Asserting here could break a lot of code
11532                 //g_assert (klass->wastypebuilder);
11533         }
11534
11535         if (klass->generic_class) {
11536                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11537                 int i;
11538
11539                 for (i = 0; i < inst->type_argc; ++i) {
11540                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11541                 }
11542         }
11543 }
11544
11545 static gpointer
11546 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11547 {
11548         gpointer result = NULL;
11549
11550         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11551                 result = mono_string_intern ((MonoString*)obj);
11552                 *handle_class = mono_defaults.string_class;
11553                 g_assert (result);
11554         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11555                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11556                 if (context) {
11557                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11558                         result = mono_class_from_mono_type (inflated);
11559                         mono_metadata_free_type (inflated);
11560                 } else {
11561                         result = mono_class_from_mono_type (type);
11562                 }
11563                 *handle_class = mono_defaults.typehandle_class;
11564                 g_assert (result);
11565         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11566                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11567                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11568                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11569                 result = ((MonoReflectionMethod*)obj)->method;
11570                 if (context)
11571                         result = mono_class_inflate_generic_method (result, context);
11572                 *handle_class = mono_defaults.methodhandle_class;
11573                 g_assert (result);
11574         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11575                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11576                 result = mb->mhandle;
11577                 if (!result) {
11578                         /* Type is not yet created */
11579                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11580
11581                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11582
11583                         /*
11584                          * Hopefully this has been filled in by calling CreateType() on the
11585                          * TypeBuilder.
11586                          */
11587                         /*
11588                          * TODO: This won't work if the application finishes another 
11589                          * TypeBuilder instance instead of this one.
11590                          */
11591                         result = mb->mhandle;
11592                 }
11593                 if (context)
11594                         result = mono_class_inflate_generic_method (result, context);
11595                 *handle_class = mono_defaults.methodhandle_class;
11596         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11597                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11598
11599                 result = cb->mhandle;
11600                 if (!result) {
11601                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11602
11603                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11604                         result = cb->mhandle;
11605                 }
11606                 if (context)
11607                         result = mono_class_inflate_generic_method (result, context);
11608                 *handle_class = mono_defaults.methodhandle_class;
11609         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11610                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11611
11612                 ensure_complete_type (field->parent);
11613                 if (context) {
11614                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11615                         MonoClass *class = mono_class_from_mono_type (inflated);
11616                         MonoClassField *inflated_field;
11617                         gpointer iter = NULL;
11618                         mono_metadata_free_type (inflated);
11619                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11620                                 if (!strcmp (field->name, inflated_field->name))
11621                                         break;
11622                         }
11623                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11624                         result = inflated_field;
11625                 } else {
11626                         result = field;
11627                 }
11628                 *handle_class = mono_defaults.fieldhandle_class;
11629                 g_assert (result);
11630         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11631                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11632                 result = fb->handle;
11633
11634                 if (!result) {
11635                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11636
11637                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11638                         result = fb->handle;
11639                 }
11640
11641                 if (fb->handle && fb->handle->parent->generic_container) {
11642                         MonoClass *klass = fb->handle->parent;
11643                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11644                         MonoClass *inflated = mono_class_from_mono_type (type);
11645
11646                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11647                         g_assert (result);
11648                         mono_metadata_free_type (type);
11649                 }
11650                 *handle_class = mono_defaults.fieldhandle_class;
11651         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11652                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11653                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11654                 MonoClass *klass;
11655
11656                 klass = type->data.klass;
11657                 if (klass->wastypebuilder) {
11658                         /* Already created */
11659                         result = klass;
11660                 }
11661                 else {
11662                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11663                         result = type->data.klass;
11664                         g_assert (result);
11665                 }
11666                 *handle_class = mono_defaults.typehandle_class;
11667         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11668                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11669                 MonoMethodSignature *sig;
11670                 int nargs, i;
11671
11672                 if (helper->arguments)
11673                         nargs = mono_array_length (helper->arguments);
11674                 else
11675                         nargs = 0;
11676
11677                 sig = mono_metadata_signature_alloc (image, nargs);
11678                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11679                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11680
11681                 if (helper->unmanaged_call_conv) { /* unmanaged */
11682                         sig->call_convention = helper->unmanaged_call_conv - 1;
11683                         sig->pinvoke = TRUE;
11684                 } else if (helper->call_conv & 0x02) {
11685                         sig->call_convention = MONO_CALL_VARARG;
11686                 } else {
11687                         sig->call_convention = MONO_CALL_DEFAULT;
11688                 }
11689
11690                 sig->param_count = nargs;
11691                 /* TODO: Copy type ? */
11692                 sig->ret = helper->return_type->type;
11693                 for (i = 0; i < nargs; ++i)
11694                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11695
11696                 result = sig;
11697                 *handle_class = NULL;
11698         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11699                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11700                 /* Already created by the managed code */
11701                 g_assert (method->mhandle);
11702                 result = method->mhandle;
11703                 *handle_class = mono_defaults.methodhandle_class;
11704         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11705                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11706                 type = mono_class_inflate_generic_type (type, context);
11707                 result = mono_class_from_mono_type (type);
11708                 *handle_class = mono_defaults.typehandle_class;
11709                 g_assert (result);
11710                 mono_metadata_free_type (type);
11711         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11712                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11713                 type = mono_class_inflate_generic_type (type, context);
11714                 result = mono_class_from_mono_type (type);
11715                 *handle_class = mono_defaults.typehandle_class;
11716                 g_assert (result);
11717                 mono_metadata_free_type (type);
11718         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11719                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11720                 MonoClass *inflated;
11721                 MonoType *type;
11722                 MonoClassField *field;
11723
11724                 if (is_sre_field_builder (mono_object_class (f->fb)))
11725                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11726                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11727                         field = ((MonoReflectionField*)f->fb)->field;
11728                 else
11729                         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)));
11730
11731                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11732                 inflated = mono_class_from_mono_type (type);
11733
11734                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11735                 ensure_complete_type (field->parent);
11736                 g_assert (result);
11737                 mono_metadata_free_type (type);
11738                 *handle_class = mono_defaults.fieldhandle_class;
11739         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11740                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11741                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11742                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11743                 MonoMethod *method;
11744
11745                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11746                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11747                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11748                         method = ((MonoReflectionMethod *)c->cb)->method;
11749                 else
11750                         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)));
11751
11752                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11753                 *handle_class = mono_defaults.methodhandle_class;
11754                 mono_metadata_free_type (type);
11755         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11756                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11757                 if (m->method_args) {
11758                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11759                         if (context)
11760                                 result = mono_class_inflate_generic_method (result, context);
11761                 } else {
11762                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11763                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11764                         MonoMethod *method;
11765
11766                         if (is_sre_method_builder (mono_object_class (m->mb)))
11767                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11768                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11769                                 method = ((MonoReflectionMethod *)m->mb)->method;
11770                         else
11771                                 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)));
11772
11773                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11774                         mono_metadata_free_type (type);
11775                 }
11776                 *handle_class = mono_defaults.methodhandle_class;
11777         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11778                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11779                 MonoType *mtype;
11780                 MonoClass *klass;
11781                 MonoMethod *method;
11782                 gpointer iter;
11783                 char *name;
11784
11785                 mtype = mono_reflection_type_get_handle (m->parent);
11786                 klass = mono_class_from_mono_type (mtype);
11787
11788                 /* Find the method */
11789
11790                 name = mono_string_to_utf8 (m->name);
11791                 iter = NULL;
11792                 while ((method = mono_class_get_methods (klass, &iter))) {
11793                         if (!strcmp (method->name, name))
11794                                 break;
11795                 }
11796                 g_free (name);
11797
11798                 // FIXME:
11799                 g_assert (method);
11800                 // FIXME: Check parameters/return value etc. match
11801
11802                 result = method;
11803                 *handle_class = mono_defaults.methodhandle_class;
11804         } else if (is_sre_array (mono_object_get_class(obj)) ||
11805                                 is_sre_byref (mono_object_get_class(obj)) ||
11806                                 is_sre_pointer (mono_object_get_class(obj))) {
11807                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11808                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11809                 result = mono_class_from_mono_type (type);
11810                 *handle_class = mono_defaults.typehandle_class;
11811         } else {
11812                 g_print ("%s\n", obj->vtable->klass->name);
11813                 g_assert_not_reached ();
11814         }
11815         return result;
11816 }
11817
11818 #else /* DISABLE_REFLECTION_EMIT */
11819
11820 MonoArray*
11821 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11822 {
11823         g_assert_not_reached ();
11824         return NULL;
11825 }
11826
11827 void
11828 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11829 {
11830         g_assert_not_reached ();
11831 }
11832
11833 void
11834 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11835 {
11836         g_assert_not_reached ();
11837 }
11838
11839 void
11840 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11841 {
11842         g_assert_not_reached ();
11843 }
11844
11845 void
11846 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11847 {
11848         g_assert_not_reached ();
11849 }
11850
11851 void
11852 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11853 {
11854         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11855 }
11856
11857 void
11858 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11859 {
11860         g_assert_not_reached ();
11861 }
11862
11863 void
11864 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11865 {
11866         g_assert_not_reached ();
11867 }
11868
11869 MonoReflectionModule *
11870 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11871 {
11872         g_assert_not_reached ();
11873         return NULL;
11874 }
11875
11876 guint32
11877 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11878 {
11879         g_assert_not_reached ();
11880         return 0;
11881 }
11882
11883 guint32
11884 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11885 {
11886         g_assert_not_reached ();
11887         return 0;
11888 }
11889
11890 guint32
11891 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11892                                                  gboolean create_methodspec, gboolean register_token)
11893 {
11894         g_assert_not_reached ();
11895         return 0;
11896 }
11897
11898 void
11899 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11900 {
11901 }
11902
11903 void
11904 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11905                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11906                                           MonoArray *events)
11907 {
11908         g_assert_not_reached ();
11909 }
11910
11911 void
11912 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11913 {
11914         *overrides = NULL;
11915         *num_overrides = 0;
11916 }
11917
11918 MonoReflectionEvent *
11919 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11920 {
11921         g_assert_not_reached ();
11922         return NULL;
11923 }
11924
11925 MonoReflectionType*
11926 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11927 {
11928         g_assert_not_reached ();
11929         return NULL;
11930 }
11931
11932 void
11933 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11934 {
11935         g_assert_not_reached ();
11936 }
11937
11938 MonoArray *
11939 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11940 {
11941         g_assert_not_reached ();
11942         return NULL;
11943 }
11944
11945 MonoArray *
11946 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11947 {
11948         g_assert_not_reached ();
11949         return NULL;
11950 }
11951
11952 void 
11953 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11954 {
11955 }
11956
11957 gpointer
11958 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11959 {
11960         return NULL;
11961 }
11962
11963 MonoType*
11964 mono_reflection_type_get_handle (MonoReflectionType* ref)
11965 {
11966         if (!ref)
11967                 return NULL;
11968         return ref->type;
11969 }
11970
11971 #endif /* DISABLE_REFLECTION_EMIT */
11972
11973 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11974 const static guint32 declsec_flags_map[] = {
11975         0x00000000,                                     /* empty */
11976         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
11977         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
11978         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
11979         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
11980         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
11981         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
11982         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
11983         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
11984         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
11985         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
11986         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
11987         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
11988         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
11989         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
11990         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
11991         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
11992         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
11993         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
11994 };
11995
11996 /*
11997  * Returns flags that includes all available security action associated to the handle.
11998  * @token: metadata token (either for a class or a method)
11999  * @image: image where resides the metadata.
12000  */
12001 static guint32
12002 mono_declsec_get_flags (MonoImage *image, guint32 token)
12003 {
12004         int index = mono_metadata_declsec_from_index (image, token);
12005         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12006         guint32 result = 0;
12007         guint32 action;
12008         int i;
12009
12010         /* HasSecurity can be present for other, not specially encoded, attributes,
12011            e.g. SuppressUnmanagedCodeSecurityAttribute */
12012         if (index < 0)
12013                 return 0;
12014
12015         for (i = index; i < t->rows; i++) {
12016                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12017
12018                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12019                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12020                         break;
12021
12022                 action = cols [MONO_DECL_SECURITY_ACTION];
12023                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12024                         result |= declsec_flags_map [action];
12025                 } else {
12026                         g_assert_not_reached ();
12027                 }
12028         }
12029         return result;
12030 }
12031
12032 /*
12033  * Get the security actions (in the form of flags) associated with the specified method.
12034  *
12035  * @method: The method for which we want the declarative security flags.
12036  * Return the declarative security flags for the method (only).
12037  *
12038  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12039  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12040  */
12041 guint32
12042 mono_declsec_flags_from_method (MonoMethod *method)
12043 {
12044         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12045                 /* FIXME: No cache (for the moment) */
12046                 guint32 idx = mono_method_get_index (method);
12047                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12048                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12049                 return mono_declsec_get_flags (method->klass->image, idx);
12050         }
12051         return 0;
12052 }
12053
12054 /*
12055  * Get the security actions (in the form of flags) associated with the specified class.
12056  *
12057  * @klass: The class for which we want the declarative security flags.
12058  * Return the declarative security flags for the class.
12059  *
12060  * Note: We cache the flags inside the MonoClass structure as this will get 
12061  *       called very often (at least for each method).
12062  */
12063 guint32
12064 mono_declsec_flags_from_class (MonoClass *klass)
12065 {
12066         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12067                 if (!klass->ext || !klass->ext->declsec_flags) {
12068                         guint32 idx;
12069
12070                         idx = mono_metadata_token_index (klass->type_token);
12071                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12072                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12073                         mono_loader_lock ();
12074                         mono_class_alloc_ext (klass);
12075                         mono_loader_unlock ();
12076                         /* we cache the flags on classes */
12077                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12078                 }
12079                 return klass->ext->declsec_flags;
12080         }
12081         return 0;
12082 }
12083
12084 /*
12085  * Get the security actions (in the form of flags) associated with the specified assembly.
12086  *
12087  * @assembly: The assembly for which we want the declarative security flags.
12088  * Return the declarative security flags for the assembly.
12089  */
12090 guint32
12091 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12092 {
12093         guint32 idx = 1; /* there is only one assembly */
12094         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12095         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12096         return mono_declsec_get_flags (assembly->image, idx);
12097 }
12098
12099
12100 /*
12101  * Fill actions for the specific index (which may either be an encoded class token or
12102  * an encoded method token) from the metadata image.
12103  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12104  */
12105 static MonoBoolean
12106 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12107         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12108 {
12109         MonoBoolean result = FALSE;
12110         MonoTableInfo *t;
12111         guint32 cols [MONO_DECL_SECURITY_SIZE];
12112         int index = mono_metadata_declsec_from_index (image, token);
12113         int i;
12114
12115         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12116         for (i = index; i < t->rows; i++) {
12117                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12118
12119                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12120                         return result;
12121
12122                 /* if present only replace (class) permissions with method permissions */
12123                 /* if empty accept either class or method permissions */
12124                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12125                         if (!actions->demand.blob) {
12126                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12127                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12128                                 actions->demand.blob = (char*) (blob + 2);
12129                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12130                                 result = TRUE;
12131                         }
12132                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12133                         if (!actions->noncasdemand.blob) {
12134                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12135                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12136                                 actions->noncasdemand.blob = (char*) (blob + 2);
12137                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12138                                 result = TRUE;
12139                         }
12140                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12141                         if (!actions->demandchoice.blob) {
12142                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12143                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12144                                 actions->demandchoice.blob = (char*) (blob + 2);
12145                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12146                                 result = TRUE;
12147                         }
12148                 }
12149         }
12150
12151         return result;
12152 }
12153
12154 static MonoBoolean
12155 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12156         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12157 {
12158         guint32 idx = mono_metadata_token_index (klass->type_token);
12159         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12160         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12161         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12162 }
12163
12164 static MonoBoolean
12165 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12166         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12167 {
12168         guint32 idx = mono_method_get_index (method);
12169         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12170         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12171         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12172 }
12173
12174 /*
12175  * Collect all actions (that requires to generate code in mini) assigned for
12176  * the specified method.
12177  * Note: Don't use the content of actions if the function return FALSE.
12178  */
12179 MonoBoolean
12180 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12181 {
12182         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12183                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12184         MonoBoolean result = FALSE;
12185         guint32 flags;
12186
12187         /* quick exit if no declarative security is present in the metadata */
12188         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12189                 return FALSE;
12190
12191         /* we want the original as the wrapper is "free" of the security informations */
12192         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12193                 method = mono_marshal_method_from_wrapper (method);
12194                 if (!method)
12195                         return FALSE;
12196         }
12197
12198         /* First we look for method-level attributes */
12199         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12200                 mono_class_init (method->klass);
12201                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12202
12203                 result = mono_declsec_get_method_demands_params (method, demands, 
12204                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12205         }
12206
12207         /* Here we use (or create) the class declarative cache to look for demands */
12208         flags = mono_declsec_flags_from_class (method->klass);
12209         if (flags & mask) {
12210                 if (!result) {
12211                         mono_class_init (method->klass);
12212                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12213                 }
12214                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12215                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12216         }
12217
12218         /* The boolean return value is used as a shortcut in case nothing needs to
12219            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12220         return result;
12221 }
12222
12223
12224 /*
12225  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12226  *
12227  * Note: Don't use the content of actions if the function return FALSE.
12228  */
12229 MonoBoolean
12230 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12231 {
12232         MonoBoolean result = FALSE;
12233         guint32 flags;
12234
12235         /* quick exit if no declarative security is present in the metadata */
12236         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12237                 return FALSE;
12238
12239         /* we want the original as the wrapper is "free" of the security informations */
12240         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12241                 method = mono_marshal_method_from_wrapper (method);
12242                 if (!method)
12243                         return FALSE;
12244         }
12245
12246         /* results are independant - zeroize both */
12247         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12248         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12249
12250         /* First we look for method-level attributes */
12251         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12252                 mono_class_init (method->klass);
12253
12254                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12255                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12256         }
12257
12258         /* Here we use (or create) the class declarative cache to look for demands */
12259         flags = mono_declsec_flags_from_class (method->klass);
12260         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12261                 mono_class_init (method->klass);
12262
12263                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12264                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12265         }
12266
12267         return result;
12268 }
12269
12270 /*
12271  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12272  *
12273  * @klass       The inherited class - this is the class that provides the security check (attributes)
12274  * @demans      
12275  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12276  * 
12277  * Note: Don't use the content of actions if the function return FALSE.
12278  */
12279 MonoBoolean
12280 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12281 {
12282         MonoBoolean result = FALSE;
12283         guint32 flags;
12284
12285         /* quick exit if no declarative security is present in the metadata */
12286         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12287                 return FALSE;
12288
12289         /* Here we use (or create) the class declarative cache to look for demands */
12290         flags = mono_declsec_flags_from_class (klass);
12291         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12292                 mono_class_init (klass);
12293                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12294
12295                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12296                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12297         }
12298
12299         return result;
12300 }
12301
12302 /*
12303  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12304  *
12305  * Note: Don't use the content of actions if the function return FALSE.
12306  */
12307 MonoBoolean
12308 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12309 {
12310         /* quick exit if no declarative security is present in the metadata */
12311         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12312                 return FALSE;
12313
12314         /* we want the original as the wrapper is "free" of the security informations */
12315         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12316                 method = mono_marshal_method_from_wrapper (method);
12317                 if (!method)
12318                         return FALSE;
12319         }
12320
12321         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12322                 mono_class_init (method->klass);
12323                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12324
12325                 return mono_declsec_get_method_demands_params (method, demands, 
12326                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12327         }
12328         return FALSE;
12329 }
12330
12331
12332 static MonoBoolean
12333 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12334 {
12335         guint32 cols [MONO_DECL_SECURITY_SIZE];
12336         MonoTableInfo *t;
12337         int i;
12338
12339         int index = mono_metadata_declsec_from_index (image, token);
12340         if (index == -1)
12341                 return FALSE;
12342
12343         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12344         for (i = index; i < t->rows; i++) {
12345                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12346
12347                 /* shortcut - index are ordered */
12348                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12349                         return FALSE;
12350
12351                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12352                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12353                         entry->blob = (char*) (metadata + 2);
12354                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12355                         return TRUE;
12356                 }
12357         }
12358
12359         return FALSE;
12360 }
12361
12362 MonoBoolean
12363 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12364 {
12365         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12366                 guint32 idx = mono_method_get_index (method);
12367                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12368                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12369                 return get_declsec_action (method->klass->image, idx, action, entry);
12370         }
12371         return FALSE;
12372 }
12373
12374 MonoBoolean
12375 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12376 {
12377         /* use cache */
12378         guint32 flags = mono_declsec_flags_from_class (klass);
12379         if (declsec_flags_map [action] & flags) {
12380                 guint32 idx = mono_metadata_token_index (klass->type_token);
12381                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12382                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12383                 return get_declsec_action (klass->image, idx, action, entry);
12384         }
12385         return FALSE;
12386 }
12387
12388 MonoBoolean
12389 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12390 {
12391         guint32 idx = 1; /* there is only one assembly */
12392         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12393         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12394
12395         return get_declsec_action (assembly->image, idx, action, entry);
12396 }
12397
12398 gboolean
12399 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12400 {
12401         MonoObject *res, *exc;
12402         void *params [1];
12403         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12404         static MonoMethod *method = NULL;
12405
12406         if (!System_Reflection_Emit_TypeBuilder) {
12407                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12408                 g_assert (System_Reflection_Emit_TypeBuilder);
12409         }
12410         if (method == NULL) {
12411                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12412                 g_assert (method);
12413         }
12414
12415         /* 
12416          * The result of mono_type_get_object () might be a System.MonoType but we
12417          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12418          */
12419         g_assert (mono_class_get_ref_info (klass));
12420         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12421
12422         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12423
12424         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12425         if (exc)
12426                 return FALSE;
12427         else
12428                 return *(MonoBoolean*)mono_object_unbox (res);
12429 }