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