Merge remote branch 'upstream/master'
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45
46 static gboolean is_usertype (MonoReflectionType *ref);
47 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
48
49 typedef struct {
50         char *p;
51         char *buf;
52         char *end;
53 } SigBuffer;
54
55 #define TEXT_OFFSET 512
56 #define CLI_H_SIZE 136
57 #define FILE_ALIGN 512
58 #define VIRT_ALIGN 8192
59 #define START_TEXT_RVA  0x00002000
60
61 typedef struct {
62         MonoReflectionILGen *ilgen;
63         MonoReflectionType *rtype;
64         MonoArray *parameters;
65         MonoArray *generic_params;
66         MonoGenericContainer *generic_container;
67         MonoArray *pinfo;
68         MonoArray *opt_types;
69         guint32 attrs;
70         guint32 iattrs;
71         guint32 call_conv;
72         guint32 *table_idx; /* note: it's a pointer */
73         MonoArray *code;
74         MonoObject *type;
75         MonoString *name;
76         MonoBoolean init_locals;
77         MonoBoolean skip_visibility;
78         MonoArray *return_modreq;
79         MonoArray *return_modopt;
80         MonoArray *param_modreq;
81         MonoArray *param_modopt;
82         MonoArray *permissions;
83         MonoMethod *mhandle;
84         guint32 nrefs;
85         gpointer *refs;
86         /* for PInvoke */
87         int charset, extra_flags, native_cc;
88         MonoString *dll, *dllentry;
89 } ReflectionMethodBuilder;
90
91 typedef struct {
92         guint32 owner;
93         MonoReflectionGenericParam *gparam;
94 } GenericParamTableEntry;
95
96 const unsigned char table_sizes [MONO_TABLE_NUM] = {
97         MONO_MODULE_SIZE,
98         MONO_TYPEREF_SIZE,
99         MONO_TYPEDEF_SIZE,
100         0,
101         MONO_FIELD_SIZE,
102         0,
103         MONO_METHOD_SIZE,
104         0,
105         MONO_PARAM_SIZE,
106         MONO_INTERFACEIMPL_SIZE,
107         MONO_MEMBERREF_SIZE,    /* 0x0A */
108         MONO_CONSTANT_SIZE,
109         MONO_CUSTOM_ATTR_SIZE,
110         MONO_FIELD_MARSHAL_SIZE,
111         MONO_DECL_SECURITY_SIZE,
112         MONO_CLASS_LAYOUT_SIZE,
113         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
114         MONO_STAND_ALONE_SIGNATURE_SIZE,
115         MONO_EVENT_MAP_SIZE,
116         0,
117         MONO_EVENT_SIZE,
118         MONO_PROPERTY_MAP_SIZE,
119         0,
120         MONO_PROPERTY_SIZE,
121         MONO_METHOD_SEMA_SIZE,
122         MONO_METHODIMPL_SIZE,
123         MONO_MODULEREF_SIZE,    /* 0x1A */
124         MONO_TYPESPEC_SIZE,
125         MONO_IMPLMAP_SIZE,      
126         MONO_FIELD_RVA_SIZE,
127         0,
128         0,
129         MONO_ASSEMBLY_SIZE,     /* 0x20 */
130         MONO_ASSEMBLY_PROCESSOR_SIZE,
131         MONO_ASSEMBLYOS_SIZE,
132         MONO_ASSEMBLYREF_SIZE,
133         MONO_ASSEMBLYREFPROC_SIZE,
134         MONO_ASSEMBLYREFOS_SIZE,
135         MONO_FILE_SIZE,
136         MONO_EXP_TYPE_SIZE,
137         MONO_MANIFEST_SIZE,
138         MONO_NESTED_CLASS_SIZE,
139
140         MONO_GENERICPARAM_SIZE, /* 0x2A */
141         MONO_METHODSPEC_SIZE,
142         MONO_GENPARCONSTRAINT_SIZE
143
144 };
145
146 #ifndef DISABLE_REFLECTION_EMIT
147 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
148 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
149 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
150 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
151 static void    ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
153 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
154 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
155 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
156 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
157 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
158 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
159 #endif
160
161 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
162 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
163 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
164 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
165 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
166 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
167 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
170 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
171 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
172 static gboolean is_sre_array (MonoClass *class);
173 static gboolean is_sre_byref (MonoClass *class);
174 static gboolean is_sre_pointer (MonoClass *class);
175 static gboolean is_sre_type_builder (MonoClass *class);
176 static gboolean is_sre_method_builder (MonoClass *class);
177 static gboolean is_sre_ctor_builder (MonoClass *class);
178 static gboolean is_sre_field_builder (MonoClass *class);
179 static gboolean is_sr_mono_method (MonoClass *class);
180 static gboolean is_sr_mono_cmethod (MonoClass *class);
181 static gboolean is_sr_mono_generic_method (MonoClass *class);
182 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_field (MonoClass *class);
184 static gboolean is_sr_mono_property (MonoClass *class);
185 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
186 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
187
188 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
189 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
190 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
191
192 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
193 static void init_type_builder_generics (MonoObject *type);
194
195 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
196 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
197         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
198         __type = mono_reflection_type_resolve_user_types (__type);      \
199         mono_array_set (arr, MonoReflectionType*, index, __type);       \
200 } while (0)
201
202 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
203
204 void
205 mono_reflection_init (void)
206 {
207 }
208
209 static void
210 sigbuffer_init (SigBuffer *buf, int size)
211 {
212         buf->buf = g_malloc (size);
213         buf->p = buf->buf;
214         buf->end = buf->buf + size;
215 }
216
217 static void
218 sigbuffer_make_room (SigBuffer *buf, int size)
219 {
220         if (buf->end - buf->p < size) {
221                 int new_size = buf->end - buf->buf + size + 32;
222                 char *p = g_realloc (buf->buf, new_size);
223                 size = buf->p - buf->buf;
224                 buf->buf = p;
225                 buf->p = p + size;
226                 buf->end = buf->buf + new_size;
227         }
228 }
229
230 static void
231 sigbuffer_add_value (SigBuffer *buf, guint32 val)
232 {
233         sigbuffer_make_room (buf, 6);
234         mono_metadata_encode_value (val, buf->p, &buf->p);
235 }
236
237 static void
238 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
239 {
240         sigbuffer_make_room (buf, 1);
241         buf->p [0] = val;
242         buf->p++;
243 }
244
245 static void
246 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
247 {
248         sigbuffer_make_room (buf, size);
249         memcpy (buf->p, p, size);
250         buf->p += size;
251 }
252
253 static void
254 sigbuffer_free (SigBuffer *buf)
255 {
256         g_free (buf->buf);
257 }
258
259 #ifndef DISABLE_REFLECTION_EMIT
260 /**
261  * mp_g_alloc:
262  *
263  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
264  * from the C heap.
265  */
266 static gpointer
267 image_g_malloc (MonoImage *image, guint size)
268 {
269         if (image)
270                 return mono_image_alloc (image, size);
271         else
272                 return g_malloc (size);
273 }
274 #endif /* !DISABLE_REFLECTION_EMIT */
275
276 /**
277  * image_g_alloc0:
278  *
279  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
280  * from the C heap.
281  */
282 static gpointer
283 image_g_malloc0 (MonoImage *image, guint size)
284 {
285         if (image)
286                 return mono_image_alloc0 (image, size);
287         else
288                 return g_malloc0 (size);
289 }
290
291 #ifndef DISABLE_REFLECTION_EMIT
292 static char*
293 image_strdup (MonoImage *image, const char *s)
294 {
295         if (image)
296                 return mono_image_strdup (image, s);
297         else
298                 return g_strdup (s);
299 }
300 #endif
301
302 #define image_g_new(image,struct_type, n_structs)               \
303     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
304
305 #define image_g_new0(image,struct_type, n_structs)              \
306     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
307
308
309 static void
310 alloc_table (MonoDynamicTable *table, guint nrows)
311 {
312         table->rows = nrows;
313         g_assert (table->columns);
314         if (nrows + 1 >= table->alloc_rows) {
315                 while (nrows + 1 >= table->alloc_rows) {
316                         if (table->alloc_rows == 0)
317                                 table->alloc_rows = 16;
318                         else
319                                 table->alloc_rows *= 2;
320                 }
321
322                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
323         }
324 }
325
326 static void
327 make_room_in_stream (MonoDynamicStream *stream, int size)
328 {
329         if (size <= stream->alloc_size)
330                 return;
331         
332         while (stream->alloc_size <= size) {
333                 if (stream->alloc_size < 4096)
334                         stream->alloc_size = 4096;
335                 else
336                         stream->alloc_size *= 2;
337         }
338         
339         stream->data = g_realloc (stream->data, stream->alloc_size);
340 }
341
342 static guint32
343 string_heap_insert (MonoDynamicStream *sh, const char *str)
344 {
345         guint32 idx;
346         guint32 len;
347         gpointer oldkey, oldval;
348
349         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
350                 return GPOINTER_TO_UINT (oldval);
351
352         len = strlen (str) + 1;
353         idx = sh->index;
354         
355         make_room_in_stream (sh, idx + len);
356
357         /*
358          * We strdup the string even if we already copy them in sh->data
359          * so that the string pointers in the hash remain valid even if
360          * we need to realloc sh->data. We may want to avoid that later.
361          */
362         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
363         memcpy (sh->data + idx, str, len);
364         sh->index += len;
365         return idx;
366 }
367
368 static guint32
369 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
370 {
371         char *name = mono_string_to_utf8 (str);
372         guint32 idx;
373         idx = string_heap_insert (sh, name);
374         g_free (name);
375         return idx;
376 }
377
378 #ifndef DISABLE_REFLECTION_EMIT
379 static void
380 string_heap_init (MonoDynamicStream *sh)
381 {
382         sh->index = 0;
383         sh->alloc_size = 4096;
384         sh->data = g_malloc (4096);
385         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
386         string_heap_insert (sh, "");
387 }
388 #endif
389
390 static guint32
391 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
392 {
393         guint32 idx;
394         
395         make_room_in_stream (stream, stream->index + len);
396         memcpy (stream->data + stream->index, data, len);
397         idx = stream->index;
398         stream->index += len;
399         /* 
400          * align index? Not without adding an additional param that controls it since
401          * we may store a blob value in pieces.
402          */
403         return idx;
404 }
405
406 static guint32
407 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
408 {
409         guint32 idx;
410         
411         make_room_in_stream (stream, stream->index + len);
412         memset (stream->data + stream->index, 0, len);
413         idx = stream->index;
414         stream->index += len;
415         return idx;
416 }
417
418 static void
419 stream_data_align (MonoDynamicStream *stream)
420 {
421         char buf [4] = {0};
422         guint32 count = stream->index % 4;
423
424         /* we assume the stream data will be aligned */
425         if (count)
426                 mono_image_add_stream_data (stream, buf, 4 - count);
427 }
428
429 #ifndef DISABLE_REFLECTION_EMIT
430 static int
431 mono_blob_entry_hash (const char* str)
432 {
433         guint len, h;
434         const char *end;
435         len = mono_metadata_decode_blob_size (str, &str);
436         if (len > 0) {
437                 end = str + len;
438                 h = *str;
439                 for (str += 1; str < end; str++)
440                         h = (h << 5) - h + *str;
441                 return h;
442         } else {
443                 return 0;
444         }
445 }
446
447 static gboolean
448 mono_blob_entry_equal (const char *str1, const char *str2) {
449         int len, len2;
450         const char *end1;
451         const char *end2;
452         len = mono_metadata_decode_blob_size (str1, &end1);
453         len2 = mono_metadata_decode_blob_size (str2, &end2);
454         if (len != len2)
455                 return 0;
456         return memcmp (end1, end2, len) == 0;
457 }
458 #endif
459 static guint32
460 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
461 {
462         guint32 idx;
463         char *copy;
464         gpointer oldkey, oldval;
465
466         copy = g_malloc (s1+s2);
467         memcpy (copy, b1, s1);
468         memcpy (copy + s1, b2, s2);
469         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
470                 g_free (copy);
471                 idx = GPOINTER_TO_UINT (oldval);
472         } else {
473                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
474                 mono_image_add_stream_data (&assembly->blob, b2, s2);
475                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
476         }
477         return idx;
478 }
479
480 static guint32
481 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
482 {
483         char blob_size [8];
484         char *b = blob_size;
485         guint32 size = buf->p - buf->buf;
486         /* store length */
487         g_assert (size <= (buf->end - buf->buf));
488         mono_metadata_encode_value (size, b, &b);
489         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
490 }
491
492 /*
493  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
494  * dest may be misaligned.
495  */
496 static void
497 swap_with_size (char *dest, const char* val, int len, int nelem) {
498 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
499         int elem;
500
501         for (elem = 0; elem < nelem; ++elem) {
502                 switch (len) {
503                 case 1:
504                         *dest = *val;
505                         break;
506                 case 2:
507                         dest [0] = val [1];
508                         dest [1] = val [0];
509                         break;
510                 case 4:
511                         dest [0] = val [3];
512                         dest [1] = val [2];
513                         dest [2] = val [1];
514                         dest [3] = val [0];
515                         break;
516                 case 8:
517                         dest [0] = val [7];
518                         dest [1] = val [6];
519                         dest [2] = val [5];
520                         dest [3] = val [4];
521                         dest [4] = val [3];
522                         dest [5] = val [2];
523                         dest [6] = val [1];
524                         dest [7] = val [0];
525                         break;
526                 default:
527                         g_assert_not_reached ();
528                 }
529                 dest += len;
530                 val += len;
531         }
532 #else
533         memcpy (dest, val, len * nelem);
534 #endif
535 }
536
537 static guint32
538 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
539 {
540         char blob_size [64];
541         char *b = blob_size;
542         guint32 idx = 0, len;
543
544         len = str->length * 2;
545         mono_metadata_encode_value (len, b, &b);
546 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
547         {
548                 char *swapped = g_malloc (2 * mono_string_length (str));
549                 const char *p = (const char*)mono_string_chars (str);
550
551                 swap_with_size (swapped, p, 2, mono_string_length (str));
552                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
553                 g_free (swapped);
554         }
555 #else
556         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
557 #endif
558         return idx;
559 }
560
561 #ifndef DISABLE_REFLECTION_EMIT
562 static MonoClass *
563 default_class_from_mono_type (MonoType *type)
564 {
565         switch (type->type) {
566         case MONO_TYPE_OBJECT:
567                 return mono_defaults.object_class;
568         case MONO_TYPE_VOID:
569                 return mono_defaults.void_class;
570         case MONO_TYPE_BOOLEAN:
571                 return mono_defaults.boolean_class;
572         case MONO_TYPE_CHAR:
573                 return mono_defaults.char_class;
574         case MONO_TYPE_I1:
575                 return mono_defaults.sbyte_class;
576         case MONO_TYPE_U1:
577                 return mono_defaults.byte_class;
578         case MONO_TYPE_I2:
579                 return mono_defaults.int16_class;
580         case MONO_TYPE_U2:
581                 return mono_defaults.uint16_class;
582         case MONO_TYPE_I4:
583                 return mono_defaults.int32_class;
584         case MONO_TYPE_U4:
585                 return mono_defaults.uint32_class;
586         case MONO_TYPE_I:
587                 return mono_defaults.int_class;
588         case MONO_TYPE_U:
589                 return mono_defaults.uint_class;
590         case MONO_TYPE_I8:
591                 return mono_defaults.int64_class;
592         case MONO_TYPE_U8:
593                 return mono_defaults.uint64_class;
594         case MONO_TYPE_R4:
595                 return mono_defaults.single_class;
596         case MONO_TYPE_R8:
597                 return mono_defaults.double_class;
598         case MONO_TYPE_STRING:
599                 return mono_defaults.string_class;
600         default:
601                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
602                 g_assert_not_reached ();
603         }
604         
605         return NULL;
606 }
607 #endif
608
609 /*
610  * mono_class_get_ref_info:
611  *
612  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
613  */
614 gpointer
615 mono_class_get_ref_info (MonoClass *klass)
616 {
617         if (klass->ref_info_handle == 0)
618                 return NULL;
619         else
620                 return mono_gchandle_get_target (klass->ref_info_handle);
621 }
622
623 void
624 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
625 {
626         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
627         g_assert (klass->ref_info_handle != 0);
628 }
629
630 void
631 mono_class_free_ref_info (MonoClass *klass)
632 {
633         if (klass->ref_info_handle) {
634                 mono_gchandle_free (klass->ref_info_handle);
635                 klass->ref_info_handle = 0;
636         }
637 }
638
639 static void
640 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
641 {
642         int i;
643         MonoGenericInst *class_inst;
644         MonoClass *klass;
645
646         g_assert (gclass);
647
648         class_inst = gclass->context.class_inst;
649
650         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
651         klass = gclass->container_class;
652         sigbuffer_add_value (buf, klass->byval_arg.type);
653         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
654
655         sigbuffer_add_value (buf, class_inst->type_argc);
656         for (i = 0; i < class_inst->type_argc; ++i)
657                 encode_type (assembly, class_inst->type_argv [i], buf);
658
659 }
660
661 static void
662 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
663 {
664         if (!type) {
665                 g_assert_not_reached ();
666                 return;
667         }
668                 
669         if (type->byref)
670                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
671
672         switch (type->type){
673         case MONO_TYPE_VOID:
674         case MONO_TYPE_BOOLEAN:
675         case MONO_TYPE_CHAR:
676         case MONO_TYPE_I1:
677         case MONO_TYPE_U1:
678         case MONO_TYPE_I2:
679         case MONO_TYPE_U2:
680         case MONO_TYPE_I4:
681         case MONO_TYPE_U4:
682         case MONO_TYPE_I8:
683         case MONO_TYPE_U8:
684         case MONO_TYPE_R4:
685         case MONO_TYPE_R8:
686         case MONO_TYPE_I:
687         case MONO_TYPE_U:
688         case MONO_TYPE_STRING:
689         case MONO_TYPE_OBJECT:
690         case MONO_TYPE_TYPEDBYREF:
691                 sigbuffer_add_value (buf, type->type);
692                 break;
693         case MONO_TYPE_PTR:
694                 sigbuffer_add_value (buf, type->type);
695                 encode_type (assembly, type->data.type, buf);
696                 break;
697         case MONO_TYPE_SZARRAY:
698                 sigbuffer_add_value (buf, type->type);
699                 encode_type (assembly, &type->data.klass->byval_arg, buf);
700                 break;
701         case MONO_TYPE_VALUETYPE:
702         case MONO_TYPE_CLASS: {
703                 MonoClass *k = mono_class_from_mono_type (type);
704
705                 if (k->generic_container) {
706                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
707                         encode_generic_class (assembly, gclass, buf);
708                 } else {
709                         /*
710                          * Make sure we use the correct type.
711                          */
712                         sigbuffer_add_value (buf, k->byval_arg.type);
713                         /*
714                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
715                          * otherwise two typerefs could point to the same type, leading to
716                          * verification errors.
717                          */
718                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
719                 }
720                 break;
721         }
722         case MONO_TYPE_ARRAY:
723                 sigbuffer_add_value (buf, type->type);
724                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
725                 sigbuffer_add_value (buf, type->data.array->rank);
726                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
727                 sigbuffer_add_value (buf, 0);
728                 break;
729         case MONO_TYPE_GENERICINST:
730                 encode_generic_class (assembly, type->data.generic_class, buf);
731                 break;
732         case MONO_TYPE_VAR:
733         case MONO_TYPE_MVAR:
734                 sigbuffer_add_value (buf, type->type);
735                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
736                 break;
737         default:
738                 g_error ("need to encode type %x", type->type);
739         }
740 }
741
742 static void
743 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
744 {
745         if (!type) {
746                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
747                 return;
748         }
749
750         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
751 }
752
753 static void
754 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
755 {
756         int i;
757
758         if (modreq) {
759                 for (i = 0; i < mono_array_length (modreq); ++i) {
760                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
761                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
762                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
763                 }
764         }
765         if (modopt) {
766                 for (i = 0; i < mono_array_length (modopt); ++i) {
767                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
768                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
769                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
770                 }
771         }
772 }
773
774 #ifndef DISABLE_REFLECTION_EMIT
775 static guint32
776 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
777 {
778         SigBuffer buf;
779         int i;
780         guint32 nparams =  sig->param_count;
781         guint32 idx;
782
783         if (!assembly->save)
784                 return 0;
785
786         sigbuffer_init (&buf, 32);
787         /*
788          * FIXME: vararg, explicit_this, differenc call_conv values...
789          */
790         idx = sig->call_convention;
791         if (sig->hasthis)
792                 idx |= 0x20; /* hasthis */
793         if (sig->generic_param_count)
794                 idx |= 0x10; /* generic */
795         sigbuffer_add_byte (&buf, idx);
796         if (sig->generic_param_count)
797                 sigbuffer_add_value (&buf, sig->generic_param_count);
798         sigbuffer_add_value (&buf, nparams);
799         encode_type (assembly, sig->ret, &buf);
800         for (i = 0; i < nparams; ++i) {
801                 if (i == sig->sentinelpos)
802                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
803                 encode_type (assembly, sig->params [i], &buf);
804         }
805         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
806         sigbuffer_free (&buf);
807         return idx;
808 }
809 #endif
810
811 static guint32
812 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
813 {
814         /*
815          * FIXME: reuse code from method_encode_signature().
816          */
817         SigBuffer buf;
818         int i;
819         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
820         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
821         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
822         guint32 idx;
823
824         sigbuffer_init (&buf, 32);
825         /* LAMESPEC: all the call conv spec is foobared */
826         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
827         if (mb->call_conv & 2)
828                 idx |= 0x5; /* vararg */
829         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
830                 idx |= 0x20; /* hasthis */
831         if (ngparams)
832                 idx |= 0x10; /* generic */
833         sigbuffer_add_byte (&buf, idx);
834         if (ngparams)
835                 sigbuffer_add_value (&buf, ngparams);
836         sigbuffer_add_value (&buf, nparams + notypes);
837         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
838         encode_reflection_type (assembly, mb->rtype, &buf);
839         for (i = 0; i < nparams; ++i) {
840                 MonoArray *modreq = NULL;
841                 MonoArray *modopt = NULL;
842                 MonoReflectionType *pt;
843
844                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
845                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
846                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
847                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
848                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
849                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
850                 encode_reflection_type (assembly, pt, &buf);
851         }
852         if (notypes)
853                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
854         for (i = 0; i < notypes; ++i) {
855                 MonoReflectionType *pt;
856
857                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
858                 encode_reflection_type (assembly, pt, &buf);
859         }
860
861         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
862         sigbuffer_free (&buf);
863         return idx;
864 }
865
866 static guint32
867 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
868 {
869         MonoDynamicTable *table;
870         guint32 *values;
871         guint32 idx, sig_idx;
872         guint nl = mono_array_length (ilgen->locals);
873         SigBuffer buf;
874         int i;
875
876         sigbuffer_init (&buf, 32);
877         sigbuffer_add_value (&buf, 0x07);
878         sigbuffer_add_value (&buf, nl);
879         for (i = 0; i < nl; ++i) {
880                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
881                 
882                 if (lb->is_pinned)
883                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
884                 
885                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
886         }
887         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
888         sigbuffer_free (&buf);
889
890         if (assembly->standalonesig_cache == NULL)
891                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
892         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
893         if (idx)
894                 return idx;
895
896         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
897         idx = table->next_idx ++;
898         table->rows ++;
899         alloc_table (table, table->rows);
900         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
901
902         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
903
904         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
905
906         return idx;
907 }
908
909 static guint32
910 method_count_clauses (MonoReflectionILGen *ilgen)
911 {
912         guint32 num_clauses = 0;
913         int i;
914
915         MonoILExceptionInfo *ex_info;
916         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
917                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
918                 if (ex_info->handlers)
919                         num_clauses += mono_array_length (ex_info->handlers);
920                 else
921                         num_clauses++;
922         }
923
924         return num_clauses;
925 }
926
927 #ifndef DISABLE_REFLECTION_EMIT
928 static MonoExceptionClause*
929 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
930 {
931         MonoExceptionClause *clauses;
932         MonoExceptionClause *clause;
933         MonoILExceptionInfo *ex_info;
934         MonoILExceptionBlock *ex_block;
935         guint32 finally_start;
936         int i, j, clause_index;;
937
938         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
939
940         clause_index = 0;
941         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
942                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
943                 finally_start = ex_info->start + ex_info->len;
944                 if (!ex_info->handlers)
945                         continue;
946                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
947                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
948                         clause = &(clauses [clause_index]);
949
950                         clause->flags = ex_block->type;
951                         clause->try_offset = ex_info->start;
952
953                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
954                                 clause->try_len = finally_start - ex_info->start;
955                         else
956                                 clause->try_len = ex_info->len;
957                         clause->handler_offset = ex_block->start;
958                         clause->handler_len = ex_block->len;
959                         if (ex_block->extype) {
960                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
961                         } else {
962                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
963                                         clause->data.filter_offset = ex_block->filter_offset;
964                                 else
965                                         clause->data.filter_offset = 0;
966                         }
967                         finally_start = ex_block->start + ex_block->len;
968
969                         clause_index ++;
970                 }
971         }
972
973         return clauses;
974 }
975 #endif /* !DISABLE_REFLECTION_EMIT */
976
977 static guint32
978 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
979 {
980         char flags = 0;
981         guint32 idx;
982         guint32 code_size;
983         gint32 max_stack, i;
984         gint32 num_locals = 0;
985         gint32 num_exception = 0;
986         gint maybe_small;
987         guint32 fat_flags;
988         char fat_header [12];
989         guint32 int_value;
990         guint16 short_value;
991         guint32 local_sig = 0;
992         guint32 header_size = 12;
993         MonoArray *code;
994
995         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
996                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
997                 return 0;
998
999         /*if (mb->name)
1000                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1001         if (mb->ilgen) {
1002                 code = mb->ilgen->code;
1003                 code_size = mb->ilgen->code_len;
1004                 max_stack = mb->ilgen->max_stack;
1005                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1006                 if (mb->ilgen->ex_handlers)
1007                         num_exception = method_count_clauses (mb->ilgen);
1008         } else {
1009                 code = mb->code;
1010                 if (code == NULL){
1011                         char *name = mono_string_to_utf8 (mb->name);
1012                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1013                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1014                         g_free (str);
1015                         g_free (name);
1016                         mono_raise_exception (exception);
1017                 }
1018
1019                 code_size = mono_array_length (code);
1020                 max_stack = 8; /* we probably need to run a verifier on the code... */
1021         }
1022
1023         stream_data_align (&assembly->code);
1024
1025         /* check for exceptions, maxstack, locals */
1026         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1027         if (maybe_small) {
1028                 if (code_size < 64 && !(code_size & 1)) {
1029                         flags = (code_size << 2) | 0x2;
1030                 } else if (code_size < 32 && (code_size & 1)) {
1031                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1032                 } else {
1033                         goto fat_header;
1034                 }
1035                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1036                 /* add to the fixup todo list */
1037                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1038                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1039                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1040                 return assembly->text_rva + idx;
1041         } 
1042 fat_header:
1043         if (num_locals)
1044                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1045         /* 
1046          * FIXME: need to set also the header size in fat_flags.
1047          * (and more sects and init locals flags)
1048          */
1049         fat_flags =  0x03;
1050         if (num_exception)
1051                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1052         if (mb->init_locals)
1053                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1054         fat_header [0] = fat_flags;
1055         fat_header [1] = (header_size / 4 ) << 4;
1056         short_value = GUINT16_TO_LE (max_stack);
1057         memcpy (fat_header + 2, &short_value, 2);
1058         int_value = GUINT32_TO_LE (code_size);
1059         memcpy (fat_header + 4, &int_value, 4);
1060         int_value = GUINT32_TO_LE (local_sig);
1061         memcpy (fat_header + 8, &int_value, 4);
1062         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1063         /* add to the fixup todo list */
1064         if (mb->ilgen && mb->ilgen->num_token_fixups)
1065                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1066         
1067         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1068         if (num_exception) {
1069                 unsigned char sheader [4];
1070                 MonoILExceptionInfo * ex_info;
1071                 MonoILExceptionBlock * ex_block;
1072                 int j;
1073
1074                 stream_data_align (&assembly->code);
1075                 /* always use fat format for now */
1076                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1077                 num_exception *= 6 * sizeof (guint32);
1078                 num_exception += 4; /* include the size of the header */
1079                 sheader [1] = num_exception & 0xff;
1080                 sheader [2] = (num_exception >> 8) & 0xff;
1081                 sheader [3] = (num_exception >> 16) & 0xff;
1082                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1083                 /* fat header, so we are already aligned */
1084                 /* reverse order */
1085                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1086                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1087                         if (ex_info->handlers) {
1088                                 int finally_start = ex_info->start + ex_info->len;
1089                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1090                                         guint32 val;
1091                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1092                                         /* the flags */
1093                                         val = GUINT32_TO_LE (ex_block->type);
1094                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1095                                         /* try offset */
1096                                         val = GUINT32_TO_LE (ex_info->start);
1097                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1098                                         /* need fault, too, probably */
1099                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1100                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1101                                         else
1102                                                 val = GUINT32_TO_LE (ex_info->len);
1103                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1104                                         /* handler offset */
1105                                         val = GUINT32_TO_LE (ex_block->start);
1106                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1107                                         /* handler len */
1108                                         val = GUINT32_TO_LE (ex_block->len);
1109                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1110                                         finally_start = ex_block->start + ex_block->len;
1111                                         if (ex_block->extype) {
1112                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1113                                         } else {
1114                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1115                                                         val = ex_block->filter_offset;
1116                                                 else
1117                                                         val = 0;
1118                                         }
1119                                         val = GUINT32_TO_LE (val);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /*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", 
1122                                                         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);*/
1123                                 }
1124                         } else {
1125                                 g_error ("No clauses for ex info block %d", i);
1126                         }
1127                 }
1128         }
1129         return assembly->text_rva + idx;
1130 }
1131
1132 static guint32
1133 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1134 {
1135         int i;
1136         MonoDynamicTable *table;
1137         guint32 *values;
1138         
1139         table = &assembly->tables [table_idx];
1140
1141         g_assert (col < table->columns);
1142
1143         values = table->values + table->columns;
1144         for (i = 1; i <= table->rows; ++i) {
1145                 if (values [col] == token)
1146                         return i;
1147                 values += table->columns;
1148         }
1149         return 0;
1150 }
1151
1152 /*
1153  * LOCKING: Acquires the loader lock. 
1154  */
1155 static MonoCustomAttrInfo*
1156 lookup_custom_attr (MonoImage *image, gpointer member)
1157 {
1158         MonoCustomAttrInfo* res;
1159
1160         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1161
1162         if (!res)
1163                 return NULL;
1164
1165         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1166         res->cached = 0;
1167         return res;
1168 }
1169
1170 static gboolean
1171 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1172 {
1173         /* FIXME: Need to do more checks */
1174         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1175                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1176
1177                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1178                         return FALSE;
1179         }
1180
1181         return TRUE;
1182 }
1183
1184 static MonoCustomAttrInfo*
1185 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1186 {
1187         int i, index, count, not_visible;
1188         MonoCustomAttrInfo *ainfo;
1189         MonoReflectionCustomAttr *cattr;
1190
1191         if (!cattrs)
1192                 return NULL;
1193         /* FIXME: check in assembly the Run flag is set */
1194
1195         count = mono_array_length (cattrs);
1196
1197         /* Skip nonpublic attributes since MS.NET seems to do the same */
1198         /* FIXME: This needs to be done more globally */
1199         not_visible = 0;
1200         for (i = 0; i < count; ++i) {
1201                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1202                 if (!custom_attr_visible (image, cattr))
1203                         not_visible ++;
1204         }
1205         count -= not_visible;
1206
1207         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1208
1209         ainfo->image = image;
1210         ainfo->num_attrs = count;
1211         ainfo->cached = alloc_img != NULL;
1212         index = 0;
1213         for (i = 0; i < count; ++i) {
1214                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1215                 if (custom_attr_visible (image, cattr)) {
1216                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1217                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1218                         ainfo->attrs [index].ctor = cattr->ctor->method;
1219                         ainfo->attrs [index].data = saved;
1220                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1221                         index ++;
1222                 }
1223         }
1224
1225         return ainfo;
1226 }
1227
1228 #ifndef DISABLE_REFLECTION_EMIT
1229 /*
1230  * LOCKING: Acquires the loader lock. 
1231  */
1232 static void
1233 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1234 {
1235         MonoCustomAttrInfo *ainfo, *tmp;
1236
1237         if (!cattrs || !mono_array_length (cattrs))
1238                 return;
1239
1240         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1241
1242         mono_loader_lock ();
1243         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1244         if (tmp)
1245                 mono_custom_attrs_free (tmp);
1246         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1247         mono_loader_unlock ();
1248
1249 }
1250 #endif
1251
1252 void
1253 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1254 {
1255         if (!ainfo->cached)
1256                 g_free (ainfo);
1257 }
1258
1259 /*
1260  * idx is the table index of the object
1261  * type is one of MONO_CUSTOM_ATTR_*
1262  */
1263 static void
1264 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1265 {
1266         MonoDynamicTable *table;
1267         MonoReflectionCustomAttr *cattr;
1268         guint32 *values;
1269         guint32 count, i, token;
1270         char blob_size [6];
1271         char *p = blob_size;
1272         
1273         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1274         if (!cattrs)
1275                 return;
1276         count = mono_array_length (cattrs);
1277         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1278         table->rows += count;
1279         alloc_table (table, table->rows);
1280         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1281         idx <<= MONO_CUSTOM_ATTR_BITS;
1282         idx |= type;
1283         for (i = 0; i < count; ++i) {
1284                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1285                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1286                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1287                 type = mono_metadata_token_index (token);
1288                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1289                 switch (mono_metadata_token_table (token)) {
1290                 case MONO_TABLE_METHOD:
1291                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1292                         break;
1293                 case MONO_TABLE_MEMBERREF:
1294                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1295                         break;
1296                 default:
1297                         g_warning ("got wrong token in custom attr");
1298                         continue;
1299                 }
1300                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1301                 p = blob_size;
1302                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1303                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1304                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1305                 values += MONO_CUSTOM_ATTR_SIZE;
1306                 ++table->next_idx;
1307         }
1308 }
1309
1310 static void
1311 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1312 {
1313         MonoDynamicTable *table;
1314         guint32 *values;
1315         guint32 count, i, idx;
1316         MonoReflectionPermissionSet *perm;
1317
1318         if (!permissions)
1319                 return;
1320
1321         count = mono_array_length (permissions);
1322         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1323         table->rows += count;
1324         alloc_table (table, table->rows);
1325
1326         for (i = 0; i < mono_array_length (permissions); ++i) {
1327                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1328
1329                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1330
1331                 idx = mono_metadata_token_index (parent_token);
1332                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1333                 switch (mono_metadata_token_table (parent_token)) {
1334                 case MONO_TABLE_TYPEDEF:
1335                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1336                         break;
1337                 case MONO_TABLE_METHOD:
1338                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1339                         break;
1340                 case MONO_TABLE_ASSEMBLY:
1341                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1342                         break;
1343                 default:
1344                         g_assert_not_reached ();
1345                 }
1346
1347                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1348                 values [MONO_DECL_SECURITY_PARENT] = idx;
1349                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1350
1351                 ++table->next_idx;
1352         }
1353 }
1354
1355 /*
1356  * Fill in the MethodDef and ParamDef tables for a method.
1357  * This is used for both normal methods and constructors.
1358  */
1359 static void
1360 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1361 {
1362         MonoDynamicTable *table;
1363         guint32 *values;
1364         guint i, count;
1365
1366         /* room in this table is already allocated */
1367         table = &assembly->tables [MONO_TABLE_METHOD];
1368         *mb->table_idx = table->next_idx ++;
1369         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1370         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1371         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1372         values [MONO_METHOD_FLAGS] = mb->attrs;
1373         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1374         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1375         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1376         
1377         table = &assembly->tables [MONO_TABLE_PARAM];
1378         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1379
1380         mono_image_add_decl_security (assembly, 
1381                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1382
1383         if (mb->pinfo) {
1384                 MonoDynamicTable *mtable;
1385                 guint32 *mvalues;
1386                 
1387                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1388                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1389                 
1390                 count = 0;
1391                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1392                         if (mono_array_get (mb->pinfo, gpointer, i))
1393                                 count++;
1394                 }
1395                 table->rows += count;
1396                 alloc_table (table, table->rows);
1397                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1398                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1399                         MonoReflectionParamBuilder *pb;
1400                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1401                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1402                                 values [MONO_PARAM_SEQUENCE] = i;
1403                                 if (pb->name != NULL) {
1404                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1405                                 } else {
1406                                         values [MONO_PARAM_NAME] = 0;
1407                                 }
1408                                 values += MONO_PARAM_SIZE;
1409                                 if (pb->marshal_info) {
1410                                         mtable->rows++;
1411                                         alloc_table (mtable, mtable->rows);
1412                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1413                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1414                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1415                                 }
1416                                 pb->table_idx = table->next_idx++;
1417                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1418                                         guint32 field_type = 0;
1419                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1420                                         mtable->rows ++;
1421                                         alloc_table (mtable, mtable->rows);
1422                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1423                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1424                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1425                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1426                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1427                                 }
1428                         }
1429                 }
1430         }
1431 }
1432
1433 #ifndef DISABLE_REFLECTION_EMIT
1434 static void
1435 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1436 {
1437         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1438
1439         rmb->ilgen = mb->ilgen;
1440         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1441         rmb->parameters = mb->parameters;
1442         rmb->generic_params = mb->generic_params;
1443         rmb->generic_container = mb->generic_container;
1444         rmb->opt_types = NULL;
1445         rmb->pinfo = mb->pinfo;
1446         rmb->attrs = mb->attrs;
1447         rmb->iattrs = mb->iattrs;
1448         rmb->call_conv = mb->call_conv;
1449         rmb->code = mb->code;
1450         rmb->type = mb->type;
1451         rmb->name = mb->name;
1452         rmb->table_idx = &mb->table_idx;
1453         rmb->init_locals = mb->init_locals;
1454         rmb->skip_visibility = FALSE;
1455         rmb->return_modreq = mb->return_modreq;
1456         rmb->return_modopt = mb->return_modopt;
1457         rmb->param_modreq = mb->param_modreq;
1458         rmb->param_modopt = mb->param_modopt;
1459         rmb->permissions = mb->permissions;
1460         rmb->mhandle = mb->mhandle;
1461         rmb->nrefs = 0;
1462         rmb->refs = NULL;
1463
1464         if (mb->dll) {
1465                 rmb->charset = mb->charset;
1466                 rmb->extra_flags = mb->extra_flags;
1467                 rmb->native_cc = mb->native_cc;
1468                 rmb->dllentry = mb->dllentry;
1469                 rmb->dll = mb->dll;
1470         }
1471 }
1472
1473 static void
1474 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1475 {
1476         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1477
1478         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1479
1480         rmb->ilgen = mb->ilgen;
1481         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1482         rmb->parameters = mb->parameters;
1483         rmb->generic_params = NULL;
1484         rmb->generic_container = NULL;
1485         rmb->opt_types = NULL;
1486         rmb->pinfo = mb->pinfo;
1487         rmb->attrs = mb->attrs;
1488         rmb->iattrs = mb->iattrs;
1489         rmb->call_conv = mb->call_conv;
1490         rmb->code = NULL;
1491         rmb->type = mb->type;
1492         rmb->name = mono_string_new (mono_domain_get (), name);
1493         rmb->table_idx = &mb->table_idx;
1494         rmb->init_locals = mb->init_locals;
1495         rmb->skip_visibility = FALSE;
1496         rmb->return_modreq = NULL;
1497         rmb->return_modopt = NULL;
1498         rmb->param_modreq = mb->param_modreq;
1499         rmb->param_modopt = mb->param_modopt;
1500         rmb->permissions = mb->permissions;
1501         rmb->mhandle = mb->mhandle;
1502         rmb->nrefs = 0;
1503         rmb->refs = NULL;
1504 }
1505
1506 static void
1507 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1508 {
1509         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1510
1511         rmb->ilgen = mb->ilgen;
1512         rmb->rtype = mb->rtype;
1513         rmb->parameters = mb->parameters;
1514         rmb->generic_params = NULL;
1515         rmb->generic_container = NULL;
1516         rmb->opt_types = NULL;
1517         rmb->pinfo = NULL;
1518         rmb->attrs = mb->attrs;
1519         rmb->iattrs = 0;
1520         rmb->call_conv = mb->call_conv;
1521         rmb->code = NULL;
1522         rmb->type = (MonoObject *) mb->owner;
1523         rmb->name = mb->name;
1524         rmb->table_idx = NULL;
1525         rmb->init_locals = mb->init_locals;
1526         rmb->skip_visibility = mb->skip_visibility;
1527         rmb->return_modreq = NULL;
1528         rmb->return_modopt = NULL;
1529         rmb->param_modreq = NULL;
1530         rmb->param_modopt = NULL;
1531         rmb->permissions = NULL;
1532         rmb->mhandle = mb->mhandle;
1533         rmb->nrefs = 0;
1534         rmb->refs = NULL;
1535 }       
1536 #endif
1537
1538 static void
1539 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1540 {
1541         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1542         MonoDynamicTable *table;
1543         guint32 *values;
1544         guint32 tok;
1545
1546         if (!mb->override_method)
1547                 return;
1548
1549         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1550         table->rows ++;
1551         alloc_table (table, table->rows);
1552         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1553         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1554         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1555
1556         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1557         switch (mono_metadata_token_table (tok)) {
1558         case MONO_TABLE_MEMBERREF:
1559                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1560                 break;
1561         case MONO_TABLE_METHOD:
1562                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1563                 break;
1564         default:
1565                 g_assert_not_reached ();
1566         }
1567         values [MONO_METHODIMPL_DECLARATION] = tok;
1568 }
1569
1570 #ifndef DISABLE_REFLECTION_EMIT
1571 static void
1572 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1573 {
1574         MonoDynamicTable *table;
1575         guint32 *values;
1576         ReflectionMethodBuilder rmb;
1577         int i;
1578
1579         reflection_methodbuilder_from_method_builder (&rmb, mb);
1580
1581         mono_image_basic_method (&rmb, assembly);
1582         mb->table_idx = *rmb.table_idx;
1583
1584         if (mb->dll) { /* It's a P/Invoke method */
1585                 guint32 moduleref;
1586                 /* map CharSet values to on-disk values */
1587                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1588                 int extra_flags = mb->extra_flags;
1589                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1590                 table->rows ++;
1591                 alloc_table (table, table->rows);
1592                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1593                 
1594                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1595                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1596                 if (mb->dllentry)
1597                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1598                 else
1599                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1600                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1601                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1602                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1603                         table->rows ++;
1604                         alloc_table (table, table->rows);
1605                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1606                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1607                 }
1608         }
1609
1610         if (mb->generic_params) {
1611                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1612                 table->rows += mono_array_length (mb->generic_params);
1613                 alloc_table (table, table->rows);
1614                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1615                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1616
1617                         mono_image_get_generic_param_info (
1618                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1619                 }
1620         }
1621
1622 }
1623
1624 static void
1625 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1626 {
1627         ReflectionMethodBuilder rmb;
1628
1629         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1630
1631         mono_image_basic_method (&rmb, assembly);
1632         mb->table_idx = *rmb.table_idx;
1633 }
1634 #endif
1635
1636 static char*
1637 type_get_fully_qualified_name (MonoType *type)
1638 {
1639         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1640 }
1641
1642 static char*
1643 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1644         MonoClass *klass;
1645         MonoAssembly *ta;
1646
1647         klass = mono_class_from_mono_type (type);
1648         if (!klass) 
1649                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1650         ta = klass->image->assembly;
1651         if (ta->dynamic || (ta == ass)) {
1652                 if (klass->generic_class || klass->generic_container)
1653                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1654                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1655                 else
1656                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1657         }
1658
1659         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1660 }
1661
1662 #ifndef DISABLE_REFLECTION_EMIT
1663 /*field_image is the image to which the eventual custom mods have been encoded against*/
1664 static guint32
1665 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1666 {
1667         SigBuffer buf;
1668         guint32 idx, i, token;
1669
1670         if (!assembly->save)
1671                 return 0;
1672
1673         sigbuffer_init (&buf, 32);
1674         
1675         sigbuffer_add_value (&buf, 0x06);
1676         /* encode custom attributes before the type */
1677         if (type->num_mods) {
1678                 for (i = 0; i < type->num_mods; ++i) {
1679                         if (field_image) {
1680                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1681                                 g_assert (class);
1682                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1683                         } else {
1684                                 token = type->modifiers [i].token;
1685                         }
1686
1687                         if (type->modifiers [i].required)
1688                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1689                         else
1690                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1691
1692                         sigbuffer_add_value (&buf, token);
1693                 }
1694         }
1695         encode_type (assembly, type, &buf);
1696         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1697         sigbuffer_free (&buf);
1698         return idx;
1699 }
1700 #endif
1701
1702 static guint32
1703 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1704 {
1705         SigBuffer buf;
1706         guint32 idx;
1707         guint32 typespec = 0;
1708         MonoType *type;
1709         MonoClass *class;
1710
1711         init_type_builder_generics (fb->type);
1712
1713         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1714         class = mono_class_from_mono_type (type);
1715
1716         sigbuffer_init (&buf, 32);
1717         
1718         sigbuffer_add_value (&buf, 0x06);
1719         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1720         /* encode custom attributes before the type */
1721
1722         if (class->generic_container)
1723                 typespec = create_typespec (assembly, type);
1724
1725         if (typespec) {
1726                 MonoGenericClass *gclass;
1727                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1728                 encode_generic_class (assembly, gclass, &buf);
1729         } else {
1730                 encode_type (assembly, type, &buf);
1731         }
1732         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1733         sigbuffer_free (&buf);
1734         return idx;
1735 }
1736
1737 static guint32
1738 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1739         char blob_size [64];
1740         char *b = blob_size;
1741         char *p, *box_val;
1742         char* buf;
1743         guint32 idx = 0, len = 0, dummy = 0;
1744 #ifdef ARM_FPU_FPA
1745 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1746         guint32 fpa_double [2];
1747         guint32 *fpa_p;
1748 #endif
1749 #endif
1750         
1751         p = buf = g_malloc (64);
1752         if (!val) {
1753                 *ret_type = MONO_TYPE_CLASS;
1754                 len = 4;
1755                 box_val = (char*)&dummy;
1756         } else {
1757                 box_val = ((char*)val) + sizeof (MonoObject);
1758                 *ret_type = val->vtable->klass->byval_arg.type;
1759         }
1760 handle_enum:
1761         switch (*ret_type) {
1762         case MONO_TYPE_BOOLEAN:
1763         case MONO_TYPE_U1:
1764         case MONO_TYPE_I1:
1765                 len = 1;
1766                 break;
1767         case MONO_TYPE_CHAR:
1768         case MONO_TYPE_U2:
1769         case MONO_TYPE_I2:
1770                 len = 2;
1771                 break;
1772         case MONO_TYPE_U4:
1773         case MONO_TYPE_I4:
1774         case MONO_TYPE_R4:
1775                 len = 4;
1776                 break;
1777         case MONO_TYPE_U8:
1778         case MONO_TYPE_I8:
1779                 len = 8;
1780                 break;
1781         case MONO_TYPE_R8:
1782                 len = 8;
1783 #ifdef ARM_FPU_FPA
1784 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1785                 fpa_p = (guint32*)box_val;
1786                 fpa_double [0] = fpa_p [1];
1787                 fpa_double [1] = fpa_p [0];
1788                 box_val = (char*)fpa_double;
1789 #endif
1790 #endif
1791                 break;
1792         case MONO_TYPE_VALUETYPE: {
1793                 MonoClass *klass = val->vtable->klass;
1794                 
1795                 if (klass->enumtype) {
1796                         *ret_type = mono_class_enum_basetype (klass)->type;
1797                         goto handle_enum;
1798                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1799                         len = 8;
1800                 } else 
1801                         g_error ("we can't encode valuetypes, we should have never reached this line");
1802                 break;
1803         }
1804         case MONO_TYPE_CLASS:
1805                 break;
1806         case MONO_TYPE_STRING: {
1807                 MonoString *str = (MonoString*)val;
1808                 /* there is no signature */
1809                 len = str->length * 2;
1810                 mono_metadata_encode_value (len, b, &b);
1811 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1812                 {
1813                         char *swapped = g_malloc (2 * mono_string_length (str));
1814                         const char *p = (const char*)mono_string_chars (str);
1815
1816                         swap_with_size (swapped, p, 2, mono_string_length (str));
1817                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1818                         g_free (swapped);
1819                 }
1820 #else
1821                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1822 #endif
1823
1824                 g_free (buf);
1825                 return idx;
1826         }
1827         case MONO_TYPE_GENERICINST:
1828                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1829                 goto handle_enum;
1830         default:
1831                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1832         }
1833
1834         /* there is no signature */
1835         mono_metadata_encode_value (len, b, &b);
1836 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1837         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1838         swap_with_size (blob_size, box_val, len, 1);
1839         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1840 #else
1841         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1842 #endif
1843
1844         g_free (buf);
1845         return idx;
1846 }
1847
1848 static guint32
1849 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1850         char *str;
1851         SigBuffer buf;
1852         guint32 idx, len;
1853
1854         sigbuffer_init (&buf, 32);
1855
1856         sigbuffer_add_value (&buf, minfo->type);
1857
1858         switch (minfo->type) {
1859         case MONO_NATIVE_BYVALTSTR:
1860         case MONO_NATIVE_BYVALARRAY:
1861                 sigbuffer_add_value (&buf, minfo->count);
1862                 break;
1863         case MONO_NATIVE_LPARRAY:
1864                 if (minfo->eltype || minfo->has_size) {
1865                         sigbuffer_add_value (&buf, minfo->eltype);
1866                         if (minfo->has_size) {
1867                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1868                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1869
1870                                 /* LAMESPEC: ElemMult is undocumented */
1871                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1872                         }
1873                 }
1874                 break;
1875         case MONO_NATIVE_SAFEARRAY:
1876                 if (minfo->eltype)
1877                         sigbuffer_add_value (&buf, minfo->eltype);
1878                 break;
1879         case MONO_NATIVE_CUSTOM:
1880                 if (minfo->guid) {
1881                         str = mono_string_to_utf8 (minfo->guid);
1882                         len = strlen (str);
1883                         sigbuffer_add_value (&buf, len);
1884                         sigbuffer_add_mem (&buf, str, len);
1885                         g_free (str);
1886                 } else {
1887                         sigbuffer_add_value (&buf, 0);
1888                 }
1889                 /* native type name */
1890                 sigbuffer_add_value (&buf, 0);
1891                 /* custom marshaler type name */
1892                 if (minfo->marshaltype || minfo->marshaltyperef) {
1893                         if (minfo->marshaltyperef)
1894                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1895                         else
1896                                 str = mono_string_to_utf8 (minfo->marshaltype);
1897                         len = strlen (str);
1898                         sigbuffer_add_value (&buf, len);
1899                         sigbuffer_add_mem (&buf, str, len);
1900                         g_free (str);
1901                 } else {
1902                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1903                         sigbuffer_add_value (&buf, 0);
1904                 }
1905                 if (minfo->mcookie) {
1906                         str = mono_string_to_utf8 (minfo->mcookie);
1907                         len = strlen (str);
1908                         sigbuffer_add_value (&buf, len);
1909                         sigbuffer_add_mem (&buf, str, len);
1910                         g_free (str);
1911                 } else {
1912                         sigbuffer_add_value (&buf, 0);
1913                 }
1914                 break;
1915         default:
1916                 break;
1917         }
1918         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1919         sigbuffer_free (&buf);
1920         return idx;
1921 }
1922
1923 static void
1924 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1925 {
1926         MonoDynamicTable *table;
1927         guint32 *values;
1928
1929         /* maybe this fixup should be done in the C# code */
1930         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1931                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1932         table = &assembly->tables [MONO_TABLE_FIELD];
1933         fb->table_idx = table->next_idx ++;
1934         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1935         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1936         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1937         values [MONO_FIELD_FLAGS] = fb->attrs;
1938         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1939
1940         if (fb->offset != -1) {
1941                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1942                 table->rows ++;
1943                 alloc_table (table, table->rows);
1944                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1945                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1946                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1947         }
1948         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1949                 guint32 field_type = 0;
1950                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1951                 table->rows ++;
1952                 alloc_table (table, table->rows);
1953                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1954                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1955                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1956                 values [MONO_CONSTANT_TYPE] = field_type;
1957                 values [MONO_CONSTANT_PADDING] = 0;
1958         }
1959         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1960                 guint32 rva_idx;
1961                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1962                 table->rows ++;
1963                 alloc_table (table, table->rows);
1964                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1965                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1966                 /*
1967                  * We store it in the code section because it's simpler for now.
1968                  */
1969                 if (fb->rva_data) {
1970                         if (mono_array_length (fb->rva_data) >= 10)
1971                                 stream_data_align (&assembly->code);
1972                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1973                 } else
1974                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1975                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1976         }
1977         if (fb->marshal_info) {
1978                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1979                 table->rows ++;
1980                 alloc_table (table, table->rows);
1981                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1982                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1983                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1984         }
1985 }
1986
1987 static guint32
1988 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1989 {
1990         SigBuffer buf;
1991         guint32 nparams = 0;
1992         MonoReflectionMethodBuilder *mb = fb->get_method;
1993         MonoReflectionMethodBuilder *smb = fb->set_method;
1994         guint32 idx, i;
1995
1996         if (mb && mb->parameters)
1997                 nparams = mono_array_length (mb->parameters);
1998         if (!mb && smb && smb->parameters)
1999                 nparams = mono_array_length (smb->parameters) - 1;
2000         sigbuffer_init (&buf, 32);
2001         if (fb->call_conv & 0x20)
2002                 sigbuffer_add_byte (&buf, 0x28);
2003         else
2004                 sigbuffer_add_byte (&buf, 0x08);
2005         sigbuffer_add_value (&buf, nparams);
2006         if (mb) {
2007                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2008                 for (i = 0; i < nparams; ++i) {
2009                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2010                         encode_reflection_type (assembly, pt, &buf);
2011                 }
2012         } else if (smb && smb->parameters) {
2013                 /* the property type is the last param */
2014                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2015                 for (i = 0; i < nparams; ++i) {
2016                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2017                         encode_reflection_type (assembly, pt, &buf);
2018                 }
2019         } else {
2020                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2021         }
2022
2023         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2024         sigbuffer_free (&buf);
2025         return idx;
2026 }
2027
2028 static void
2029 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2030 {
2031         MonoDynamicTable *table;
2032         guint32 *values;
2033         guint num_methods = 0;
2034         guint32 semaidx;
2035
2036         /* 
2037          * we need to set things in the following tables:
2038          * PROPERTYMAP (info already filled in _get_type_info ())
2039          * PROPERTY    (rows already preallocated in _get_type_info ())
2040          * METHOD      (method info already done with the generic method code)
2041          * METHODSEMANTICS
2042          * CONSTANT
2043          */
2044         table = &assembly->tables [MONO_TABLE_PROPERTY];
2045         pb->table_idx = table->next_idx ++;
2046         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2047         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2048         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2049         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2050
2051         /* FIXME: we still don't handle 'other' methods */
2052         if (pb->get_method) num_methods ++;
2053         if (pb->set_method) num_methods ++;
2054
2055         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2056         table->rows += num_methods;
2057         alloc_table (table, table->rows);
2058
2059         if (pb->get_method) {
2060                 semaidx = table->next_idx ++;
2061                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2062                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2063                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2064                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2065         }
2066         if (pb->set_method) {
2067                 semaidx = table->next_idx ++;
2068                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2069                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2070                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2071                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2072         }
2073         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2074                 guint32 field_type = 0;
2075                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2076                 table->rows ++;
2077                 alloc_table (table, table->rows);
2078                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2079                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2080                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2081                 values [MONO_CONSTANT_TYPE] = field_type;
2082                 values [MONO_CONSTANT_PADDING] = 0;
2083         }
2084 }
2085
2086 static void
2087 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2088 {
2089         MonoDynamicTable *table;
2090         guint32 *values;
2091         guint num_methods = 0;
2092         guint32 semaidx;
2093
2094         /* 
2095          * we need to set things in the following tables:
2096          * EVENTMAP (info already filled in _get_type_info ())
2097          * EVENT    (rows already preallocated in _get_type_info ())
2098          * METHOD      (method info already done with the generic method code)
2099          * METHODSEMANTICS
2100          */
2101         table = &assembly->tables [MONO_TABLE_EVENT];
2102         eb->table_idx = table->next_idx ++;
2103         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2104         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2105         values [MONO_EVENT_FLAGS] = eb->attrs;
2106         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2107
2108         /*
2109          * FIXME: we still don't handle 'other' methods 
2110          */
2111         if (eb->add_method) num_methods ++;
2112         if (eb->remove_method) num_methods ++;
2113         if (eb->raise_method) num_methods ++;
2114
2115         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2116         table->rows += num_methods;
2117         alloc_table (table, table->rows);
2118
2119         if (eb->add_method) {
2120                 semaidx = table->next_idx ++;
2121                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2122                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2123                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2124                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2125         }
2126         if (eb->remove_method) {
2127                 semaidx = table->next_idx ++;
2128                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2129                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2130                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2131                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2132         }
2133         if (eb->raise_method) {
2134                 semaidx = table->next_idx ++;
2135                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2136                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2137                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2138                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2139         }
2140 }
2141
2142 static void
2143 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2144 {
2145         MonoDynamicTable *table;
2146         guint32 num_constraints, i;
2147         guint32 *values;
2148         guint32 table_idx;
2149
2150         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2151         num_constraints = gparam->iface_constraints ?
2152                 mono_array_length (gparam->iface_constraints) : 0;
2153         table->rows += num_constraints;
2154         if (gparam->base_type)
2155                 table->rows++;
2156         alloc_table (table, table->rows);
2157
2158         if (gparam->base_type) {
2159                 table_idx = table->next_idx ++;
2160                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2161
2162                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2163                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2164                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2165         }
2166
2167         for (i = 0; i < num_constraints; i++) {
2168                 MonoReflectionType *constraint = mono_array_get (
2169                         gparam->iface_constraints, gpointer, i);
2170
2171                 table_idx = table->next_idx ++;
2172                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2173
2174                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176                         assembly, mono_reflection_type_get_handle (constraint));
2177         }
2178 }
2179
2180 static void
2181 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2182 {
2183         GenericParamTableEntry *entry;
2184
2185         /*
2186          * The GenericParam table must be sorted according to the `owner' field.
2187          * We need to do this sorting prior to writing the GenericParamConstraint
2188          * table, since we have to use the final GenericParam table indices there
2189          * and they must also be sorted.
2190          */
2191
2192         entry = g_new0 (GenericParamTableEntry, 1);
2193         entry->owner = owner;
2194         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2195         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2196         entry->gparam = gparam;
2197         
2198         g_ptr_array_add (assembly->gen_params, entry);
2199 }
2200
2201 static void
2202 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2203 {
2204         MonoDynamicTable *table;
2205         MonoGenericParam *param;
2206         guint32 *values;
2207         guint32 table_idx;
2208
2209         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2210         table_idx = table->next_idx ++;
2211         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2212
2213         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2214
2215         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2216         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2217         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2218         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2219
2220         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2221
2222         encode_constraints (entry->gparam, table_idx, assembly);
2223 }
2224
2225 static guint32
2226 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2227 {
2228         MonoDynamicTable *table;
2229         guint32 token;
2230         guint32 *values;
2231         guint32 cols [MONO_ASSEMBLY_SIZE];
2232         const char *pubkey;
2233         guint32 publen;
2234
2235         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2236                 return token;
2237
2238         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2239                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2240                 token = table->next_idx ++;
2241                 table->rows ++;
2242                 alloc_table (table, table->rows);
2243                 values = table->values + token * MONO_MODULEREF_SIZE;
2244                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2245
2246                 token <<= MONO_RESOLTION_SCOPE_BITS;
2247                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2248                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2249
2250                 return token;
2251         }
2252         
2253         if (image->assembly->dynamic)
2254                 /* FIXME: */
2255                 memset (cols, 0, sizeof (cols));
2256         else {
2257                 /* image->assembly->image is the manifest module */
2258                 image = image->assembly->image;
2259                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2260         }
2261
2262         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2263         token = table->next_idx ++;
2264         table->rows ++;
2265         alloc_table (table, table->rows);
2266         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2267         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2268         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2269         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2270         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2271         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2272         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2273         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2274         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2275
2276         if (strcmp ("", image->assembly->aname.culture)) {
2277                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2278                                 image->assembly->aname.culture);
2279         }
2280
2281         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2282                 guchar pubtoken [9];
2283                 pubtoken [0] = 8;
2284                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2285                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2286         } else {
2287                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2288         }
2289         token <<= MONO_RESOLTION_SCOPE_BITS;
2290         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2291         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2292         return token;
2293 }
2294
2295 static guint32
2296 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2297 {
2298         MonoDynamicTable *table;
2299         guint32 *values;
2300         guint32 token;
2301         SigBuffer buf;
2302
2303         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2304                 return token;
2305
2306         sigbuffer_init (&buf, 32);
2307         switch (type->type) {
2308         case MONO_TYPE_FNPTR:
2309         case MONO_TYPE_PTR:
2310         case MONO_TYPE_SZARRAY:
2311         case MONO_TYPE_ARRAY:
2312         case MONO_TYPE_VAR:
2313         case MONO_TYPE_MVAR:
2314         case MONO_TYPE_GENERICINST:
2315                 encode_type (assembly, type, &buf);
2316                 break;
2317         case MONO_TYPE_CLASS:
2318         case MONO_TYPE_VALUETYPE: {
2319                 MonoClass *k = mono_class_from_mono_type (type);
2320                 if (!k || !k->generic_container) {
2321                         sigbuffer_free (&buf);
2322                         return 0;
2323                 }
2324                 encode_type (assembly, type, &buf);
2325                 break;
2326         }
2327         default:
2328                 sigbuffer_free (&buf);
2329                 return 0;
2330         }
2331
2332         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2333         if (assembly->save) {
2334                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2335                 alloc_table (table, table->rows + 1);
2336                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2337                 values [MONO_TYPESPEC_SIGNATURE] = token;
2338         }
2339         sigbuffer_free (&buf);
2340
2341         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2342         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2343         table->next_idx ++;
2344         return token;
2345 }
2346
2347 static guint32
2348 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2349 {
2350         MonoDynamicTable *table;
2351         guint32 *values;
2352         guint32 token, scope, enclosing;
2353         MonoClass *klass;
2354
2355         /* if the type requires a typespec, we must try that first*/
2356         if (try_typespec && (token = create_typespec (assembly, type)))
2357                 return token;
2358         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2359         if (token)
2360                 return token;
2361         klass = mono_class_from_mono_type (type);
2362         if (!klass)
2363                 klass = mono_class_from_mono_type (type);
2364
2365         /*
2366          * If it's in the same module and not a generic type parameter:
2367          */
2368         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2369                         (type->type != MONO_TYPE_MVAR)) {
2370                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2371                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2372                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2373                 return token;
2374         }
2375
2376         if (klass->nested_in) {
2377                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2378                 /* get the typeref idx of the enclosing type */
2379                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2380                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2381         } else {
2382                 scope = resolution_scope_from_image (assembly, klass->image);
2383         }
2384         table = &assembly->tables [MONO_TABLE_TYPEREF];
2385         if (assembly->save) {
2386                 alloc_table (table, table->rows + 1);
2387                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2388                 values [MONO_TYPEREF_SCOPE] = scope;
2389                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2390                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2391         }
2392         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2393         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2394         table->next_idx ++;
2395         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2396         return token;
2397 }
2398
2399 /*
2400  * Despite the name, we handle also TypeSpec (with the above helper).
2401  */
2402 static guint32
2403 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2404 {
2405         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2406 }
2407
2408 #ifndef DISABLE_REFLECTION_EMIT
2409 static guint32
2410 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2411 {
2412         MonoDynamicTable *table;
2413         guint32 *values;
2414         guint32 token, pclass;
2415
2416         switch (parent & MONO_TYPEDEFORREF_MASK) {
2417         case MONO_TYPEDEFORREF_TYPEREF:
2418                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2419                 break;
2420         case MONO_TYPEDEFORREF_TYPESPEC:
2421                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2422                 break;
2423         case MONO_TYPEDEFORREF_TYPEDEF:
2424                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2425                 break;
2426         default:
2427                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2428                 return 0;
2429         }
2430         /* extract the index */
2431         parent >>= MONO_TYPEDEFORREF_BITS;
2432
2433         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2434
2435         if (assembly->save) {
2436                 alloc_table (table, table->rows + 1);
2437                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2438                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2439                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2440                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2441         }
2442
2443         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2444         table->next_idx ++;
2445
2446         return token;
2447 }
2448
2449 /*
2450  * Insert a memberef row into the metadata: the token that point to the memberref
2451  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2452  * mono_image_get_fieldref_token()).
2453  * The sig param is an index to an already built signature.
2454  */
2455 static guint32
2456 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2457 {
2458         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2459         return mono_image_add_memberef_row (assembly, parent, name, sig);
2460 }
2461
2462
2463 static guint32
2464 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2465 {
2466         guint32 token;
2467         MonoMethodSignature *sig;
2468         
2469         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2470
2471         if (create_typespec) {
2472                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2473                 if (token)
2474                         return token;
2475         } 
2476
2477         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2478         if (token && !create_typespec)
2479                 return token;
2480
2481         g_assert (!method->is_inflated);
2482         if (!token) {
2483                 /*
2484                  * A methodref signature can't contain an unmanaged calling convention.
2485                  */
2486                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2487                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2488                         sig->call_convention = MONO_CALL_DEFAULT;
2489                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2490                         method->name,  method_encode_signature (assembly, sig));
2491                 g_free (sig);
2492                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2493         }
2494
2495         if (create_typespec) {
2496                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2497                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2498                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2499
2500                 if (assembly->save) {
2501                         guint32 *values;
2502
2503                         alloc_table (table, table->rows + 1);
2504                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2505                         values [MONO_METHODSPEC_METHOD] = token;
2506                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2507                 }
2508
2509                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2510                 table->next_idx ++;
2511                 /*methodspec and memberef tokens are diferent, */
2512                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2513                 return token;
2514         }
2515         return token;
2516 }
2517
2518 static guint32
2519 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2520 {
2521         guint32 token, parent, sig;
2522         ReflectionMethodBuilder rmb;
2523         char *name;
2524         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2525         
2526         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2527         if (token)
2528                 return token;
2529
2530         name = mono_string_to_utf8 (method->name);
2531         reflection_methodbuilder_from_method_builder (&rmb, method);
2532
2533         /*
2534          * A methodref signature can't contain an unmanaged calling convention.
2535          * Since some flags are encoded as part of call_conv, we need to check against it.
2536         */
2537         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2538                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2539
2540         sig = method_builder_encode_signature (assembly, &rmb);
2541
2542         if (tb->generic_params)
2543                 parent = create_generic_typespec (assembly, tb);
2544         else
2545                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2546
2547         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2548
2549         g_free (name);
2550         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2551         return token;
2552 }
2553
2554 static guint32
2555 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2556                                      const gchar *name, guint32 sig)
2557 {
2558         MonoDynamicTable *table;
2559         guint32 token;
2560         guint32 *values;
2561         
2562         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2563
2564         if (assembly->save) {
2565                 alloc_table (table, table->rows + 1);
2566                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2567                 values [MONO_MEMBERREF_CLASS] = original;
2568                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2569                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2570         }
2571
2572         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2573         table->next_idx ++;
2574
2575         return token;
2576 }
2577
2578 static guint32
2579 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2580 {
2581         SigBuffer buf;
2582         int i;
2583         guint32 nparams = mono_array_length (mb->generic_params);
2584         guint32 idx;
2585
2586         if (!assembly->save)
2587                 return 0;
2588
2589         sigbuffer_init (&buf, 32);
2590
2591         sigbuffer_add_value (&buf, 0xa);
2592         sigbuffer_add_value (&buf, nparams);
2593
2594         for (i = 0; i < nparams; i++) {
2595                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2596                 sigbuffer_add_value (&buf, i);
2597         }
2598
2599         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2600         sigbuffer_free (&buf);
2601         return idx;
2602 }
2603
2604 static guint32
2605 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2606 {
2607         MonoDynamicTable *table;
2608         guint32 *values;
2609         guint32 token, mtoken = 0;
2610
2611         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2612         if (token)
2613                 return token;
2614
2615         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2616
2617         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2618         switch (mono_metadata_token_table (mtoken)) {
2619         case MONO_TABLE_MEMBERREF:
2620                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2621                 break;
2622         case MONO_TABLE_METHOD:
2623                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2624                 break;
2625         default:
2626                 g_assert_not_reached ();
2627         }
2628
2629         if (assembly->save) {
2630                 alloc_table (table, table->rows + 1);
2631                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2632                 values [MONO_METHODSPEC_METHOD] = mtoken;
2633                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2634         }
2635
2636         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2637         table->next_idx ++;
2638
2639         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2640         return token;
2641 }
2642
2643 static guint32
2644 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2645 {
2646         guint32 token;
2647
2648         if (mb->generic_params && create_methodspec) 
2649                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2650
2651         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2652         if (token)
2653                 return token;
2654
2655         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2656         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2657         return token;
2658 }
2659
2660 static guint32
2661 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2662 {
2663         guint32 token, parent, sig;
2664         ReflectionMethodBuilder rmb;
2665         char *name;
2666         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2667         
2668         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2669         if (token)
2670                 return token;
2671
2672         g_assert (tb->generic_params);
2673
2674         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2675
2676         parent = create_generic_typespec (assembly, tb);
2677         name = mono_string_to_utf8 (rmb.name);
2678         sig = method_builder_encode_signature (assembly, &rmb);
2679
2680         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2681
2682         g_free (name);
2683         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2684         return token;
2685 }
2686 #endif
2687
2688 static gboolean
2689 is_field_on_inst (MonoClassField *field)
2690 {
2691         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2692 }
2693
2694 /*
2695  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2696  */
2697 static MonoType*
2698 get_field_on_inst_generic_type (MonoClassField *field)
2699 {
2700         MonoClass *class, *gtd;
2701         MonoDynamicGenericClass *dgclass;
2702         int field_index;
2703
2704         g_assert (is_field_on_inst (field));
2705
2706         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2707
2708         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2709                 field_index = field - dgclass->fields;
2710                 return dgclass->field_generic_types [field_index];              
2711         }
2712
2713         class = field->parent;
2714         gtd = class->generic_class->container_class;
2715
2716         if (field >= class->fields && field - class->fields < class->field.count) {
2717                 field_index = field - class->fields;
2718                 return gtd->fields [field_index].type;
2719         }
2720
2721         g_assert_not_reached ();
2722         return 0;
2723 }
2724
2725 #ifndef DISABLE_REFLECTION_EMIT
2726 static guint32
2727 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2728 {
2729         MonoType *type;
2730         guint32 token;
2731
2732         g_assert (field);
2733         g_assert (field->parent);
2734
2735         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2736         if (token)
2737                 return token;
2738
2739         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2740                 int index = field - field->parent->fields;
2741                 type = field->parent->generic_class->container_class->fields [index].type;
2742         } else {
2743                 if (is_field_on_inst (field))
2744                         type = get_field_on_inst_generic_type (field);
2745                 else
2746                         type = field->type;
2747         }
2748         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2749                                                                                         mono_field_get_name (field),
2750                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2751         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2752         return token;
2753 }
2754
2755 static guint32
2756 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2757 {
2758         guint32 token;
2759         MonoClass *klass;
2760         MonoGenericClass *gclass;
2761         MonoDynamicGenericClass *dgclass;
2762         MonoType *type;
2763         char *name;
2764
2765         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2766         if (token)
2767                 return token;
2768         if (is_sre_field_builder (mono_object_class (f->fb))) {
2769                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2770                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2771                 klass = mono_class_from_mono_type (type);
2772                 gclass = type->data.generic_class;
2773                 g_assert (gclass->is_dynamic);
2774                 dgclass = (MonoDynamicGenericClass *) gclass;
2775
2776                 name = mono_string_to_utf8 (fb->name);
2777                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2778                                                                                                 field_encode_signature (assembly, fb));
2779                 g_free (name);          
2780         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2781                 guint32 sig;
2782                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2783
2784                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785                 klass = mono_class_from_mono_type (type);
2786
2787                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2788                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2789         } else {
2790                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2791                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2792         }
2793
2794         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2795         return token;
2796 }
2797
2798 static guint32
2799 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2800 {
2801         guint32 sig, token;
2802         MonoClass *klass;
2803         MonoGenericClass *gclass;
2804         MonoType *type;
2805
2806         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2807
2808         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2809         if (token)
2810                 return token;
2811
2812         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2813                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2814                 MonoDynamicGenericClass *dgclass;
2815                 ReflectionMethodBuilder rmb;
2816                 char *name;
2817
2818                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2819                 klass = mono_class_from_mono_type (type);
2820
2821                 gclass = type->data.generic_class;
2822                 g_assert (gclass->is_dynamic);
2823                 dgclass = (MonoDynamicGenericClass *) gclass;
2824
2825                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2826
2827                 name = mono_string_to_utf8 (rmb.name);
2828
2829                 sig = method_builder_encode_signature (assembly, &rmb);
2830
2831                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2832                 g_free (name);
2833         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2834                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2835
2836                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2837                 klass = mono_class_from_mono_type (type);
2838
2839                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2840                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2841         } else {
2842                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2843                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2844         }
2845
2846
2847         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2848         return token;
2849 }
2850
2851 static MonoMethod*
2852 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2853 {
2854         MonoClass *klass;
2855         MonoGenericContext tmp_context;
2856         MonoType **type_argv;
2857         MonoGenericInst *ginst;
2858         MonoMethod *method, *inflated;
2859         int count, i;
2860
2861         init_type_builder_generics ((MonoObject*)m->inst);
2862
2863         method = inflate_method (m->inst, (MonoObject*)m->mb);
2864
2865         klass = method->klass;
2866
2867         if (m->method_args == NULL)
2868                 return method;
2869
2870         if (method->is_inflated)
2871                 method = ((MonoMethodInflated *) method)->declaring;
2872
2873         count = mono_array_length (m->method_args);
2874
2875         type_argv = g_new0 (MonoType *, count);
2876         for (i = 0; i < count; i++) {
2877                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2878                 type_argv [i] = mono_reflection_type_get_handle (garg);
2879         }
2880         ginst = mono_metadata_get_generic_inst (count, type_argv);
2881         g_free (type_argv);
2882
2883         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2884         tmp_context.method_inst = ginst;
2885
2886         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2887         return inflated;
2888 }
2889
2890 static guint32
2891 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2892 {
2893         guint32 sig, token = 0;
2894         MonoType *type;
2895         MonoClass *klass;
2896
2897         if (m->method_args) {
2898                 MonoMethod *inflated;
2899
2900                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2901                 if (create_methodspec)
2902                         token = mono_image_get_methodspec_token (assembly, inflated);
2903                 else
2904                         token = mono_image_get_inflated_method_token (assembly, inflated);
2905                 return token;
2906         }
2907
2908         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2909         if (token)
2910                 return token;
2911
2912         if (is_sre_method_builder (mono_object_class (m->mb))) {
2913                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2914                 MonoGenericClass *gclass;
2915                 ReflectionMethodBuilder rmb;
2916                 char *name;
2917
2918                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2919                 klass = mono_class_from_mono_type (type);
2920                 gclass = type->data.generic_class;
2921                 g_assert (gclass->is_dynamic);
2922
2923                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2924
2925                 name = mono_string_to_utf8 (rmb.name);
2926
2927                 sig = method_builder_encode_signature (assembly, &rmb);
2928
2929                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2930                 g_free (name);          
2931         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2932                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2933
2934                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2935                 klass = mono_class_from_mono_type (type);
2936
2937                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2938                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2939         } else {
2940                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2941                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2942         }
2943
2944         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2945         return token;
2946 }
2947
2948 static guint32
2949 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2950 {
2951         SigBuffer buf;
2952         int i;
2953         guint32 nparams = context->method_inst->type_argc;
2954         guint32 idx;
2955
2956         if (!assembly->save)
2957                 return 0;
2958
2959         sigbuffer_init (&buf, 32);
2960         /*
2961          * FIXME: vararg, explicit_this, differenc call_conv values...
2962          */
2963         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2964         sigbuffer_add_value (&buf, nparams);
2965
2966         for (i = 0; i < nparams; i++)
2967                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2968
2969         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2970         sigbuffer_free (&buf);
2971         return idx;
2972 }
2973
2974 static guint32
2975 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2976 {
2977         MonoDynamicTable *table;
2978         guint32 *values;
2979         guint32 token, mtoken = 0, sig;
2980         MonoMethodInflated *imethod;
2981         MonoMethod *declaring;
2982
2983         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2984
2985         g_assert (method->is_inflated);
2986         imethod = (MonoMethodInflated *) method;
2987         declaring = imethod->declaring;
2988
2989         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2990         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2991
2992         if (!mono_method_signature (declaring)->generic_param_count)
2993                 return mtoken;
2994
2995         switch (mono_metadata_token_table (mtoken)) {
2996         case MONO_TABLE_MEMBERREF:
2997                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2998                 break;
2999         case MONO_TABLE_METHOD:
3000                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3001                 break;
3002         default:
3003                 g_assert_not_reached ();
3004         }
3005
3006         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3007
3008         if (assembly->save) {
3009                 alloc_table (table, table->rows + 1);
3010                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3011                 values [MONO_METHODSPEC_METHOD] = mtoken;
3012                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3013         }
3014
3015         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3016         table->next_idx ++;
3017
3018         return token;
3019 }
3020
3021 static guint32
3022 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3023 {
3024         MonoMethodInflated *imethod;
3025         guint32 token;
3026         
3027         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3028         if (token)
3029                 return token;
3030
3031         g_assert (method->is_inflated);
3032         imethod = (MonoMethodInflated *) method;
3033
3034         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3035                 token = method_encode_methodspec (assembly, method);
3036         } else {
3037                 guint32 sig = method_encode_signature (
3038                         assembly, mono_method_signature (imethod->declaring));
3039                 token = mono_image_get_memberref_token (
3040                         assembly, &method->klass->byval_arg, method->name, sig);
3041         }
3042
3043         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3044         return token;
3045 }
3046
3047 static guint32
3048 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3049 {
3050         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3051         guint32 sig, token;
3052
3053         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3054         token = mono_image_get_memberref_token (
3055                 assembly, &m->klass->byval_arg, m->name, sig);
3056
3057         return token;
3058 }
3059
3060 static guint32
3061 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3062 {
3063         MonoDynamicTable *table;
3064         MonoClass *klass;
3065         MonoType *type;
3066         guint32 *values;
3067         guint32 token;
3068         SigBuffer buf;
3069         int count, i;
3070
3071         /*
3072          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3073          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3074          * Because of this, we must not insert it into the `typeref' hash table.
3075          */
3076         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3077         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3078         if (token)
3079                 return token;
3080
3081         sigbuffer_init (&buf, 32);
3082
3083         g_assert (tb->generic_params);
3084         klass = mono_class_from_mono_type (type);
3085
3086         if (tb->generic_container)
3087                 mono_reflection_create_generic_class (tb);
3088
3089         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3090         g_assert (klass->generic_container);
3091         sigbuffer_add_value (&buf, klass->byval_arg.type);
3092         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3093
3094         count = mono_array_length (tb->generic_params);
3095         sigbuffer_add_value (&buf, count);
3096         for (i = 0; i < count; i++) {
3097                 MonoReflectionGenericParam *gparam;
3098
3099                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3100
3101                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3102         }
3103
3104         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3105
3106         if (assembly->save) {
3107                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3108                 alloc_table (table, table->rows + 1);
3109                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3110                 values [MONO_TYPESPEC_SIGNATURE] = token;
3111         }
3112         sigbuffer_free (&buf);
3113
3114         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3115         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3116         table->next_idx ++;
3117         return token;
3118 }
3119
3120 /*
3121  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3122  */
3123 static MonoType*
3124 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3125 {
3126         int i, count, len, pos;
3127         MonoType *t;
3128
3129         count = 0;
3130         if (modreq)
3131                 count += mono_array_length (modreq);
3132         if (modopt)
3133                 count += mono_array_length (modopt);
3134
3135         if (count == 0)
3136                 return mono_metadata_type_dup (NULL, type);
3137
3138         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3139         t = g_malloc (len);
3140         memcpy (t, type, MONO_SIZEOF_TYPE);
3141
3142         t->num_mods = count;
3143         pos = 0;
3144         if (modreq) {
3145                 for (i = 0; i < mono_array_length (modreq); ++i) {
3146                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3147                         t->modifiers [pos].required = 1;
3148                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3149                         pos ++;
3150                 }
3151         }
3152         if (modopt) {
3153                 for (i = 0; i < mono_array_length (modopt); ++i) {
3154                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3155                         t->modifiers [pos].required = 0;
3156                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3157                         pos ++;
3158                 }
3159         }
3160
3161         return t;
3162 }
3163
3164 static void
3165 init_type_builder_generics (MonoObject *type)
3166 {
3167         MonoReflectionTypeBuilder *tb;
3168
3169         if (!is_sre_type_builder(mono_object_class (type)))
3170                 return;
3171         tb = (MonoReflectionTypeBuilder *)type;
3172
3173         if (tb && tb->generic_container)
3174                 mono_reflection_create_generic_class (tb);
3175 }
3176
3177 static guint32
3178 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3179 {
3180         MonoDynamicTable *table;
3181         MonoClass *klass;
3182         MonoType *custom = NULL, *type;
3183         guint32 *values;
3184         guint32 token, pclass, parent, sig;
3185         gchar *name;
3186
3187         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3188         if (token)
3189                 return token;
3190
3191         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3192         name = mono_string_to_utf8 (fb->name);
3193
3194         /*FIXME this is one more layer of ugliness due how types are created.*/
3195         init_type_builder_generics (fb->type);
3196
3197         /* fb->type does not include the custom modifiers */
3198         /* FIXME: We should do this in one place when a fieldbuilder is created */
3199         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3200         if (fb->modreq || fb->modopt)
3201                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3202
3203         sig = fieldref_encode_signature (assembly, NULL, type);
3204         g_free (custom);
3205
3206         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3207         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3208         
3209         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3210         parent >>= MONO_TYPEDEFORREF_BITS;
3211
3212         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3213
3214         if (assembly->save) {
3215                 alloc_table (table, table->rows + 1);
3216                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3217                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3218                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3219                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3220         }
3221
3222         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3223         table->next_idx ++;
3224         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3225         g_free (name);
3226         return token;
3227 }
3228
3229 static guint32
3230 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3231 {
3232         SigBuffer buf;
3233         guint32 nargs;
3234         guint32 size;
3235         guint32 i, idx;
3236
3237         if (!assembly->save)
3238                 return 0;
3239
3240         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3241         g_assert (helper->type == 2);
3242
3243         if (helper->arguments)
3244                 nargs = mono_array_length (helper->arguments);
3245         else
3246                 nargs = 0;
3247
3248         size = 10 + (nargs * 10);
3249         
3250         sigbuffer_init (&buf, 32);
3251
3252         /* Encode calling convention */
3253         /* Change Any to Standard */
3254         if ((helper->call_conv & 0x03) == 0x03)
3255                 helper->call_conv = 0x01;
3256         /* explicit_this implies has_this */
3257         if (helper->call_conv & 0x40)
3258                 helper->call_conv &= 0x20;
3259
3260         if (helper->call_conv == 0) { /* Unmanaged */
3261                 idx = helper->unmanaged_call_conv - 1;
3262         } else {
3263                 /* Managed */
3264                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3265                 if (helper->call_conv & 0x02) /* varargs */
3266                         idx += 0x05;
3267         }
3268
3269         sigbuffer_add_byte (&buf, idx);
3270         sigbuffer_add_value (&buf, nargs);
3271         encode_reflection_type (assembly, helper->return_type, &buf);
3272         for (i = 0; i < nargs; ++i) {
3273                 MonoArray *modreqs = NULL;
3274                 MonoArray *modopts = NULL;
3275                 MonoReflectionType *pt;
3276
3277                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3278                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3279                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3280                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3281
3282                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3283                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3284                 encode_reflection_type (assembly, pt, &buf);
3285         }
3286         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3287         sigbuffer_free (&buf);
3288
3289         return idx;
3290 }
3291
3292 static guint32 
3293 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3294 {
3295         guint32 idx;
3296         MonoDynamicTable *table;
3297         guint32 *values;
3298
3299         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3300         idx = table->next_idx ++;
3301         table->rows ++;
3302         alloc_table (table, table->rows);
3303         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3304
3305         values [MONO_STAND_ALONE_SIGNATURE] =
3306                 mono_reflection_encode_sighelper (assembly, helper);
3307
3308         return idx;
3309 }
3310
3311 static int
3312 reflection_cc_to_file (int call_conv) {
3313         switch (call_conv & 0x3) {
3314         case 0:
3315         case 1: return MONO_CALL_DEFAULT;
3316         case 2: return MONO_CALL_VARARG;
3317         default:
3318                 g_assert_not_reached ();
3319         }
3320         return 0;
3321 }
3322 #endif /* !DISABLE_REFLECTION_EMIT */
3323
3324 typedef struct {
3325         MonoType *parent;
3326         MonoMethodSignature *sig;
3327         char *name;
3328         guint32 token;
3329 } ArrayMethod;
3330
3331 #ifndef DISABLE_REFLECTION_EMIT
3332 static guint32
3333 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3334 {
3335         guint32 nparams, i;
3336         GList *tmp;
3337         char *name;
3338         MonoMethodSignature *sig;
3339         ArrayMethod *am;
3340         MonoType *mtype;
3341
3342         name = mono_string_to_utf8 (m->name);
3343         nparams = mono_array_length (m->parameters);
3344         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3345         sig->hasthis = 1;
3346         sig->sentinelpos = -1;
3347         sig->call_convention = reflection_cc_to_file (m->call_conv);
3348         sig->param_count = nparams;
3349         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3350         mtype = mono_reflection_type_get_handle (m->parent);
3351         for (i = 0; i < nparams; ++i)
3352                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3353
3354         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3355                 am = tmp->data;
3356                 if (strcmp (name, am->name) == 0 && 
3357                                 mono_metadata_type_equal (am->parent, mtype) &&
3358                                 mono_metadata_signature_equal (am->sig, sig)) {
3359                         g_free (name);
3360                         g_free (sig);
3361                         m->table_idx = am->token & 0xffffff;
3362                         return am->token;
3363                 }
3364         }
3365         am = g_new0 (ArrayMethod, 1);
3366         am->name = name;
3367         am->sig = sig;
3368         am->parent = mtype;
3369         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3370                 method_encode_signature (assembly, sig));
3371         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3372         m->table_idx = am->token & 0xffffff;
3373         return am->token;
3374 }
3375
3376 /*
3377  * Insert into the metadata tables all the info about the TypeBuilder tb.
3378  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3379  */
3380 static void
3381 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3382 {
3383         MonoDynamicTable *table;
3384         guint *values;
3385         int i, is_object = 0, is_system = 0;
3386         char *n;
3387
3388         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3389         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3390         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3391         n = mono_string_to_utf8 (tb->name);
3392         if (strcmp (n, "Object") == 0)
3393                 is_object++;
3394         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3395         g_free (n);
3396         n = mono_string_to_utf8 (tb->nspace);
3397         if (strcmp (n, "System") == 0)
3398                 is_system++;
3399         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3400         g_free (n);
3401         if (tb->parent && !(is_system && is_object) && 
3402                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3403                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3404         } else {
3405                 values [MONO_TYPEDEF_EXTENDS] = 0;
3406         }
3407         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3408         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3409
3410         /*
3411          * if we have explicitlayout or sequentiallayouts, output data in the
3412          * ClassLayout table.
3413          */
3414         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3415                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3416                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3417                 table->rows++;
3418                 alloc_table (table, table->rows);
3419                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3420                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3421                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3422                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3423         }
3424
3425         /* handle interfaces */
3426         if (tb->interfaces) {
3427                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3428                 i = table->rows;
3429                 table->rows += mono_array_length (tb->interfaces);
3430                 alloc_table (table, table->rows);
3431                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3432                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3433                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3434                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3435                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3436                         values += MONO_INTERFACEIMPL_SIZE;
3437                 }
3438         }
3439
3440         /* handle fields */
3441         if (tb->fields) {
3442                 table = &assembly->tables [MONO_TABLE_FIELD];
3443                 table->rows += tb->num_fields;
3444                 alloc_table (table, table->rows);
3445                 for (i = 0; i < tb->num_fields; ++i)
3446                         mono_image_get_field_info (
3447                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3448         }
3449
3450         /* handle constructors */
3451         if (tb->ctors) {
3452                 table = &assembly->tables [MONO_TABLE_METHOD];
3453                 table->rows += mono_array_length (tb->ctors);
3454                 alloc_table (table, table->rows);
3455                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3456                         mono_image_get_ctor_info (domain,
3457                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3458         }
3459
3460         /* handle methods */
3461         if (tb->methods) {
3462                 table = &assembly->tables [MONO_TABLE_METHOD];
3463                 table->rows += tb->num_methods;
3464                 alloc_table (table, table->rows);
3465                 for (i = 0; i < tb->num_methods; ++i)
3466                         mono_image_get_method_info (
3467                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3468         }
3469
3470         /* Do the same with properties etc.. */
3471         if (tb->events && mono_array_length (tb->events)) {
3472                 table = &assembly->tables [MONO_TABLE_EVENT];
3473                 table->rows += mono_array_length (tb->events);
3474                 alloc_table (table, table->rows);
3475                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3476                 table->rows ++;
3477                 alloc_table (table, table->rows);
3478                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3479                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3480                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3481                 for (i = 0; i < mono_array_length (tb->events); ++i)
3482                         mono_image_get_event_info (
3483                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3484         }
3485         if (tb->properties && mono_array_length (tb->properties)) {
3486                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3487                 table->rows += mono_array_length (tb->properties);
3488                 alloc_table (table, table->rows);
3489                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3490                 table->rows ++;
3491                 alloc_table (table, table->rows);
3492                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3493                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3494                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3495                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3496                         mono_image_get_property_info (
3497                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3498         }
3499
3500         /* handle generic parameters */
3501         if (tb->generic_params) {
3502                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3503                 table->rows += mono_array_length (tb->generic_params);
3504                 alloc_table (table, table->rows);
3505                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3506                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3507
3508                         mono_image_get_generic_param_info (
3509                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3510                 }
3511         }
3512
3513         mono_image_add_decl_security (assembly, 
3514                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3515
3516         if (tb->subtypes) {
3517                 MonoDynamicTable *ntable;
3518                 
3519                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3520                 ntable->rows += mono_array_length (tb->subtypes);
3521                 alloc_table (ntable, ntable->rows);
3522                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3523
3524                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3525                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3526
3527                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3528                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3529                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3530                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3531                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3532                                 ntable->next_idx, ntable->rows);*/
3533                         values += MONO_NESTED_CLASS_SIZE;
3534                         ntable->next_idx++;
3535                 }
3536         }
3537 }
3538 #endif
3539
3540 static void
3541 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3542 {
3543         int i;
3544
3545         mono_ptr_array_append (*types, type);
3546
3547         if (!type->subtypes)
3548                 return;
3549
3550         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3551                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3552                 collect_types (types, subtype);
3553         }
3554 }
3555
3556 static gint
3557 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3558 {
3559         if ((*type1)->table_idx < (*type2)->table_idx)
3560                 return -1;
3561         else
3562                 if ((*type1)->table_idx > (*type2)->table_idx)
3563                         return 1;
3564         else
3565                 return 0;
3566 }
3567
3568 static void
3569 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3570         int i;
3571
3572         if (!pinfo)
3573                 return;
3574         for (i = 0; i < mono_array_length (pinfo); ++i) {
3575                 MonoReflectionParamBuilder *pb;
3576                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3577                 if (!pb)
3578                         continue;
3579                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3580         }
3581 }
3582
3583 static void
3584 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3585         int i;
3586         
3587         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3588         if (tb->fields) {
3589                 for (i = 0; i < tb->num_fields; ++i) {
3590                         MonoReflectionFieldBuilder* fb;
3591                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3592                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3593                 }
3594         }
3595         if (tb->events) {
3596                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3597                         MonoReflectionEventBuilder* eb;
3598                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3599                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3600                 }
3601         }
3602         if (tb->properties) {
3603                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3604                         MonoReflectionPropertyBuilder* pb;
3605                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3606                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3607                 }
3608         }
3609         if (tb->ctors) {
3610                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3611                         MonoReflectionCtorBuilder* cb;
3612                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3613                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3614                         params_add_cattrs (assembly, cb->pinfo);
3615                 }
3616         }
3617
3618         if (tb->methods) {
3619                 for (i = 0; i < tb->num_methods; ++i) {
3620                         MonoReflectionMethodBuilder* mb;
3621                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3622                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3623                         params_add_cattrs (assembly, mb->pinfo);
3624                 }
3625         }
3626
3627         if (tb->subtypes) {
3628                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3629                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3630         }
3631 }
3632
3633 static void
3634 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3635 {
3636         int i;
3637         
3638         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3639
3640         if (moduleb->global_methods) {
3641                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3642                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3643                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3644                         params_add_cattrs (assembly, mb->pinfo);
3645                 }
3646         }
3647
3648         if (moduleb->global_fields) {
3649                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3650                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3651                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3652                 }
3653         }
3654         
3655         if (moduleb->types) {
3656                 for (i = 0; i < moduleb->num_types; ++i)
3657                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3658         }
3659 }
3660
3661 static void
3662 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3663 {
3664         MonoDynamicTable *table;
3665         guint32 *values;
3666         char blob_size [6];
3667         guchar hash [20];
3668         char *b = blob_size;
3669         char *dir, *path;
3670
3671         table = &assembly->tables [MONO_TABLE_FILE];
3672         table->rows++;
3673         alloc_table (table, table->rows);
3674         values = table->values + table->next_idx * MONO_FILE_SIZE;
3675         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3676         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3677         if (module->image->dynamic) {
3678                 /* This depends on the fact that the main module is emitted last */
3679                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3680                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3681         } else {
3682                 dir = NULL;
3683                 path = g_strdup (module->image->name);
3684         }
3685         mono_sha1_get_digest_from_file (path, hash);
3686         g_free (dir);
3687         g_free (path);
3688         mono_metadata_encode_value (20, b, &b);
3689         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3690         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3691         table->next_idx ++;
3692 }
3693
3694 static void
3695 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3696 {
3697         MonoDynamicTable *table;
3698         int i;
3699
3700         table = &assembly->tables [MONO_TABLE_MODULE];
3701         mb->table_idx = table->next_idx ++;
3702         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3703         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3704         i /= 16;
3705         ++i;
3706         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3707         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3708         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3709         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3710 }
3711
3712 static guint32
3713 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3714         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3715 {
3716         MonoDynamicTable *table;
3717         guint32 *values;
3718         guint32 visib, res;
3719
3720         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3721         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3722                 return 0;
3723
3724         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3725         table->rows++;
3726         alloc_table (table, table->rows);
3727         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3728
3729         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3730         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3731         if (klass->nested_in)
3732                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3733         else
3734                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3735         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3736         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3737
3738         res = table->next_idx;
3739
3740         table->next_idx ++;
3741
3742         /* Emit nested types */
3743         if (klass->ext && klass->ext->nested_classes) {
3744                 GList *tmp;
3745
3746                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3747                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3748         }
3749
3750         return res;
3751 }
3752
3753 static void
3754 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3755         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3756 {
3757         MonoClass *klass;
3758         guint32 idx, i;
3759
3760         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3761
3762         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3763
3764         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3765                                                                                                    parent_index, assembly);
3766
3767         /* 
3768          * Emit nested types
3769          * We need to do this ourselves since klass->nested_classes is not set up.
3770          */
3771         if (tb->subtypes) {
3772                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3773                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3774         }
3775 }
3776
3777 static void
3778 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3779         guint32 module_index, MonoDynamicImage *assembly)
3780 {
3781         MonoImage *image = module->image;
3782         MonoTableInfo  *t;
3783         guint32 i;
3784
3785         t = &image->tables [MONO_TABLE_TYPEDEF];
3786
3787         for (i = 0; i < t->rows; ++i) {
3788                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3789
3790                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3791                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3792         }
3793 }
3794
3795 static void
3796 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3797 {
3798         MonoDynamicTable *table;
3799         guint32 *values;
3800         guint32 scope, scope_idx, impl, current_idx;
3801         gboolean forwarder = TRUE;
3802         gpointer iter = NULL;
3803         MonoClass *nested;
3804
3805         if (klass->nested_in) {
3806                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3807                 forwarder = FALSE;
3808         } else {
3809                 scope = resolution_scope_from_image (assembly, klass->image);
3810                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3811                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3812                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3813         }
3814
3815         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3816
3817         table->rows++;
3818         alloc_table (table, table->rows);
3819         current_idx = table->next_idx;
3820         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3821
3822         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3823         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3824         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3825         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3826         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3827
3828         table->next_idx++;
3829
3830         while ((nested = mono_class_get_nested_types (klass, &iter)))
3831                 add_exported_type (assemblyb, assembly, nested, current_idx);
3832 }
3833
3834 static void
3835 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3836 {
3837         MonoClass *klass;
3838         int i;
3839
3840         if (!assemblyb->type_forwarders)
3841                 return;
3842
3843         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3844                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3845                 MonoType *type;
3846                 if (!t)
3847                         continue;
3848
3849                 type = mono_reflection_type_get_handle (t);
3850                 g_assert (type);
3851
3852                 klass = mono_class_from_mono_type (type);
3853
3854                 add_exported_type (assemblyb, assembly, klass, 0);
3855         }
3856 }
3857
3858 #define align_pointer(base,p)\
3859         do {\
3860                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3861                 if (__diff & 3)\
3862                         (p) += 4 - (__diff & 3);\
3863         } while (0)
3864
3865 static int
3866 compare_constants (const void *a, const void *b)
3867 {
3868         const guint32 *a_values = a;
3869         const guint32 *b_values = b;
3870         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3871 }
3872
3873 static int
3874 compare_semantics (const void *a, const void *b)
3875 {
3876         const guint32 *a_values = a;
3877         const guint32 *b_values = b;
3878         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3879         if (assoc)
3880                 return assoc;
3881         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3882 }
3883
3884 static int
3885 compare_custom_attrs (const void *a, const void *b)
3886 {
3887         const guint32 *a_values = a;
3888         const guint32 *b_values = b;
3889
3890         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3891 }
3892
3893 static int
3894 compare_field_marshal (const void *a, const void *b)
3895 {
3896         const guint32 *a_values = a;
3897         const guint32 *b_values = b;
3898
3899         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3900 }
3901
3902 static int
3903 compare_nested (const void *a, const void *b)
3904 {
3905         const guint32 *a_values = a;
3906         const guint32 *b_values = b;
3907
3908         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3909 }
3910
3911 static int
3912 compare_genericparam (const void *a, const void *b)
3913 {
3914         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3915         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3916
3917         if ((*b_entry)->owner == (*a_entry)->owner)
3918                 return 
3919                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3920                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3921         else
3922                 return (*a_entry)->owner - (*b_entry)->owner;
3923 }
3924
3925 static int
3926 compare_declsecurity_attrs (const void *a, const void *b)
3927 {
3928         const guint32 *a_values = a;
3929         const guint32 *b_values = b;
3930
3931         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3932 }
3933
3934 static int
3935 compare_interface_impl (const void *a, const void *b)
3936 {
3937         const guint32 *a_values = a;
3938         const guint32 *b_values = b;
3939
3940         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3941         if (klass)
3942                 return klass;
3943
3944         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3945 }
3946
3947 static void
3948 pad_heap (MonoDynamicStream *sh)
3949 {
3950         if (sh->index & 3) {
3951                 int sz = 4 - (sh->index & 3);
3952                 memset (sh->data + sh->index, 0, sz);
3953                 sh->index += sz;
3954         }
3955 }
3956
3957 struct StreamDesc {
3958         const char *name;
3959         MonoDynamicStream *stream;
3960 };
3961
3962 /*
3963  * build_compressed_metadata() fills in the blob of data that represents the 
3964  * raw metadata as it will be saved in the PE file. The five streams are output 
3965  * and the metadata tables are comnpressed from the guint32 array representation, 
3966  * to the compressed on-disk format.
3967  */
3968 static void
3969 build_compressed_metadata (MonoDynamicImage *assembly)
3970 {
3971         MonoDynamicTable *table;
3972         int i;
3973         guint64 valid_mask = 0;
3974         guint64 sorted_mask;
3975         guint32 heapt_size = 0;
3976         guint32 meta_size = 256; /* allow for header and other stuff */
3977         guint32 table_offset;
3978         guint32 ntables = 0;
3979         guint64 *int64val;
3980         guint32 *int32val;
3981         guint16 *int16val;
3982         MonoImage *meta;
3983         unsigned char *p;
3984         struct StreamDesc stream_desc [5];
3985
3986         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3987         for (i = 0; i < assembly->gen_params->len; i++){
3988                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3989                 write_generic_param_entry (assembly, entry);
3990         }
3991
3992         stream_desc [0].name  = "#~";
3993         stream_desc [0].stream = &assembly->tstream;
3994         stream_desc [1].name  = "#Strings";
3995         stream_desc [1].stream = &assembly->sheap;
3996         stream_desc [2].name  = "#US";
3997         stream_desc [2].stream = &assembly->us;
3998         stream_desc [3].name  = "#Blob";
3999         stream_desc [3].stream = &assembly->blob;
4000         stream_desc [4].name  = "#GUID";
4001         stream_desc [4].stream = &assembly->guid;
4002         
4003         /* tables that are sorted */
4004         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4005                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4006                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4007                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4008                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4009                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4010                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4011         
4012         /* Compute table sizes */
4013         /* the MonoImage has already been created in mono_image_basic_init() */
4014         meta = &assembly->image;
4015
4016         /* sizes should be multiple of 4 */
4017         pad_heap (&assembly->blob);
4018         pad_heap (&assembly->guid);
4019         pad_heap (&assembly->sheap);
4020         pad_heap (&assembly->us);
4021
4022         /* Setup the info used by compute_sizes () */
4023         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4024         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4025         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4026
4027         meta_size += assembly->blob.index;
4028         meta_size += assembly->guid.index;
4029         meta_size += assembly->sheap.index;
4030         meta_size += assembly->us.index;
4031
4032         for (i=0; i < MONO_TABLE_NUM; ++i)
4033                 meta->tables [i].rows = assembly->tables [i].rows;
4034         
4035         for (i = 0; i < MONO_TABLE_NUM; i++){
4036                 if (meta->tables [i].rows == 0)
4037                         continue;
4038                 valid_mask |= (guint64)1 << i;
4039                 ntables ++;
4040                 meta->tables [i].row_size = mono_metadata_compute_size (
4041                         meta, i, &meta->tables [i].size_bitfield);
4042                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4043         }
4044         heapt_size += 24; /* #~ header size */
4045         heapt_size += ntables * 4;
4046         /* make multiple of 4 */
4047         heapt_size += 3;
4048         heapt_size &= ~3;
4049         meta_size += heapt_size;
4050         meta->raw_metadata = g_malloc0 (meta_size);
4051         p = (unsigned char*)meta->raw_metadata;
4052         /* the metadata signature */
4053         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4054         /* version numbers and 4 bytes reserved */
4055         int16val = (guint16*)p;
4056         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4057         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4058         p += 8;
4059         /* version string */
4060         int32val = (guint32*)p;
4061         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4062         p += 4;
4063         memcpy (p, meta->version, strlen (meta->version));
4064         p += GUINT32_FROM_LE (*int32val);
4065         align_pointer (meta->raw_metadata, p);
4066         int16val = (guint16*)p;
4067         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4068         *int16val = GUINT16_TO_LE (5); /* number of streams */
4069         p += 4;
4070
4071         /*
4072          * write the stream info.
4073          */
4074         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4075         table_offset += 3; table_offset &= ~3;
4076
4077         assembly->tstream.index = heapt_size;
4078         for (i = 0; i < 5; ++i) {
4079                 int32val = (guint32*)p;
4080                 stream_desc [i].stream->offset = table_offset;
4081                 *int32val++ = GUINT32_TO_LE (table_offset);
4082                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4083                 table_offset += GUINT32_FROM_LE (*int32val);
4084                 table_offset += 3; table_offset &= ~3;
4085                 p += 8;
4086                 strcpy ((char*)p, stream_desc [i].name);
4087                 p += strlen (stream_desc [i].name) + 1;
4088                 align_pointer (meta->raw_metadata, p);
4089         }
4090         /* 
4091          * now copy the data, the table stream header and contents goes first.
4092          */
4093         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4094         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4095         int32val = (guint32*)p;
4096         *int32val = GUINT32_TO_LE (0); /* reserved */
4097         p += 4;
4098
4099         *p++ = 2; /* version */
4100         *p++ = 0;
4101
4102         if (meta->idx_string_wide)
4103                 *p |= 0x01;
4104         if (meta->idx_guid_wide)
4105                 *p |= 0x02;
4106         if (meta->idx_blob_wide)
4107                 *p |= 0x04;
4108         ++p;
4109         *p++ = 1; /* reserved */
4110         int64val = (guint64*)p;
4111         *int64val++ = GUINT64_TO_LE (valid_mask);
4112         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4113         p += 16;
4114         int32val = (guint32*)p;
4115         for (i = 0; i < MONO_TABLE_NUM; i++){
4116                 if (meta->tables [i].rows == 0)
4117                         continue;
4118                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4119         }
4120         p = (unsigned char*)int32val;
4121
4122         /* sort the tables that still need sorting */
4123         table = &assembly->tables [MONO_TABLE_CONSTANT];
4124         if (table->rows)
4125                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4126         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4127         if (table->rows)
4128                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4129         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4130         if (table->rows)
4131                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4132         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4133         if (table->rows)
4134                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4135         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4136         if (table->rows)
4137                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4138         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4139         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4140         if (table->rows)
4141                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4142         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4143         if (table->rows)
4144                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4145
4146         /* compress the tables */
4147         for (i = 0; i < MONO_TABLE_NUM; i++){
4148                 int row, col;
4149                 guint32 *values;
4150                 guint32 bitfield = meta->tables [i].size_bitfield;
4151                 if (!meta->tables [i].rows)
4152                         continue;
4153                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4154                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4155                 meta->tables [i].base = (char*)p;
4156                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4157                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4158                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4159                                 switch (mono_metadata_table_size (bitfield, col)) {
4160                                 case 1:
4161                                         *p++ = values [col];
4162                                         break;
4163                                 case 2:
4164                                         *p++ = values [col] & 0xff;
4165                                         *p++ = (values [col] >> 8) & 0xff;
4166                                         break;
4167                                 case 4:
4168                                         *p++ = values [col] & 0xff;
4169                                         *p++ = (values [col] >> 8) & 0xff;
4170                                         *p++ = (values [col] >> 16) & 0xff;
4171                                         *p++ = (values [col] >> 24) & 0xff;
4172                                         break;
4173                                 default:
4174                                         g_assert_not_reached ();
4175                                 }
4176                         }
4177                 }
4178                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4179         }
4180         
4181         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4182         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4183         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4184         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4185         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4186
4187         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4188 }
4189
4190 /*
4191  * Some tables in metadata need to be sorted according to some criteria, but
4192  * when methods and fields are first created with reflection, they may be assigned a token
4193  * that doesn't correspond to the final token they will get assigned after the sorting.
4194  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4195  * with the reflection objects that represent them. Once all the tables are set up, the 
4196  * reflection objects will contains the correct table index. fixup_method() will fixup the
4197  * tokens for the method with ILGenerator @ilgen.
4198  */
4199 static void
4200 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4201 {
4202         guint32 code_idx = GPOINTER_TO_UINT (value);
4203         MonoReflectionILTokenInfo *iltoken;
4204         MonoReflectionFieldBuilder *field;
4205         MonoReflectionCtorBuilder *ctor;
4206         MonoReflectionMethodBuilder *method;
4207         MonoReflectionTypeBuilder *tb;
4208         MonoReflectionArrayMethod *am;
4209         guint32 i, idx = 0;
4210         unsigned char *target;
4211
4212         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4213                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4214                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4215                 switch (target [3]) {
4216                 case MONO_TABLE_FIELD:
4217                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4218                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4219                                 idx = field->table_idx;
4220                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4221                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4222                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4223                         } else {
4224                                 g_assert_not_reached ();
4225                         }
4226                         break;
4227                 case MONO_TABLE_METHOD:
4228                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4229                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4230                                 idx = method->table_idx;
4231                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4233                                 idx = ctor->table_idx;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4235                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4236                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4237                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4238                         } else {
4239                                 g_assert_not_reached ();
4240                         }
4241                         break;
4242                 case MONO_TABLE_TYPEDEF:
4243                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4244                                 g_assert_not_reached ();
4245                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4246                         idx = tb->table_idx;
4247                         break;
4248                 case MONO_TABLE_MEMBERREF:
4249                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4250                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4251                                 idx = am->table_idx;
4252                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4253                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4254                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4255                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4256                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4257                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4258                                 continue;
4259                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4260                                 continue;
4261                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4262                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4263                                 g_assert (is_field_on_inst (f));
4264                                 continue;
4265                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4266                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4267                                 continue;
4268                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4269                                 continue;
4270                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4273                                 continue;
4274                         } else {
4275                                 g_assert_not_reached ();
4276                         }
4277                         break;
4278                 case MONO_TABLE_METHODSPEC:
4279                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4280                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281                                 g_assert (mono_method_signature (m)->generic_param_count);
4282                                 continue;
4283                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else {
4288                                 g_assert_not_reached ();
4289                         }
4290                         break;
4291                 default:
4292                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4293                 }
4294                 target [0] = idx & 0xff;
4295                 target [1] = (idx >> 8) & 0xff;
4296                 target [2] = (idx >> 16) & 0xff;
4297         }
4298 }
4299
4300 /*
4301  * fixup_cattrs:
4302  *
4303  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4304  * value is not known when the table is emitted.
4305  */
4306 static void
4307 fixup_cattrs (MonoDynamicImage *assembly)
4308 {
4309         MonoDynamicTable *table;
4310         guint32 *values;
4311         guint32 type, i, idx, token;
4312         MonoObject *ctor;
4313
4314         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4315
4316         for (i = 0; i < table->rows; ++i) {
4317                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4318
4319                 type = values [MONO_CUSTOM_ATTR_TYPE];
4320                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4321                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4322                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4323                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4324                         g_assert (ctor);
4325
4326                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4327                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4328                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4329                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4330                         }
4331                 }
4332         }
4333 }
4334
4335 static void
4336 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4337 {
4338         MonoDynamicTable *table;
4339         guint32 *values;
4340
4341         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4342         table->rows++;
4343         alloc_table (table, table->rows);
4344         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4345         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4346         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4347         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4348         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4349         table->next_idx++;
4350 }
4351
4352 static void
4353 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4354 {
4355         MonoDynamicTable *table;
4356         guint32 *values;
4357         char blob_size [6];
4358         guchar hash [20];
4359         char *b = blob_size;
4360         char *name, *sname;
4361         guint32 idx, offset;
4362
4363         if (rsrc->filename) {
4364                 name = mono_string_to_utf8 (rsrc->filename);
4365                 sname = g_path_get_basename (name);
4366         
4367                 table = &assembly->tables [MONO_TABLE_FILE];
4368                 table->rows++;
4369                 alloc_table (table, table->rows);
4370                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4371                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4372                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4373                 g_free (sname);
4374
4375                 mono_sha1_get_digest_from_file (name, hash);
4376                 mono_metadata_encode_value (20, b, &b);
4377                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4378                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4379                 g_free (name);
4380                 idx = table->next_idx++;
4381                 rsrc->offset = 0;
4382                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4383         } else {
4384                 char sizebuf [4];
4385                 char *data;
4386                 guint len;
4387                 if (rsrc->data) {
4388                         data = mono_array_addr (rsrc->data, char, 0);
4389                         len = mono_array_length (rsrc->data);
4390                 } else {
4391                         data = NULL;
4392                         len = 0;
4393                 }
4394                 offset = len;
4395                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4396                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4397                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4398                 mono_image_add_stream_data (&assembly->resources, data, len);
4399
4400                 if (!mb->is_main)
4401                         /* 
4402                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4403                          * the main module, but that needs to reference the FILE table
4404                          * which isn't emitted yet.
4405                          */
4406                         return;
4407                 else
4408                         idx = 0;
4409         }
4410
4411         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4412 }
4413
4414 static void
4415 set_version_from_string (MonoString *version, guint32 *values)
4416 {
4417         gchar *ver, *p, *str;
4418         guint32 i;
4419         
4420         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4421         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4422         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4423         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4424         if (!version)
4425                 return;
4426         ver = str = mono_string_to_utf8 (version);
4427         for (i = 0; i < 4; ++i) {
4428                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4429                 switch (*p) {
4430                 case '.':
4431                         p++;
4432                         break;
4433                 case '*':
4434                         /* handle Revision and Build */
4435                         p++;
4436                         break;
4437                 }
4438                 ver = p;
4439         }
4440         g_free (str);
4441 }
4442
4443 static guint32
4444 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4445         gsize len;
4446         guint32 token = 0;
4447         char blob_size [6];
4448         char *b = blob_size;
4449
4450         if (!pkey)
4451                 return token;
4452
4453         len = mono_array_length (pkey);
4454         mono_metadata_encode_value (len, b, &b);
4455         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4456         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4457
4458         assembly->public_key = g_malloc (len);
4459         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4460         assembly->public_key_len = len;
4461
4462         /* Special case: check for ECMA key (16 bytes) */
4463         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4464                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4465                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4466         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4467                 /* minimum key size (in 2.0) is 384 bits */
4468                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4469         } else {
4470                 /* FIXME - verifier */
4471                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4472                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4473         }
4474         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4475
4476         return token;
4477 }
4478
4479 static void
4480 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4481 {
4482         MonoDynamicTable *table;
4483         MonoDynamicImage *assembly;
4484         MonoReflectionAssemblyBuilder *assemblyb;
4485         MonoDomain *domain;
4486         guint32 *values;
4487         int i;
4488         guint32 module_index;
4489
4490         assemblyb = moduleb->assemblyb;
4491         assembly = moduleb->dynamic_image;
4492         domain = mono_object_domain (assemblyb);
4493
4494         /* Emit ASSEMBLY table */
4495         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4496         alloc_table (table, 1);
4497         values = table->values + MONO_ASSEMBLY_SIZE;
4498         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4499         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4500         if (assemblyb->culture) {
4501                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4502         } else {
4503                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4504         }
4505         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4506         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4507         set_version_from_string (assemblyb->version, values);
4508
4509         /* Emit FILE + EXPORTED_TYPE table */
4510         module_index = 0;
4511         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4512                 int j;
4513                 MonoReflectionModuleBuilder *file_module = 
4514                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4515                 if (file_module != moduleb) {
4516                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4517                         module_index ++;
4518                         if (file_module->types) {
4519                                 for (j = 0; j < file_module->num_types; ++j) {
4520                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4521                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4522                                 }
4523                         }
4524                 }
4525         }
4526         if (assemblyb->loaded_modules) {
4527                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4528                         MonoReflectionModule *file_module = 
4529                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4530                         mono_image_fill_file_table (domain, file_module, assembly);
4531                         module_index ++;
4532                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4533                 }
4534         }
4535         if (assemblyb->type_forwarders)
4536                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4537
4538         /* Emit MANIFESTRESOURCE table */
4539         module_index = 0;
4540         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4541                 int j;
4542                 MonoReflectionModuleBuilder *file_module = 
4543                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4544                 /* The table for the main module is emitted later */
4545                 if (file_module != moduleb) {
4546                         module_index ++;
4547                         if (file_module->resources) {
4548                                 int len = mono_array_length (file_module->resources);
4549                                 for (j = 0; j < len; ++j) {
4550                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4551                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4552                                 }
4553                         }
4554                 }
4555         }               
4556 }
4557
4558 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4559
4560 /*
4561  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4562  * for the modulebuilder @moduleb.
4563  * At the end of the process, method and field tokens are fixed up and the 
4564  * on-disk compressed metadata representation is created.
4565  */
4566 void
4567 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4568 {
4569         MonoDynamicTable *table;
4570         MonoDynamicImage *assembly;
4571         MonoReflectionAssemblyBuilder *assemblyb;
4572         MonoDomain *domain;
4573         MonoPtrArray types;
4574         guint32 *values;
4575         int i, j;
4576
4577         assemblyb = moduleb->assemblyb;
4578         assembly = moduleb->dynamic_image;
4579         domain = mono_object_domain (assemblyb);
4580
4581         if (assembly->text_rva)
4582                 return;
4583
4584         assembly->text_rva = START_TEXT_RVA;
4585
4586         if (moduleb->is_main) {
4587                 mono_image_emit_manifest (moduleb);
4588         }
4589
4590         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4591         table->rows = 1; /* .<Module> */
4592         table->next_idx++;
4593         alloc_table (table, table->rows);
4594         /*
4595          * Set the first entry.
4596          */
4597         values = table->values + table->columns;
4598         values [MONO_TYPEDEF_FLAGS] = 0;
4599         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4600         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4601         values [MONO_TYPEDEF_EXTENDS] = 0;
4602         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4603         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4604
4605         /* 
4606          * handle global methods 
4607          * FIXME: test what to do when global methods are defined in multiple modules.
4608          */
4609         if (moduleb->global_methods) {
4610                 table = &assembly->tables [MONO_TABLE_METHOD];
4611                 table->rows += mono_array_length (moduleb->global_methods);
4612                 alloc_table (table, table->rows);
4613                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4614                         mono_image_get_method_info (
4615                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4616         }
4617         if (moduleb->global_fields) {
4618                 table = &assembly->tables [MONO_TABLE_FIELD];
4619                 table->rows += mono_array_length (moduleb->global_fields);
4620                 alloc_table (table, table->rows);
4621                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4622                         mono_image_get_field_info (
4623                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4624         }
4625
4626         table = &assembly->tables [MONO_TABLE_MODULE];
4627         alloc_table (table, 1);
4628         mono_image_fill_module_table (domain, moduleb, assembly);
4629
4630         /* Collect all types into a list sorted by their table_idx */
4631         mono_ptr_array_init (types, moduleb->num_types);
4632
4633         if (moduleb->types)
4634                 for (i = 0; i < moduleb->num_types; ++i) {
4635                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4636                         collect_types (&types, type);
4637                 }
4638
4639         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4640         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4641         table->rows += mono_ptr_array_size (types);
4642         alloc_table (table, table->rows);
4643
4644         /*
4645          * Emit type names + namespaces at one place inside the string heap,
4646          * so load_class_names () needs to touch fewer pages.
4647          */
4648         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4649                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4650                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4651         }
4652         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4653                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4654                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4655         }
4656
4657         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4658                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4659                 mono_image_get_type_info (domain, type, assembly);
4660         }
4661
4662         /* 
4663          * table->rows is already set above and in mono_image_fill_module_table.
4664          */
4665         /* add all the custom attributes at the end, once all the indexes are stable */
4666         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4667
4668         /* CAS assembly permissions */
4669         if (assemblyb->permissions_minimum)
4670                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4671         if (assemblyb->permissions_optional)
4672                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4673         if (assemblyb->permissions_refused)
4674                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4675
4676         module_add_cattrs (assembly, moduleb);
4677
4678         /* fixup tokens */
4679         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4680
4681         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4682          * the final tokens and don't need another fixup pass. */
4683
4684         if (moduleb->global_methods) {
4685                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4686                         MonoReflectionMethodBuilder *mb = mono_array_get (
4687                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4688                         mono_image_add_methodimpl (assembly, mb);
4689                 }
4690         }
4691
4692         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4693                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4694                 if (type->methods) {
4695                         for (j = 0; j < type->num_methods; ++j) {
4696                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4697                                         type->methods, MonoReflectionMethodBuilder*, j);
4698
4699                                 mono_image_add_methodimpl (assembly, mb);
4700                         }
4701                 }
4702         }
4703
4704         mono_ptr_array_destroy (types);
4705
4706         fixup_cattrs (assembly);
4707 }
4708
4709 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4710
4711 void
4712 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4713 {
4714         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4715 }
4716
4717 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4718
4719
4720 typedef struct {
4721         guint32 import_lookup_table;
4722         guint32 timestamp;
4723         guint32 forwarder;
4724         guint32 name_rva;
4725         guint32 import_address_table_rva;
4726 } MonoIDT;
4727
4728 typedef struct {
4729         guint32 name_rva;
4730         guint32 flags;
4731 } MonoILT;
4732
4733 #ifndef DISABLE_REFLECTION_EMIT
4734
4735 /*
4736  * mono_image_insert_string:
4737  * @module: module builder object
4738  * @str: a string
4739  *
4740  * Insert @str into the user string stream of @module.
4741  */
4742 guint32
4743 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4744 {
4745         MonoDynamicImage *assembly;
4746         guint32 idx;
4747         char buf [16];
4748         char *b = buf;
4749         
4750         MONO_ARCH_SAVE_REGS;
4751
4752         if (!module->dynamic_image)
4753                 mono_image_module_basic_init (module);
4754
4755         assembly = module->dynamic_image;
4756         
4757         if (assembly->save) {
4758                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4759                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4760 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4761         {
4762                 char *swapped = g_malloc (2 * mono_string_length (str));
4763                 const char *p = (const char*)mono_string_chars (str);
4764
4765                 swap_with_size (swapped, p, 2, mono_string_length (str));
4766                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4767                 g_free (swapped);
4768         }
4769 #else
4770                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4771 #endif
4772                 mono_image_add_stream_data (&assembly->us, "", 1);
4773         } else {
4774                 idx = assembly->us.index ++;
4775         }
4776
4777         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4778
4779         return MONO_TOKEN_STRING | idx;
4780 }
4781
4782 guint32
4783 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4784 {
4785         MonoClass *klass;
4786         guint32 token = 0;
4787         MonoMethodSignature *sig;
4788
4789         klass = obj->vtable->klass;
4790         if (strcmp (klass->name, "MonoMethod") == 0) {
4791                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4792                 MonoMethodSignature *old;
4793                 guint32 sig_token, parent;
4794                 int nargs, i;
4795
4796                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4797
4798                 nargs = mono_array_length (opt_param_types);
4799                 old = mono_method_signature (method);
4800                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4801
4802                 sig->hasthis = old->hasthis;
4803                 sig->explicit_this = old->explicit_this;
4804                 sig->call_convention = old->call_convention;
4805                 sig->generic_param_count = old->generic_param_count;
4806                 sig->param_count = old->param_count + nargs;
4807                 sig->sentinelpos = old->param_count;
4808                 sig->ret = old->ret;
4809
4810                 for (i = 0; i < old->param_count; i++)
4811                         sig->params [i] = old->params [i];
4812
4813                 for (i = 0; i < nargs; i++) {
4814                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4815                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4816                 }
4817
4818                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4819                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4820                 parent >>= MONO_TYPEDEFORREF_BITS;
4821
4822                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4823                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4824
4825                 sig_token = method_encode_signature (assembly, sig);
4826                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4827         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4828                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4829                 ReflectionMethodBuilder rmb;
4830                 guint32 parent, sig_token;
4831                 int nopt_args, nparams, ngparams, i;
4832                 char *name;
4833
4834                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4835                 rmb.opt_types = opt_param_types;
4836                 nopt_args = mono_array_length (opt_param_types);
4837
4838                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4839                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4840                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4841
4842                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4843                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4844                 sig->call_convention = rmb.call_conv;
4845                 sig->generic_param_count = ngparams;
4846                 sig->param_count = nparams + nopt_args;
4847                 sig->sentinelpos = nparams;
4848                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4849
4850                 for (i = 0; i < nparams; i++) {
4851                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4852                         sig->params [i] = mono_reflection_type_get_handle (rt);
4853                 }
4854
4855                 for (i = 0; i < nopt_args; i++) {
4856                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4857                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4858                 }
4859
4860                 sig_token = method_builder_encode_signature (assembly, &rmb);
4861
4862                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4863                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4864
4865                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4866                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4867
4868                 name = mono_string_to_utf8 (rmb.name);
4869                 token = mono_image_get_varargs_method_token (
4870                         assembly, parent, name, sig_token);
4871                 g_free (name);
4872         } else {
4873                 g_error ("requested method token for %s\n", klass->name);
4874         }
4875
4876         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4877         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4878         return token;
4879 }
4880
4881 /*
4882  * mono_image_create_token:
4883  * @assembly: a dynamic assembly
4884  * @obj:
4885  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4886  *
4887  * Get a token to insert in the IL code stream for the given MemberInfo.
4888  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4889  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4890  * entry.
4891  */
4892 guint32
4893 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4894                                                  gboolean create_open_instance, gboolean register_token)
4895 {
4896         MonoClass *klass;
4897         guint32 token = 0;
4898
4899         klass = obj->vtable->klass;
4900
4901         /* Check for user defined reflection objects */
4902         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4903         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4904                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4905
4906         if (strcmp (klass->name, "MethodBuilder") == 0) {
4907                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4908                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4909
4910                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4911                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4912                 else
4913                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4914                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4915         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4916                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4917                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4918
4919                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4920                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4921                 else
4922                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4923                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4924         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4925                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4926                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4927                 if (tb->generic_params) {
4928                         token = mono_image_get_generic_field_token (assembly, fb);
4929                 } else {
4930                         if ((tb->module->dynamic_image == assembly)) {
4931                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4932                         } else {
4933                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4934                         }
4935                 }
4936         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4937                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4938                 if (create_open_instance && tb->generic_params) {
4939                         MonoType *type;
4940                         init_type_builder_generics (obj);
4941                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4942                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4943                         token = mono_metadata_token_from_dor (token);
4944                 } else {
4945                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4946                 }
4947         } else if (strcmp (klass->name, "MonoType") == 0) {
4948                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4949                 MonoClass *mc = mono_class_from_mono_type (type);
4950                 token = mono_metadata_token_from_dor (
4951                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4952         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4953                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4954                 token = mono_metadata_token_from_dor (
4955                         mono_image_typedef_or_ref (assembly, type));
4956         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4957                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4958                 token = mono_metadata_token_from_dor (
4959                         mono_image_typedef_or_ref (assembly, type));
4960         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4961                    strcmp (klass->name, "MonoMethod") == 0 ||
4962                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4963                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4964                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4965                 if (m->method->is_inflated) {
4966                         if (create_open_instance)
4967                                 token = mono_image_get_methodspec_token (assembly, m->method);
4968                         else
4969                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4970                 } else if ((m->method->klass->image == &assembly->image) &&
4971                          !m->method->klass->generic_class) {
4972                         static guint32 method_table_idx = 0xffffff;
4973                         if (m->method->klass->wastypebuilder) {
4974                                 /* we use the same token as the one that was assigned
4975                                  * to the Methodbuilder.
4976                                  * FIXME: do the equivalent for Fields.
4977                                  */
4978                                 token = m->method->token;
4979                         } else {
4980                                 /*
4981                                  * Each token should have a unique index, but the indexes are
4982                                  * assigned by managed code, so we don't know about them. An
4983                                  * easy solution is to count backwards...
4984                                  */
4985                                 method_table_idx --;
4986                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4987                         }
4988                 } else {
4989                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4990                 }
4991                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4992         } else if (strcmp (klass->name, "MonoField") == 0) {
4993                 MonoReflectionField *f = (MonoReflectionField *)obj;
4994                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4995                         static guint32 field_table_idx = 0xffffff;
4996                         field_table_idx --;
4997                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4998                 } else {
4999                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5000                 }
5001                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5002         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5003                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5004                 token = mono_image_get_array_token (assembly, m);
5005         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5006                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5007                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5008         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5009                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5010                 token = mono_metadata_token_from_dor (
5011                         mono_image_typedef_or_ref (assembly, type));
5012         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5013                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5014                 token = mono_image_get_field_on_inst_token (assembly, f);
5015         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5016                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5017                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5018         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5019                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5020                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5021         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5022                 MonoReflectionType *type = (MonoReflectionType *)obj;
5023                 token = mono_metadata_token_from_dor (
5024                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5025         } else {
5026                 g_error ("requested token for %s\n", klass->name);
5027         }
5028
5029         if (register_token)
5030                 mono_image_register_token (assembly, token, obj);
5031
5032         return token;
5033 }
5034
5035 /*
5036  * mono_image_register_token:
5037  *
5038  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5039  * the Module.ResolveXXXToken () methods to work.
5040  */
5041 void
5042 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5043 {
5044         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5045         if (prev) {
5046                 /* There could be multiple MethodInfo objects with the same token */
5047                 //g_assert (prev == obj);
5048         } else {
5049                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5050         }
5051 }
5052
5053 static MonoDynamicImage*
5054 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5055 {
5056         static const guchar entrycode [16] = {0xff, 0x25, 0};
5057         MonoDynamicImage *image;
5058         int i;
5059
5060         const char *version;
5061
5062         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5063                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5064         else
5065                 version = mono_get_runtime_info ()->runtime_version;
5066
5067 #if HAVE_BOEHM_GC
5068         /* The MonoGHashTable's need GC tracking */
5069         image = GC_MALLOC (sizeof (MonoDynamicImage));
5070 #else
5071         image = g_new0 (MonoDynamicImage, 1);
5072 #endif
5073         
5074         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5075         
5076         /*g_print ("created image %p\n", image);*/
5077         /* keep in sync with image.c */
5078         image->image.name = assembly_name;
5079         image->image.assembly_name = image->image.name; /* they may be different */
5080         image->image.module_name = module_name;
5081         image->image.version = g_strdup (version);
5082         image->image.md_version_major = 1;
5083         image->image.md_version_minor = 1;
5084         image->image.dynamic = TRUE;
5085
5086         image->image.references = g_new0 (MonoAssembly*, 1);
5087         image->image.references [0] = NULL;
5088
5089         mono_image_init (&image->image);
5090
5091         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5092         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5093         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5094         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5095         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5096         image->handleref = g_hash_table_new (NULL, NULL);
5097         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5098         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5099         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5100         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5101         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5102         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5103         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5104         image->gen_params = g_ptr_array_new ();
5105
5106         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5107         string_heap_init (&image->sheap);
5108         mono_image_add_stream_data (&image->us, "", 1);
5109         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5110         /* import tables... */
5111         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5112         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5113         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5114         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5115         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5116         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5117         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5118         stream_data_align (&image->code);
5119
5120         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5121
5122         for (i=0; i < MONO_TABLE_NUM; ++i) {
5123                 image->tables [i].next_idx = 1;
5124                 image->tables [i].columns = table_sizes [i];
5125         }
5126
5127         image->image.assembly = (MonoAssembly*)assembly;
5128         image->run = assembly->run;
5129         image->save = assembly->save;
5130         image->pe_kind = 0x1; /* ILOnly */
5131         image->machine = 0x14c; /* I386 */
5132         
5133         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5134
5135         return image;
5136 }
5137 #endif
5138
5139 static void
5140 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5141 {
5142         g_free (key);
5143 }
5144
5145 void
5146 mono_dynamic_image_free (MonoDynamicImage *image)
5147 {
5148         MonoDynamicImage *di = image;
5149         GList *list;
5150         int i;
5151
5152         if (di->methodspec)
5153                 mono_g_hash_table_destroy (di->methodspec);
5154         if (di->typespec)
5155                 g_hash_table_destroy (di->typespec);
5156         if (di->typeref)
5157                 g_hash_table_destroy (di->typeref);
5158         if (di->handleref)
5159                 g_hash_table_destroy (di->handleref);
5160         if (di->handleref_managed)
5161                 mono_g_hash_table_destroy (di->handleref_managed);
5162         if (di->tokens)
5163                 mono_g_hash_table_destroy (di->tokens);
5164         if (di->generic_def_objects)
5165                 mono_g_hash_table_destroy (di->generic_def_objects);
5166         if (di->blob_cache) {
5167                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5168                 g_hash_table_destroy (di->blob_cache);
5169         }
5170         if (di->standalonesig_cache)
5171                 g_hash_table_destroy (di->standalonesig_cache);
5172         for (list = di->array_methods; list; list = list->next) {
5173                 ArrayMethod *am = (ArrayMethod *)list->data;
5174                 g_free (am->sig);
5175                 g_free (am->name);
5176                 g_free (am);
5177         }
5178         g_list_free (di->array_methods);
5179         if (di->gen_params) {
5180                 for (i = 0; i < di->gen_params->len; i++) {
5181                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5182                         mono_gc_deregister_root ((char*) &entry->gparam);
5183                         g_free (entry);
5184                 }
5185                 g_ptr_array_free (di->gen_params, TRUE);
5186         }
5187         if (di->token_fixups)
5188                 mono_g_hash_table_destroy (di->token_fixups);
5189         if (di->method_to_table_idx)
5190                 g_hash_table_destroy (di->method_to_table_idx);
5191         if (di->field_to_table_idx)
5192                 g_hash_table_destroy (di->field_to_table_idx);
5193         if (di->method_aux_hash)
5194                 g_hash_table_destroy (di->method_aux_hash);
5195         if (di->vararg_aux_hash)
5196                 g_hash_table_destroy (di->vararg_aux_hash);
5197         g_free (di->strong_name);
5198         g_free (di->win32_res);
5199         if (di->public_key)
5200                 g_free (di->public_key);
5201
5202         /*g_print ("string heap destroy for image %p\n", di);*/
5203         mono_dynamic_stream_reset (&di->sheap);
5204         mono_dynamic_stream_reset (&di->code);
5205         mono_dynamic_stream_reset (&di->resources);
5206         mono_dynamic_stream_reset (&di->us);
5207         mono_dynamic_stream_reset (&di->blob);
5208         mono_dynamic_stream_reset (&di->tstream);
5209         mono_dynamic_stream_reset (&di->guid);
5210         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5211                 g_free (di->tables [i].values);
5212         }
5213 }       
5214
5215 #ifndef DISABLE_REFLECTION_EMIT
5216
5217 /*
5218  * mono_image_basic_init:
5219  * @assembly: an assembly builder object
5220  *
5221  * Create the MonoImage that represents the assembly builder and setup some
5222  * of the helper hash table and the basic metadata streams.
5223  */
5224 void
5225 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5226 {
5227         MonoDynamicAssembly *assembly;
5228         MonoDynamicImage *image;
5229         MonoDomain *domain = mono_object_domain (assemblyb);
5230         
5231         MONO_ARCH_SAVE_REGS;
5232
5233         if (assemblyb->dynamic_assembly)
5234                 return;
5235
5236 #if HAVE_BOEHM_GC
5237         /* assembly->assembly.image might be GC allocated */
5238         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5239 #else
5240         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5241 #endif
5242
5243         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5244         
5245         assembly->assembly.ref_count = 1;
5246         assembly->assembly.dynamic = TRUE;
5247         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5248         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5249         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5250         if (assemblyb->culture)
5251                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5252         else
5253                 assembly->assembly.aname.culture = g_strdup ("");
5254
5255         if (assemblyb->version) {
5256                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5257                         char **version = g_strsplit (vstr, ".", 4);
5258                         char **parts = version;
5259                         assembly->assembly.aname.major = atoi (*parts++);
5260                         assembly->assembly.aname.minor = atoi (*parts++);
5261                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5262                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5263
5264                         g_strfreev (version);
5265                         g_free (vstr);
5266         } else {
5267                         assembly->assembly.aname.major = 0;
5268                         assembly->assembly.aname.minor = 0;
5269                         assembly->assembly.aname.build = 0;
5270                         assembly->assembly.aname.revision = 0;
5271         }
5272
5273         assembly->run = assemblyb->access != 2;
5274         assembly->save = assemblyb->access != 1;
5275         assembly->domain = domain;
5276
5277         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5278         image->initial_image = TRUE;
5279         assembly->assembly.aname.name = image->image.name;
5280         assembly->assembly.image = &image->image;
5281         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5282                 /* -1 to correct for the trailing NULL byte */
5283                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5284                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5285                 }
5286                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5287         }
5288
5289         mono_domain_assemblies_lock (domain);
5290         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5291         mono_domain_assemblies_unlock (domain);
5292
5293         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5294         
5295         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5296         
5297         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5298 }
5299
5300 #endif /* !DISABLE_REFLECTION_EMIT */
5301
5302 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5303
5304 static int
5305 calc_section_size (MonoDynamicImage *assembly)
5306 {
5307         int nsections = 0;
5308
5309         /* alignment constraints */
5310         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5311         g_assert ((assembly->code.index % 4) == 0);
5312         assembly->meta_size += 3;
5313         assembly->meta_size &= ~3;
5314         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5315         g_assert ((assembly->resources.index % 4) == 0);
5316
5317         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5318         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5319         nsections++;
5320
5321         if (assembly->win32_res) {
5322                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5323
5324                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5325                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5326                 nsections++;
5327         }
5328
5329         assembly->sections [MONO_SECTION_RELOC].size = 12;
5330         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5331         nsections++;
5332
5333         return nsections;
5334 }
5335
5336 typedef struct {
5337         guint32 id;
5338         guint32 offset;
5339         GSList *children;
5340         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5341 } ResTreeNode;
5342
5343 static int
5344 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5345 {
5346         ResTreeNode *t1 = (ResTreeNode*)a;
5347         ResTreeNode *t2 = (ResTreeNode*)b;
5348
5349         return t1->id - t2->id;
5350 }
5351
5352 /*
5353  * resource_tree_create:
5354  *
5355  *  Organize the resources into a resource tree.
5356  */
5357 static ResTreeNode *
5358 resource_tree_create (MonoArray *win32_resources)
5359 {
5360         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5361         GSList *l;
5362         int i;
5363
5364         tree = g_new0 (ResTreeNode, 1);
5365         
5366         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5367                 MonoReflectionWin32Resource *win32_res =
5368                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5369
5370                 /* Create node */
5371
5372                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5373                 lang_node = g_new0 (ResTreeNode, 1);
5374                 lang_node->id = win32_res->lang_id;
5375                 lang_node->win32_res = win32_res;
5376
5377                 /* Create type node if neccesary */
5378                 type_node = NULL;
5379                 for (l = tree->children; l; l = l->next)
5380                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5381                                 type_node = (ResTreeNode*)l->data;
5382                                 break;
5383                         }
5384
5385                 if (!type_node) {
5386                         type_node = g_new0 (ResTreeNode, 1);
5387                         type_node->id = win32_res->res_type;
5388
5389                         /* 
5390                          * The resource types have to be sorted otherwise
5391                          * Windows Explorer can't display the version information.
5392                          */
5393                         tree->children = g_slist_insert_sorted (tree->children, 
5394                                 type_node, resource_tree_compare_by_id);
5395                 }
5396
5397                 /* Create res node if neccesary */
5398                 res_node = NULL;
5399                 for (l = type_node->children; l; l = l->next)
5400                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5401                                 res_node = (ResTreeNode*)l->data;
5402                                 break;
5403                         }
5404
5405                 if (!res_node) {
5406                         res_node = g_new0 (ResTreeNode, 1);
5407                         res_node->id = win32_res->res_id;
5408                         type_node->children = g_slist_append (type_node->children, res_node);
5409                 }
5410
5411                 res_node->children = g_slist_append (res_node->children, lang_node);
5412         }
5413
5414         return tree;
5415 }
5416
5417 /*
5418  * resource_tree_encode:
5419  * 
5420  *   Encode the resource tree into the format used in the PE file.
5421  */
5422 static void
5423 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5424 {
5425         char *entries;
5426         MonoPEResourceDir dir;
5427         MonoPEResourceDirEntry dir_entry;
5428         MonoPEResourceDataEntry data_entry;
5429         GSList *l;
5430         guint32 res_id_entries;
5431
5432         /*
5433          * For the format of the resource directory, see the article
5434          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5435          * Matt Pietrek
5436          */
5437
5438         memset (&dir, 0, sizeof (dir));
5439         memset (&dir_entry, 0, sizeof (dir_entry));
5440         memset (&data_entry, 0, sizeof (data_entry));
5441
5442         g_assert (sizeof (dir) == 16);
5443         g_assert (sizeof (dir_entry) == 8);
5444         g_assert (sizeof (data_entry) == 16);
5445
5446         node->offset = p - begin;
5447
5448         /* IMAGE_RESOURCE_DIRECTORY */
5449         res_id_entries = g_slist_length (node->children);
5450         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5451
5452         memcpy (p, &dir, sizeof (dir));
5453         p += sizeof (dir);
5454
5455         /* Reserve space for entries */
5456         entries = p;
5457         p += sizeof (dir_entry) * res_id_entries;
5458
5459         /* Write children */
5460         for (l = node->children; l; l = l->next) {
5461                 ResTreeNode *child = (ResTreeNode*)l->data;
5462
5463                 if (child->win32_res) {
5464                         guint32 size;
5465
5466                         child->offset = p - begin;
5467
5468                         /* IMAGE_RESOURCE_DATA_ENTRY */
5469                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5470                         size = mono_array_length (child->win32_res->res_data);
5471                         data_entry.rde_size = GUINT32_TO_LE (size);
5472
5473                         memcpy (p, &data_entry, sizeof (data_entry));
5474                         p += sizeof (data_entry);
5475
5476                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5477                         p += size;
5478                 } else {
5479                         resource_tree_encode (child, begin, p, &p);
5480                 }
5481         }
5482
5483         /* IMAGE_RESOURCE_ENTRY */
5484         for (l = node->children; l; l = l->next) {
5485                 ResTreeNode *child = (ResTreeNode*)l->data;
5486
5487                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5488                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5489
5490                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5491                 entries += sizeof (dir_entry);
5492         }
5493
5494         *endbuf = p;
5495 }
5496
5497 static void
5498 resource_tree_free (ResTreeNode * node)
5499 {
5500         GSList * list;
5501         for (list = node->children; list; list = list->next)
5502                 resource_tree_free ((ResTreeNode*)list->data);
5503         g_slist_free(node->children);
5504         g_free (node);
5505 }
5506
5507 static void
5508 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5509 {
5510         char *buf;
5511         char *p;
5512         guint32 size, i;
5513         MonoReflectionWin32Resource *win32_res;
5514         ResTreeNode *tree;
5515
5516         if (!assemblyb->win32_resources)
5517                 return;
5518
5519         /*
5520          * Resources are stored in a three level tree inside the PE file.
5521          * - level one contains a node for each type of resource
5522          * - level two contains a node for each resource
5523          * - level three contains a node for each instance of a resource for a
5524          *   specific language.
5525          */
5526
5527         tree = resource_tree_create (assemblyb->win32_resources);
5528
5529         /* Estimate the size of the encoded tree */
5530         size = 0;
5531         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5532                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5533                 size += mono_array_length (win32_res->res_data);
5534         }
5535         /* Directory structure */
5536         size += mono_array_length (assemblyb->win32_resources) * 256;
5537         p = buf = g_malloc (size);
5538
5539         resource_tree_encode (tree, p, p, &p);
5540
5541         g_assert (p - buf <= size);
5542
5543         assembly->win32_res = g_malloc (p - buf);
5544         assembly->win32_res_size = p - buf;
5545         memcpy (assembly->win32_res, buf, p - buf);
5546
5547         g_free (buf);
5548         resource_tree_free (tree);
5549 }
5550
5551 static void
5552 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5553 {
5554         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5555         int i;
5556
5557         p += sizeof (MonoPEResourceDir);
5558         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5559                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5560                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5561                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5562                         fixup_resource_directory (res_section, child, rva);
5563                 } else {
5564                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5565                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5566                 }
5567
5568                 p += sizeof (MonoPEResourceDirEntry);
5569         }
5570 }
5571
5572 static void
5573 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5574 {
5575         guint32 dummy;
5576         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5577                 g_error ("WriteFile returned %d\n", GetLastError ());
5578 }
5579
5580 /*
5581  * mono_image_create_pefile:
5582  * @mb: a module builder object
5583  * 
5584  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5585  * assembly->pefile where it can be easily retrieved later in chunks.
5586  */
5587 void
5588 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5589 {
5590         MonoMSDOSHeader *msdos;
5591         MonoDotNetHeader *header;
5592         MonoSectionTable *section;
5593         MonoCLIHeader *cli_header;
5594         guint32 size, image_size, virtual_base, text_offset;
5595         guint32 header_start, section_start, file_offset, virtual_offset;
5596         MonoDynamicImage *assembly;
5597         MonoReflectionAssemblyBuilder *assemblyb;
5598         MonoDynamicStream pefile_stream = {0};
5599         MonoDynamicStream *pefile = &pefile_stream;
5600         int i, nsections;
5601         guint32 *rva, value;
5602         guchar *p;
5603         static const unsigned char msheader[] = {
5604                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5605                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5606                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5607                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5608                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5609                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5610                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5611                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5612         };
5613
5614         assemblyb = mb->assemblyb;
5615
5616         mono_image_basic_init (assemblyb);
5617         assembly = mb->dynamic_image;
5618
5619         assembly->pe_kind = assemblyb->pe_kind;
5620         assembly->machine = assemblyb->machine;
5621         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5622         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5623         
5624         mono_image_build_metadata (mb);
5625
5626         if (mb->is_main && assemblyb->resources) {
5627                 int len = mono_array_length (assemblyb->resources);
5628                 for (i = 0; i < len; ++i)
5629                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5630         }
5631
5632         if (mb->resources) {
5633                 int len = mono_array_length (mb->resources);
5634                 for (i = 0; i < len; ++i)
5635                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5636         }
5637
5638         build_compressed_metadata (assembly);
5639
5640         if (mb->is_main)
5641                 assembly_add_win32_resources (assembly, assemblyb);
5642
5643         nsections = calc_section_size (assembly);
5644         
5645         /* The DOS header and stub */
5646         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5647         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5648
5649         /* the dotnet header */
5650         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5651
5652         /* the section tables */
5653         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5654
5655         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5656         virtual_offset = VIRT_ALIGN;
5657         image_size = 0;
5658
5659         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5660                 if (!assembly->sections [i].size)
5661                         continue;
5662                 /* align offsets */
5663                 file_offset += FILE_ALIGN - 1;
5664                 file_offset &= ~(FILE_ALIGN - 1);
5665                 virtual_offset += VIRT_ALIGN - 1;
5666                 virtual_offset &= ~(VIRT_ALIGN - 1);
5667
5668                 assembly->sections [i].offset = file_offset;
5669                 assembly->sections [i].rva = virtual_offset;
5670
5671                 file_offset += assembly->sections [i].size;
5672                 virtual_offset += assembly->sections [i].size;
5673                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5674         }
5675
5676         file_offset += FILE_ALIGN - 1;
5677         file_offset &= ~(FILE_ALIGN - 1);
5678
5679         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5680
5681         /* back-patch info */
5682         msdos = (MonoMSDOSHeader*)pefile->data;
5683         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5684
5685         header = (MonoDotNetHeader*)(pefile->data + header_start);
5686         header->pesig [0] = 'P';
5687         header->pesig [1] = 'E';
5688         
5689         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5690         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5691         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5692         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5693         if (assemblyb->pekind == 1) {
5694                 /* it's a dll */
5695                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5696         } else {
5697                 /* it's an exe */
5698                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5699         }
5700
5701         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5702
5703         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5704         header->pe.pe_major = 6;
5705         header->pe.pe_minor = 0;
5706         size = assembly->sections [MONO_SECTION_TEXT].size;
5707         size += FILE_ALIGN - 1;
5708         size &= ~(FILE_ALIGN - 1);
5709         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5710         size = assembly->sections [MONO_SECTION_RSRC].size;
5711         size += FILE_ALIGN - 1;
5712         size &= ~(FILE_ALIGN - 1);
5713         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5714         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5715         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5716         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5717         /* pe_rva_entry_point always at the beginning of the text section */
5718         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5719
5720         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5721         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5722         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5723         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5724         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5725         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5726         size = section_start;
5727         size += FILE_ALIGN - 1;
5728         size &= ~(FILE_ALIGN - 1);
5729         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5730         size = image_size;
5731         size += VIRT_ALIGN - 1;
5732         size &= ~(VIRT_ALIGN - 1);
5733         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5734
5735         /*
5736         // Translate the PEFileKind value to the value expected by the Windows loader
5737         */
5738         {
5739                 short kind;
5740
5741                 /*
5742                 // PEFileKinds.Dll == 1
5743                 // PEFileKinds.ConsoleApplication == 2
5744                 // PEFileKinds.WindowApplication == 3
5745                 //
5746                 // need to get:
5747                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5748                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5749                 */
5750                 if (assemblyb->pekind == 3)
5751                         kind = 2;
5752                 else
5753                         kind = 3;
5754                 
5755                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5756         }    
5757         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5758         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5759         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5760         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5761         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5762         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5763
5764         /* fill data directory entries */
5765
5766         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5767         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5768
5769         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5770         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5771
5772         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5773         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5774         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5775         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5776         /* patch entrypoint name */
5777         if (assemblyb->pekind == 1)
5778                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5779         else
5780                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5781         /* patch imported function RVA name */
5782         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5783         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5784
5785         /* the import table */
5786         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5787         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5788         /* patch imported dll RVA name and other entries in the dir */
5789         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5790         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5791         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5792         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5793         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5794         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5795
5796         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5797         value = (assembly->text_rva + assembly->imp_names_offset);
5798         *p++ = (value) & 0xff;
5799         *p++ = (value >> 8) & (0xff);
5800         *p++ = (value >> 16) & (0xff);
5801         *p++ = (value >> 24) & (0xff);
5802
5803         /* the CLI header info */
5804         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5805         cli_header->ch_size = GUINT32_FROM_LE (72);
5806         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5807         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5808         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5809         if (assemblyb->entry_point) {
5810                 guint32 table_idx = 0;
5811                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5812                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5813                         table_idx = methodb->table_idx;
5814                 } else {
5815                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5816                 }
5817                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5818         } else {
5819                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5820         }
5821         /* The embedded managed resources */
5822         text_offset = assembly->text_rva + assembly->code.index;
5823         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5824         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5825         text_offset += assembly->resources.index;
5826         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5827         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5828         text_offset += assembly->meta_size;
5829         if (assembly->strong_name_size) {
5830                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5831                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5832                 text_offset += assembly->strong_name_size;
5833         }
5834
5835         /* write the section tables and section content */
5836         section = (MonoSectionTable*)(pefile->data + section_start);
5837         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5838                 static const char section_names [][7] = {
5839                         ".text", ".rsrc", ".reloc"
5840                 };
5841                 if (!assembly->sections [i].size)
5842                         continue;
5843                 strcpy (section->st_name, section_names [i]);
5844                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5845                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5846                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5847                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5848                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5849                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5850                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5851                 section ++;
5852         }
5853         
5854         checked_write_file (file, pefile->data, pefile->index);
5855         
5856         mono_dynamic_stream_reset (pefile);
5857         
5858         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5859                 if (!assembly->sections [i].size)
5860                         continue;
5861                 
5862                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5863                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5864                 
5865                 switch (i) {
5866                 case MONO_SECTION_TEXT:
5867                         /* patch entry point */
5868                         p = (guchar*)(assembly->code.data + 2);
5869                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5870                         *p++ = (value) & 0xff;
5871                         *p++ = (value >> 8) & 0xff;
5872                         *p++ = (value >> 16) & 0xff;
5873                         *p++ = (value >> 24) & 0xff;
5874                 
5875                         checked_write_file (file, assembly->code.data, assembly->code.index);
5876                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5877                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5878                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5879                                 
5880
5881                         g_free (assembly->image.raw_metadata);
5882                         break;
5883                 case MONO_SECTION_RELOC: {
5884                         struct {
5885                                 guint32 page_rva;
5886                                 guint32 block_size;
5887                                 guint16 type_and_offset;
5888                                 guint16 term;
5889                         } reloc;
5890                         
5891                         g_assert (sizeof (reloc) == 12);
5892                         
5893                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5894                         reloc.block_size = GUINT32_FROM_LE (12);
5895                         
5896                         /* 
5897                          * the entrypoint is always at the start of the text section 
5898                          * 3 is IMAGE_REL_BASED_HIGHLOW
5899                          * 2 is patch_size_rva - text_rva
5900                          */
5901                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5902                         reloc.term = 0;
5903                         
5904                         checked_write_file (file, &reloc, sizeof (reloc));
5905                         
5906                         break;
5907                 }
5908                 case MONO_SECTION_RSRC:
5909                         if (assembly->win32_res) {
5910
5911                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5912                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5913                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5914                         }
5915                         break;
5916                 default:
5917                         g_assert_not_reached ();
5918                 }
5919         }
5920         
5921         /* check that the file is properly padded */
5922         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5923                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5924         if (! SetEndOfFile (file))
5925                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5926         
5927         mono_dynamic_stream_reset (&assembly->code);
5928         mono_dynamic_stream_reset (&assembly->us);
5929         mono_dynamic_stream_reset (&assembly->blob);
5930         mono_dynamic_stream_reset (&assembly->guid);
5931         mono_dynamic_stream_reset (&assembly->sheap);
5932
5933         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5934         g_hash_table_destroy (assembly->blob_cache);
5935         assembly->blob_cache = NULL;
5936 }
5937
5938 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5939
5940 void
5941 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5942 {
5943         g_assert_not_reached ();
5944 }
5945
5946 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5947
5948 #ifndef DISABLE_REFLECTION_EMIT
5949
5950 MonoReflectionModule *
5951 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5952 {
5953         char *name;
5954         MonoImage *image;
5955         MonoImageOpenStatus status;
5956         MonoDynamicAssembly *assembly;
5957         guint32 module_count;
5958         MonoImage **new_modules;
5959         gboolean *new_modules_loaded;
5960         
5961         name = mono_string_to_utf8 (fileName);
5962
5963         image = mono_image_open (name, &status);
5964         if (!image) {
5965                 MonoException *exc;
5966                 if (status == MONO_IMAGE_ERROR_ERRNO)
5967                         exc = mono_get_exception_file_not_found (fileName);
5968                 else
5969                         exc = mono_get_exception_bad_image_format (name);
5970                 g_free (name);
5971                 mono_raise_exception (exc);
5972         }
5973
5974         g_free (name);
5975
5976         assembly = ab->dynamic_assembly;
5977         image->assembly = (MonoAssembly*)assembly;
5978
5979         module_count = image->assembly->image->module_count;
5980         new_modules = g_new0 (MonoImage *, module_count + 1);
5981         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5982
5983         if (image->assembly->image->modules)
5984                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5985         if (image->assembly->image->modules_loaded)
5986                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5987         new_modules [module_count] = image;
5988         new_modules_loaded [module_count] = TRUE;
5989         mono_image_addref (image);
5990
5991         g_free (image->assembly->image->modules);
5992         image->assembly->image->modules = new_modules;
5993         image->assembly->image->modules_loaded = new_modules_loaded;
5994         image->assembly->image->module_count ++;
5995
5996         mono_assembly_load_references (image, &status);
5997         if (status) {
5998                 mono_image_close (image);
5999                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6000         }
6001
6002         return mono_module_get_object (mono_domain_get (), image);
6003 }
6004
6005 #endif /* DISABLE_REFLECTION_EMIT */
6006
6007 /*
6008  * We need to return always the same object for MethodInfo, FieldInfo etc..
6009  * but we need to consider the reflected type.
6010  * type uses a different hash, since it uses custom hash/equal functions.
6011  */
6012
6013 typedef struct {
6014         gpointer item;
6015         MonoClass *refclass;
6016 } ReflectedEntry;
6017
6018 static gboolean
6019 reflected_equal (gconstpointer a, gconstpointer b) {
6020         const ReflectedEntry *ea = a;
6021         const ReflectedEntry *eb = b;
6022
6023         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6024 }
6025
6026 static guint
6027 reflected_hash (gconstpointer a) {
6028         const ReflectedEntry *ea = a;
6029         return mono_aligned_addr_hash (ea->item);
6030 }
6031
6032 #define CHECK_OBJECT(t,p,k)     \
6033         do {    \
6034                 t _obj; \
6035                 ReflectedEntry e;       \
6036                 e.item = (p);   \
6037                 e.refclass = (k);       \
6038                 mono_domain_lock (domain);      \
6039                 if (!domain->refobject_hash)    \
6040                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6041                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6042                         mono_domain_unlock (domain);    \
6043                         return _obj;    \
6044                 }       \
6045         mono_domain_unlock (domain); \
6046         } while (0)
6047
6048 #ifdef HAVE_BOEHM_GC
6049 /* ReflectedEntry doesn't need to be GC tracked */
6050 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6051 #define FREE_REFENTRY(entry) g_free ((entry))
6052 #define REFENTRY_REQUIRES_CLEANUP
6053 #else
6054 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6055 /* FIXME: */
6056 #define FREE_REFENTRY(entry)
6057 #endif
6058
6059 #define CACHE_OBJECT(t,p,o,k)   \
6060         do {    \
6061                 t _obj; \
6062         ReflectedEntry pe; \
6063         pe.item = (p); \
6064         pe.refclass = (k); \
6065         mono_domain_lock (domain); \
6066                 if (!domain->refobject_hash)    \
6067                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6068         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6069         if (!_obj) { \
6070                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6071                     e->item = (p);      \
6072                     e->refclass = (k);  \
6073                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6074             _obj = o; \
6075         } \
6076                 mono_domain_unlock (domain);    \
6077         return _obj; \
6078         } while (0)
6079
6080 static void
6081 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6082 {
6083         mono_domain_lock (domain);
6084         if (domain->refobject_hash) {
6085         ReflectedEntry pe;
6086                 gpointer orig_pe, orig_value;
6087
6088                 pe.item = o;
6089                 pe.refclass = klass;
6090                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6091                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6092                         FREE_REFENTRY (orig_pe);
6093                 }
6094         }
6095         mono_domain_unlock (domain);
6096 }
6097
6098 #ifdef REFENTRY_REQUIRES_CLEANUP
6099 static void
6100 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6101 {
6102         FREE_REFENTRY (key);
6103 }
6104 #endif
6105
6106 void
6107 mono_reflection_cleanup_domain (MonoDomain *domain)
6108 {
6109         if (domain->refobject_hash) {
6110 /*let's avoid scanning the whole hashtable if not needed*/
6111 #ifdef REFENTRY_REQUIRES_CLEANUP
6112                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6113 #endif
6114                 mono_g_hash_table_destroy (domain->refobject_hash);
6115                 domain->refobject_hash = NULL;
6116         }
6117 }
6118
6119 #ifndef DISABLE_REFLECTION_EMIT
6120 static gpointer
6121 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6122 {
6123         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6124 }
6125
6126 static gpointer
6127 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6128 {
6129         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6130 }
6131
6132 void
6133 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6134 {
6135         MonoDynamicImage *image = moduleb->dynamic_image;
6136         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6137         if (!image) {
6138                 MonoError error;
6139                 int module_count;
6140                 MonoImage **new_modules;
6141                 MonoImage *ass;
6142                 char *name, *fqname;
6143                 /*
6144                  * FIXME: we already created an image in mono_image_basic_init (), but
6145                  * we don't know which module it belongs to, since that is only 
6146                  * determined at assembly save time.
6147                  */
6148                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6149                 name = mono_string_to_utf8 (ab->name);
6150                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6151                 if (!mono_error_ok (&error)) {
6152                         g_free (name);
6153                         mono_error_raise_exception (&error);
6154                 }
6155                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6156
6157                 moduleb->module.image = &image->image;
6158                 moduleb->dynamic_image = image;
6159                 register_module (mono_object_domain (moduleb), moduleb, image);
6160
6161                 /* register the module with the assembly */
6162                 ass = ab->dynamic_assembly->assembly.image;
6163                 module_count = ass->module_count;
6164                 new_modules = g_new0 (MonoImage *, module_count + 1);
6165
6166                 if (ass->modules)
6167                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6168                 new_modules [module_count] = &image->image;
6169                 mono_image_addref (&image->image);
6170
6171                 g_free (ass->modules);
6172                 ass->modules = new_modules;
6173                 ass->module_count ++;
6174         }
6175 }
6176
6177 void
6178 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6179 {
6180         MonoDynamicImage *image = moduleb->dynamic_image;
6181
6182         g_assert (type->type);
6183         image->wrappers_type = mono_class_from_mono_type (type->type);
6184 }
6185
6186 #endif
6187
6188 /*
6189  * mono_assembly_get_object:
6190  * @domain: an app domain
6191  * @assembly: an assembly
6192  *
6193  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6194  */
6195 MonoReflectionAssembly*
6196 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6197 {
6198         static MonoClass *assembly_type;
6199         MonoReflectionAssembly *res;
6200         
6201         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6202         if (!assembly_type) {
6203                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6204                 if (class == NULL)
6205                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6206                 g_assert (class);
6207                 assembly_type = class;
6208         }
6209         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6210         res->assembly = assembly;
6211
6212         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6213 }
6214
6215
6216
6217 MonoReflectionModule*   
6218 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6219 {
6220         static MonoClass *module_type;
6221         MonoReflectionModule *res;
6222         char* basename;
6223         
6224         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6225         if (!module_type) {
6226                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6227                 if (class == NULL)
6228                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6229                 g_assert (class);
6230                 module_type = class;
6231         }
6232         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6233
6234         res->image = image;
6235         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6236
6237         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6238         basename = g_path_get_basename (image->name);
6239         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6240         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6241         
6242         g_free (basename);
6243
6244         if (image->assembly->image == image) {
6245                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6246         } else {
6247                 int i;
6248                 res->token = 0;
6249                 if (image->assembly->image->modules) {
6250                         for (i = 0; i < image->assembly->image->module_count; i++) {
6251                                 if (image->assembly->image->modules [i] == image)
6252                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6253                         }
6254                         g_assert (res->token);
6255                 }
6256         }
6257
6258         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6259 }
6260
6261 MonoReflectionModule*   
6262 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6263 {
6264         static MonoClass *module_type;
6265         MonoReflectionModule *res;
6266         MonoTableInfo *table;
6267         guint32 cols [MONO_FILE_SIZE];
6268         const char *name;
6269         guint32 i, name_idx;
6270         const char *val;
6271         
6272         if (!module_type) {
6273                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6274                 if (class == NULL)
6275                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6276                 g_assert (class);
6277                 module_type = class;
6278         }
6279         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6280
6281         table = &image->tables [MONO_TABLE_FILE];
6282         g_assert (table_index < table->rows);
6283         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6284
6285         res->image = NULL;
6286         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6287         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6288
6289         /* Check whenever the row has a corresponding row in the moduleref table */
6290         table = &image->tables [MONO_TABLE_MODULEREF];
6291         for (i = 0; i < table->rows; ++i) {
6292                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6293                 val = mono_metadata_string_heap (image, name_idx);
6294                 if (strcmp (val, name) == 0)
6295                         res->image = image->modules [i];
6296         }
6297
6298         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6299         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6300         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6301         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6302         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6303
6304         return res;
6305 }
6306
6307 static gboolean
6308 verify_safe_for_managed_space (MonoType *type)
6309 {
6310         switch (type->type) {
6311 #ifdef DEBUG_HARDER
6312         case MONO_TYPE_ARRAY:
6313                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6314         case MONO_TYPE_PTR:
6315                 return verify_safe_for_managed_space (type->data.type);
6316         case MONO_TYPE_SZARRAY:
6317                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6318         case MONO_TYPE_GENERICINST: {
6319                 MonoGenericInst *inst = type->data.generic_class->inst;
6320                 int i;
6321                 if (!inst->is_open)
6322                         break;
6323                 for (i = 0; i < inst->type_argc; ++i)
6324                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6325                                 return FALSE;
6326                 break;
6327         }
6328 #endif
6329         case MONO_TYPE_VAR:
6330         case MONO_TYPE_MVAR:
6331                 return TRUE;
6332         }
6333         return TRUE;
6334 }
6335
6336 static MonoType*
6337 mono_type_normalize (MonoType *type)
6338 {
6339         int i;
6340         MonoGenericClass *gclass;
6341         MonoGenericInst *ginst;
6342         MonoClass *gtd;
6343         MonoGenericContainer *gcontainer;
6344         MonoType **argv = NULL;
6345         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6346
6347         if (type->type != MONO_TYPE_GENERICINST)
6348                 return type;
6349
6350         gclass = type->data.generic_class;
6351         ginst = gclass->context.class_inst;
6352         if (!ginst->is_open)
6353                 return type;
6354
6355         gtd = gclass->container_class;
6356         gcontainer = gtd->generic_container;
6357         argv = g_newa (MonoType*, ginst->type_argc);
6358
6359         for (i = 0; i < ginst->type_argc; ++i) {
6360                 MonoType *t = ginst->type_argv [i], *norm;
6361                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6362                         is_denorm_gtd = FALSE;
6363                 norm = mono_type_normalize (t);
6364                 argv [i] = norm;
6365                 if (norm != t)
6366                         requires_rebind = TRUE;
6367         }
6368
6369         if (is_denorm_gtd)
6370                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6371
6372         if (requires_rebind) {
6373                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6374                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6375         }
6376
6377         return type;
6378 }
6379 /*
6380  * mono_type_get_object:
6381  * @domain: an app domain
6382  * @type: a type
6383  *
6384  * Return an System.MonoType object representing the type @type.
6385  */
6386 MonoReflectionType*
6387 mono_type_get_object (MonoDomain *domain, MonoType *type)
6388 {
6389         MonoType *norm_type;
6390         MonoReflectionType *res;
6391         MonoClass *klass = mono_class_from_mono_type (type);
6392
6393         /*we must avoid using @type as it might have come
6394          * from a mono_metadata_type_dup and the caller
6395          * expects that is can be freed.
6396          * Using the right type from 
6397          */
6398         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6399
6400         /* void is very common */
6401         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6402                 return (MonoReflectionType*)domain->typeof_void;
6403
6404         /*
6405          * If the vtable of the given class was already created, we can use
6406          * the MonoType from there and avoid all locking and hash table lookups.
6407          * 
6408          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6409          * that the resulting object is different.   
6410          */
6411         if (type == &klass->byval_arg && !klass->image->dynamic) {
6412                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6413                 if (vtable && vtable->type)
6414                         return vtable->type;
6415         }
6416
6417         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6418         mono_domain_lock (domain);
6419         if (!domain->type_hash)
6420                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6421                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6422         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6423                 mono_domain_unlock (domain);
6424                 mono_loader_unlock ();
6425                 return res;
6426         }
6427
6428         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6429          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6430          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6431          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6432          * artifact of how generics are encoded and should be transparent to managed code so we
6433          * need to weed out this diference when retrieving managed System.Type objects.
6434          */
6435         norm_type = mono_type_normalize (type);
6436         if (norm_type != type) {
6437                 res = mono_type_get_object (domain, norm_type);
6438                 mono_g_hash_table_insert (domain->type_hash, type, res);
6439                 mono_domain_unlock (domain);
6440                 mono_loader_unlock ();
6441                 return res;
6442         }
6443
6444         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6445         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6446                 g_assert (0);
6447
6448         if (!verify_safe_for_managed_space (type)) {
6449                 mono_domain_unlock (domain);
6450                 mono_loader_unlock ();
6451                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6452         }
6453
6454         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6455                 gboolean is_type_done = TRUE;
6456                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6457                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6458                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6459                 */
6460                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6461                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6462
6463                         if (gparam->owner && gparam->owner->is_method) {
6464                                 MonoMethod *method = gparam->owner->owner.method;
6465                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6466                                         is_type_done = FALSE;
6467                         } else if (gparam->owner && !gparam->owner->is_method) {
6468                                 MonoClass *klass = gparam->owner->owner.klass;
6469                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6470                                         is_type_done = FALSE;
6471                         }
6472                 } 
6473
6474                 /* g_assert_not_reached (); */
6475                 /* should this be considered an error condition? */
6476                 if (is_type_done && !type->byref) {
6477                         mono_domain_unlock (domain);
6478                         mono_loader_unlock ();
6479                         return mono_class_get_ref_info (klass);
6480                 }
6481         }
6482         /* This is stored in vtables/JITted code so it has to be pinned */
6483         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6484         res->type = type;
6485         mono_g_hash_table_insert (domain->type_hash, type, res);
6486
6487         if (type->type == MONO_TYPE_VOID)
6488                 domain->typeof_void = (MonoObject*)res;
6489
6490         mono_domain_unlock (domain);
6491         mono_loader_unlock ();
6492         return res;
6493 }
6494
6495 /*
6496  * mono_method_get_object:
6497  * @domain: an app domain
6498  * @method: a method
6499  * @refclass: the reflected type (can be NULL)
6500  *
6501  * Return an System.Reflection.MonoMethod object representing the method @method.
6502  */
6503 MonoReflectionMethod*
6504 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6505 {
6506         /*
6507          * We use the same C representation for methods and constructors, but the type 
6508          * name in C# is different.
6509          */
6510         static MonoClass *System_Reflection_MonoMethod = NULL;
6511         static MonoClass *System_Reflection_MonoCMethod = NULL;
6512         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6513         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6514         MonoClass *klass;
6515         MonoReflectionMethod *ret;
6516
6517         if (method->is_inflated) {
6518                 MonoReflectionGenericMethod *gret;
6519
6520                 refclass = method->klass;
6521                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6522                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6523                         if (!System_Reflection_MonoGenericCMethod)
6524                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6525                         klass = System_Reflection_MonoGenericCMethod;
6526                 } else {
6527                         if (!System_Reflection_MonoGenericMethod)
6528                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6529                         klass = System_Reflection_MonoGenericMethod;
6530                 }
6531                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6532                 gret->method.method = method;
6533                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6534                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6535                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6536         }
6537
6538         if (!refclass)
6539                 refclass = method->klass;
6540
6541         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6542         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6543                 if (!System_Reflection_MonoCMethod)
6544                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6545                 klass = System_Reflection_MonoCMethod;
6546         }
6547         else {
6548                 if (!System_Reflection_MonoMethod)
6549                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6550                 klass = System_Reflection_MonoMethod;
6551         }
6552         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6553         ret->method = method;
6554         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6555         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6556 }
6557
6558 /*
6559  * mono_method_clear_object:
6560  *
6561  *   Clear the cached reflection objects for the dynamic method METHOD.
6562  */
6563 void
6564 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6565 {
6566         MonoClass *klass;
6567         g_assert (method->dynamic);
6568
6569         klass = method->klass;
6570         while (klass) {
6571                 clear_cached_object (domain, method, klass);
6572                 klass = klass->parent;
6573         }
6574         /* Added by mono_param_get_objects () */
6575         clear_cached_object (domain, &(method->signature), NULL);
6576         klass = method->klass;
6577         while (klass) {
6578                 clear_cached_object (domain, &(method->signature), klass);
6579                 klass = klass->parent;
6580         }
6581 }
6582
6583 /*
6584  * mono_field_get_object:
6585  * @domain: an app domain
6586  * @klass: a type
6587  * @field: a field
6588  *
6589  * Return an System.Reflection.MonoField object representing the field @field
6590  * in class @klass.
6591  */
6592 MonoReflectionField*
6593 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6594 {
6595         MonoReflectionField *res;
6596         static MonoClass *monofield_klass;
6597
6598         CHECK_OBJECT (MonoReflectionField *, field, klass);
6599         if (!monofield_klass)
6600                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6601         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6602         res->klass = klass;
6603         res->field = field;
6604         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6605
6606         if (is_field_on_inst (field)) {
6607                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6608                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6609         } else {
6610                 if (field->type)
6611                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6612                 res->attrs = mono_field_get_flags (field);
6613         }
6614         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6615 }
6616
6617 /*
6618  * mono_property_get_object:
6619  * @domain: an app domain
6620  * @klass: a type
6621  * @property: a property
6622  *
6623  * Return an System.Reflection.MonoProperty object representing the property @property
6624  * in class @klass.
6625  */
6626 MonoReflectionProperty*
6627 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6628 {
6629         MonoReflectionProperty *res;
6630         static MonoClass *monoproperty_klass;
6631
6632         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6633         if (!monoproperty_klass)
6634                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6635         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6636         res->klass = klass;
6637         res->property = property;
6638         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6639 }
6640
6641 /*
6642  * mono_event_get_object:
6643  * @domain: an app domain
6644  * @klass: a type
6645  * @event: a event
6646  *
6647  * Return an System.Reflection.MonoEvent object representing the event @event
6648  * in class @klass.
6649  */
6650 MonoReflectionEvent*
6651 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6652 {
6653         MonoReflectionEvent *res;
6654         MonoReflectionMonoEvent *mono_event;
6655         static MonoClass *monoevent_klass;
6656
6657         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6658         if (!monoevent_klass)
6659                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6660         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6661         mono_event->klass = klass;
6662         mono_event->event = event;
6663         res = (MonoReflectionEvent*)mono_event;
6664         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6665 }
6666
6667 /**
6668  * mono_get_reflection_missing_object:
6669  * @domain: Domain where the object lives
6670  *
6671  * Returns the System.Reflection.Missing.Value singleton object
6672  * (of type System.Reflection.Missing).
6673  *
6674  * Used as the value for ParameterInfo.DefaultValue when Optional
6675  * is present
6676  */
6677 static MonoObject *
6678 mono_get_reflection_missing_object (MonoDomain *domain)
6679 {
6680         MonoObject *obj;
6681         static MonoClassField *missing_value_field = NULL;
6682         
6683         if (!missing_value_field) {
6684                 MonoClass *missing_klass;
6685                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6686                 mono_class_init (missing_klass);
6687                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6688                 g_assert (missing_value_field);
6689         }
6690         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6691         g_assert (obj);
6692         return obj;
6693 }
6694
6695 static MonoObject*
6696 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6697 {
6698         if (!*dbnull)
6699                 *dbnull = mono_get_dbnull_object (domain);
6700         return *dbnull;
6701 }
6702
6703 static MonoObject*
6704 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6705 {
6706         if (!*reflection_missing)
6707                 *reflection_missing = mono_get_reflection_missing_object (domain);
6708         return *reflection_missing;
6709 }
6710
6711 /*
6712  * mono_param_get_objects:
6713  * @domain: an app domain
6714  * @method: a method
6715  *
6716  * Return an System.Reflection.ParameterInfo array object representing the parameters
6717  * in the method @method.
6718  */
6719 MonoArray*
6720 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6721 {
6722         static MonoClass *System_Reflection_ParameterInfo;
6723         static MonoClass *System_Reflection_ParameterInfo_array;
6724         MonoError error;
6725         MonoArray *res = NULL;
6726         MonoReflectionMethod *member = NULL;
6727         MonoReflectionParameter *param = NULL;
6728         char **names, **blobs = NULL;
6729         guint32 *types = NULL;
6730         MonoType *type = NULL;
6731         MonoObject *dbnull = NULL;
6732         MonoObject *missing = NULL;
6733         MonoMarshalSpec **mspecs;
6734         MonoMethodSignature *sig;
6735         MonoVTable *pinfo_vtable;
6736         int i;
6737
6738         if (!System_Reflection_ParameterInfo_array) {
6739                 MonoClass *klass;
6740
6741                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6742                 mono_memory_barrier ();
6743                 System_Reflection_ParameterInfo = klass; 
6744         
6745                 klass = mono_array_class_get (klass, 1);
6746                 mono_memory_barrier ();
6747                 System_Reflection_ParameterInfo_array = klass;
6748         }
6749
6750         sig = mono_method_signature_checked (method, &error);
6751         if (!mono_error_ok (&error))
6752                 mono_error_raise_exception (&error);
6753
6754         if (!sig->param_count)
6755                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6756
6757         /* Note: the cache is based on the address of the signature into the method
6758          * since we already cache MethodInfos with the method as keys.
6759          */
6760         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6761
6762         member = mono_method_get_object (domain, method, refclass);
6763         names = g_new (char *, sig->param_count);
6764         mono_method_get_param_names (method, (const char **) names);
6765
6766         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6767         mono_method_get_marshal_info (method, mspecs);
6768
6769         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6770         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6771         for (i = 0; i < sig->param_count; ++i) {
6772                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6773                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6774                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6775                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6776                 param->PositionImpl = i;
6777                 param->AttrsImpl = sig->params [i]->attrs;
6778
6779                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6780                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6781                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6782                         else
6783                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6784                 } else {
6785
6786                         if (!blobs) {
6787                                 blobs = g_new0 (char *, sig->param_count);
6788                                 types = g_new0 (guint32, sig->param_count);
6789                                 get_default_param_value_blobs (method, blobs, types); 
6790                         }
6791
6792                         /* Build MonoType for the type from the Constant Table */
6793                         if (!type)
6794                                 type = g_new0 (MonoType, 1);
6795                         type->type = types [i];
6796                         type->data.klass = NULL;
6797                         if (types [i] == MONO_TYPE_CLASS)
6798                                 type->data.klass = mono_defaults.object_class;
6799                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6800                                 /* For enums, types [i] contains the base type */
6801
6802                                         type->type = MONO_TYPE_VALUETYPE;
6803                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6804                         } else
6805                                 type->data.klass = mono_class_from_mono_type (type);
6806
6807                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6808
6809                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6810                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6811                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6812                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6813                                 else
6814                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6815                         }
6816                         
6817                 }
6818
6819                 if (mspecs [i + 1])
6820                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6821                 
6822                 mono_array_setref (res, i, param);
6823         }
6824         g_free (names);
6825         g_free (blobs);
6826         g_free (types);
6827         g_free (type);
6828
6829         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6830                 if (mspecs [i])
6831                         mono_metadata_free_marshal_spec (mspecs [i]);
6832         g_free (mspecs);
6833         
6834         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6835 }
6836
6837 MonoArray*
6838 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6839 {
6840         return mono_param_get_objects_internal (domain, method, NULL);
6841 }
6842
6843 /*
6844  * mono_method_body_get_object:
6845  * @domain: an app domain
6846  * @method: a method
6847  *
6848  * Return an System.Reflection.MethodBody object representing the method @method.
6849  */
6850 MonoReflectionMethodBody*
6851 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6852 {
6853         static MonoClass *System_Reflection_MethodBody = NULL;
6854         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6855         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6856         MonoReflectionMethodBody *ret;
6857         MonoMethodHeader *header;
6858         MonoImage *image;
6859         guint32 method_rva, local_var_sig_token;
6860     char *ptr;
6861         unsigned char format, flags;
6862         int i;
6863
6864         if (!System_Reflection_MethodBody)
6865                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6866         if (!System_Reflection_LocalVariableInfo)
6867                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6868         if (!System_Reflection_ExceptionHandlingClause)
6869                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6870
6871         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6872
6873         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6874                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6875             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6876             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6877                 return NULL;
6878
6879         image = method->klass->image;
6880         header = mono_method_get_header (method);
6881
6882         if (!image->dynamic) {
6883                 /* Obtain local vars signature token */
6884                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6885                 ptr = mono_image_rva_map (image, method_rva);
6886                 flags = *(const unsigned char *) ptr;
6887                 format = flags & METHOD_HEADER_FORMAT_MASK;
6888                 switch (format){
6889                 case METHOD_HEADER_TINY_FORMAT:
6890                         local_var_sig_token = 0;
6891                         break;
6892                 case METHOD_HEADER_FAT_FORMAT:
6893                         ptr += 2;
6894                         ptr += 2;
6895                         ptr += 4;
6896                         local_var_sig_token = read32 (ptr);
6897                         break;
6898                 default:
6899                         g_assert_not_reached ();
6900                 }
6901         } else
6902                 local_var_sig_token = 0; //FIXME
6903
6904         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6905
6906         ret->init_locals = header->init_locals;
6907         ret->max_stack = header->max_stack;
6908         ret->local_var_sig_token = local_var_sig_token;
6909         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6910         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6911
6912         /* Locals */
6913         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6914         for (i = 0; i < header->num_locals; ++i) {
6915                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6916                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6917                 info->is_pinned = header->locals [i]->pinned;
6918                 info->local_index = i;
6919                 mono_array_setref (ret->locals, i, info);
6920         }
6921
6922         /* Exceptions */
6923         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6924         for (i = 0; i < header->num_clauses; ++i) {
6925                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6926                 MonoExceptionClause *clause = &header->clauses [i];
6927
6928                 info->flags = clause->flags;
6929                 info->try_offset = clause->try_offset;
6930                 info->try_length = clause->try_len;
6931                 info->handler_offset = clause->handler_offset;
6932                 info->handler_length = clause->handler_len;
6933                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6934                         info->filter_offset = clause->data.filter_offset;
6935                 else if (clause->data.catch_class)
6936                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6937
6938                 mono_array_setref (ret->clauses, i, info);
6939         }
6940
6941         mono_metadata_free_mh (header);
6942         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6943         return ret;
6944 }
6945
6946 /**
6947  * mono_get_dbnull_object:
6948  * @domain: Domain where the object lives
6949  *
6950  * Returns the System.DBNull.Value singleton object
6951  *
6952  * Used as the value for ParameterInfo.DefaultValue 
6953  */
6954 MonoObject *
6955 mono_get_dbnull_object (MonoDomain *domain)
6956 {
6957         MonoObject *obj;
6958         static MonoClassField *dbnull_value_field = NULL;
6959         
6960         if (!dbnull_value_field) {
6961                 MonoClass *dbnull_klass;
6962                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6963                 mono_class_init (dbnull_klass);
6964                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6965                 g_assert (dbnull_value_field);
6966         }
6967         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6968         g_assert (obj);
6969         return obj;
6970 }
6971
6972 static void
6973 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6974 {
6975         guint32 param_index, i, lastp, crow = 0;
6976         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6977         gint32 idx;
6978
6979         MonoClass *klass = method->klass;
6980         MonoImage *image = klass->image;
6981         MonoMethodSignature *methodsig = mono_method_signature (method);
6982
6983         MonoTableInfo *constt;
6984         MonoTableInfo *methodt;
6985         MonoTableInfo *paramt;
6986
6987         if (!methodsig->param_count)
6988                 return;
6989
6990         mono_class_init (klass);
6991
6992         if (klass->image->dynamic) {
6993                 MonoReflectionMethodAux *aux;
6994                 if (method->is_inflated)
6995                         method = ((MonoMethodInflated*)method)->declaring;
6996                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6997                 if (aux && aux->param_defaults) {
6998                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6999                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7000                 }
7001                 return;
7002         }
7003
7004         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7005         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7006         constt = &image->tables [MONO_TABLE_CONSTANT];
7007
7008         idx = mono_method_get_index (method) - 1;
7009         g_assert (idx != -1);
7010
7011         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7012         if (idx + 1 < methodt->rows)
7013                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7014         else
7015                 lastp = paramt->rows + 1;
7016
7017         for (i = param_index; i < lastp; ++i) {
7018                 guint32 paramseq;
7019
7020                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7021                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7022
7023                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7024                         continue;
7025
7026                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7027                 if (!crow) {
7028                         continue;
7029                 }
7030         
7031                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7032                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7033                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7034         }
7035
7036         return;
7037 }
7038
7039 MonoObject *
7040 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7041 {
7042         void *retval;
7043         MonoClass *klass;
7044         MonoObject *object;
7045         MonoType *basetype = type;
7046
7047         if (!blob)
7048                 return NULL;
7049         
7050         klass = mono_class_from_mono_type (type);
7051         if (klass->valuetype) {
7052                 object = mono_object_new (domain, klass);
7053                 retval = ((gchar *) object + sizeof (MonoObject));
7054                 if (klass->enumtype)
7055                         basetype = mono_class_enum_basetype (klass);
7056         } else {
7057                 retval = &object;
7058         }
7059                         
7060         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7061                 return object;
7062         else
7063                 return NULL;
7064 }
7065
7066 static int
7067 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7068         int found_sep;
7069         char *s;
7070         gboolean quoted = FALSE;
7071
7072         memset (assembly, 0, sizeof (MonoAssemblyName));
7073         assembly->culture = "";
7074         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7075
7076         if (*p == '"') {
7077                 quoted = TRUE;
7078                 p++;
7079         }
7080         assembly->name = p;
7081         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7082                 p++;
7083         if (quoted) {
7084                 if (*p != '"')
7085                         return 1;
7086                 *p = 0;
7087                 p++;
7088         }
7089         if (*p != ',')
7090                 return 1;
7091         *p = 0;
7092         /* Remove trailing whitespace */
7093         s = p - 1;
7094         while (*s && g_ascii_isspace (*s))
7095                 *s-- = 0;
7096         p ++;
7097         while (g_ascii_isspace (*p))
7098                 p++;
7099         while (*p) {
7100                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7101                         p += 8;
7102                         assembly->major = strtoul (p, &s, 10);
7103                         if (s == p || *s != '.')
7104                                 return 1;
7105                         p = ++s;
7106                         assembly->minor = strtoul (p, &s, 10);
7107                         if (s == p || *s != '.')
7108                                 return 1;
7109                         p = ++s;
7110                         assembly->build = strtoul (p, &s, 10);
7111                         if (s == p || *s != '.')
7112                                 return 1;
7113                         p = ++s;
7114                         assembly->revision = strtoul (p, &s, 10);
7115                         if (s == p)
7116                                 return 1;
7117                         p = s;
7118                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7119                         p += 8;
7120                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7121                                 assembly->culture = "";
7122                                 p += 7;
7123                         } else {
7124                                 assembly->culture = p;
7125                                 while (*p && *p != ',') {
7126                                         p++;
7127                                 }
7128                         }
7129                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7130                         p += 15;
7131                         if (strncmp (p, "null", 4) == 0) {
7132                                 p += 4;
7133                         } else {
7134                                 int len;
7135                                 gchar *start = p;
7136                                 while (*p && *p != ',') {
7137                                         p++;
7138                                 }
7139                                 len = (p - start + 1);
7140                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7141                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7142                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7143                         }
7144                 } else {
7145                         while (*p && *p != ',')
7146                                 p++;
7147                 }
7148                 found_sep = 0;
7149                 while (g_ascii_isspace (*p) || *p == ',') {
7150                         *p++ = 0;
7151                         found_sep = 1;
7152                         continue;
7153                 }
7154                 /* failed */
7155                 if (!found_sep)
7156                         return 1;
7157         }
7158
7159         return 0;
7160 }
7161
7162 /*
7163  * mono_reflection_parse_type:
7164  * @name: type name
7165  *
7166  * Parse a type name as accepted by the GetType () method and output the info
7167  * extracted in the info structure.
7168  * the name param will be mangled, so, make a copy before passing it to this function.
7169  * The fields in info will be valid until the memory pointed to by name is valid.
7170  *
7171  * See also mono_type_get_name () below.
7172  *
7173  * Returns: 0 on parse error.
7174  */
7175 static int
7176 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7177                              MonoTypeNameParse *info)
7178 {
7179         char *start, *p, *w, *temp, *last_point, *startn;
7180         int in_modifiers = 0;
7181         int isbyref = 0, rank, arity = 0, i;
7182
7183         start = p = w = name;
7184
7185         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7186         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7187         info->name = info->name_space = NULL;
7188         info->nested = NULL;
7189         info->modifiers = NULL;
7190         info->type_arguments = NULL;
7191
7192         /* last_point separates the namespace from the name */
7193         last_point = NULL;
7194         /* Skips spaces */
7195         while (*p == ' ') p++, start++, w++, name++;
7196
7197         while (*p) {
7198                 switch (*p) {
7199                 case '+':
7200                         *p = 0; /* NULL terminate the name */
7201                         startn = p + 1;
7202                         info->nested = g_list_append (info->nested, startn);
7203                         /* we have parsed the nesting namespace + name */
7204                         if (info->name)
7205                                 break;
7206                         if (last_point) {
7207                                 info->name_space = start;
7208                                 *last_point = 0;
7209                                 info->name = last_point + 1;
7210                         } else {
7211                                 info->name_space = (char *)"";
7212                                 info->name = start;
7213                         }
7214                         break;
7215                 case '.':
7216                         last_point = p;
7217                         break;
7218                 case '\\':
7219                         ++p;
7220                         break;
7221                 case '&':
7222                 case '*':
7223                 case '[':
7224                 case ',':
7225                 case ']':
7226                         in_modifiers = 1;
7227                         break;
7228                 case '`':
7229                         ++p;
7230                         i = strtol (p, &temp, 10);
7231                         arity += i;
7232                         if (p == temp)
7233                                 return 0;
7234                         p = temp-1;
7235                         break;
7236                 default:
7237                         break;
7238                 }
7239                 if (in_modifiers)
7240                         break;
7241                 // *w++ = *p++;
7242                 p++;
7243         }
7244         
7245         if (!info->name) {
7246                 if (last_point) {
7247                         info->name_space = start;
7248                         *last_point = 0;
7249                         info->name = last_point + 1;
7250                 } else {
7251                         info->name_space = (char *)"";
7252                         info->name = start;
7253                 }
7254         }
7255         while (*p) {
7256                 switch (*p) {
7257                 case '&':
7258                         if (isbyref) /* only one level allowed by the spec */
7259                                 return 0;
7260                         isbyref = 1;
7261                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7262                         *p++ = 0;
7263                         break;
7264                 case '*':
7265                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7266                         *p++ = 0;
7267                         break;
7268                 case '[':
7269                         if (arity != 0) {
7270                                 *p++ = 0;
7271                                 info->type_arguments = g_ptr_array_new ();
7272                                 for (i = 0; i < arity; i++) {
7273                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7274                                         gboolean fqname = FALSE;
7275
7276                                         g_ptr_array_add (info->type_arguments, subinfo);
7277
7278                                         if (*p == '[') {
7279                                                 p++;
7280                                                 fqname = TRUE;
7281                                         }
7282
7283                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7284                                                 return 0;
7285
7286                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7287                                         if (fqname && (*p != ']')) {
7288                                                 char *aname;
7289
7290                                                 if (*p != ',')
7291                                                         return 0;
7292                                                 *p++ = 0;
7293
7294                                                 aname = p;
7295                                                 while (*p && (*p != ']'))
7296                                                         p++;
7297
7298                                                 if (*p != ']')
7299                                                         return 0;
7300
7301                                                 *p++ = 0;
7302                                                 while (*aname) {
7303                                                         if (g_ascii_isspace (*aname)) {
7304                                                                 ++aname;
7305                                                                 continue;
7306                                                         }
7307                                                         break;
7308                                                 }
7309                                                 if (!*aname ||
7310                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7311                                                         return 0;
7312                                         } else if (fqname && (*p == ']')) {
7313                                                 *p++ = 0;
7314                                         }
7315
7316                                         if (i + 1 < arity) {
7317                                                 if (*p != ',')
7318                                                         return 0;
7319                                         } else {
7320                                                 if (*p != ']')
7321                                                         return 0;
7322                                         }
7323                                         *p++ = 0;
7324                                 }
7325
7326                                 arity = 0;
7327                                 break;
7328                         }
7329                         rank = 1;
7330                         *p++ = 0;
7331                         while (*p) {
7332                                 if (*p == ']')
7333                                         break;
7334                                 if (*p == ',')
7335                                         rank++;
7336                                 else if (*p == '*') /* '*' means unknown lower bound */
7337                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7338                                 else
7339                                         return 0;
7340                                 ++p;
7341                         }
7342                         if (*p++ != ']')
7343                                 return 0;
7344                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7345                         break;
7346                 case ']':
7347                         if (is_recursed)
7348                                 goto end;
7349                         return 0;
7350                 case ',':
7351                         if (is_recursed)
7352                                 goto end;
7353                         *p++ = 0;
7354                         while (*p) {
7355                                 if (g_ascii_isspace (*p)) {
7356                                         ++p;
7357                                         continue;
7358                                 }
7359                                 break;
7360                         }
7361                         if (!*p)
7362                                 return 0; /* missing assembly name */
7363                         if (!assembly_name_to_aname (&info->assembly, p))
7364                                 return 0;
7365                         break;
7366                 default:
7367                         return 0;
7368                 }
7369                 if (info->assembly.name)
7370                         break;
7371         }
7372         // *w = 0; /* terminate class name */
7373  end:
7374         if (!info->name || !*info->name)
7375                 return 0;
7376         if (endptr)
7377                 *endptr = p;
7378         /* add other consistency checks */
7379         return 1;
7380 }
7381
7382 int
7383 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7384 {
7385         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7386 }
7387
7388 static MonoType*
7389 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7390 {
7391         gboolean type_resolve = FALSE;
7392         MonoType *type;
7393         MonoImage *rootimage = image;
7394
7395         if (info->assembly.name) {
7396                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7397                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7398                         /* 
7399                          * This could happen in the AOT compiler case when the search hook is not
7400                          * installed.
7401                          */
7402                         assembly = image->assembly;
7403                 if (!assembly) {
7404                         /* then we must load the assembly ourselve - see #60439 */
7405                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7406                         if (!assembly)
7407                                 return NULL;
7408                 }
7409                 image = assembly->image;
7410         } else if (!image) {
7411                 image = mono_defaults.corlib;
7412         }
7413
7414         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7415         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7416                 image = mono_defaults.corlib;
7417                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7418         }
7419
7420         return type;
7421 }
7422
7423 static MonoType*
7424 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7425 {
7426         MonoClass *klass;
7427         GList *mod;
7428         int modval;
7429         gboolean bounded = FALSE;
7430         
7431         if (!image)
7432                 image = mono_defaults.corlib;
7433
7434         if (ignorecase)
7435                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7436         else
7437                 klass = mono_class_from_name (image, info->name_space, info->name);
7438         if (!klass)
7439                 return NULL;
7440         for (mod = info->nested; mod; mod = mod->next) {
7441                 gpointer iter = NULL;
7442                 MonoClass *parent;
7443
7444                 parent = klass;
7445                 mono_class_init (parent);
7446
7447                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7448                         if (ignorecase) {
7449                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7450                                         break;
7451                         } else {
7452                                 if (strcmp (klass->name, mod->data) == 0)
7453                                         break;
7454                         }
7455                 }
7456                 if (!klass)
7457                         break;
7458         }
7459         if (!klass)
7460                 return NULL;
7461
7462         if (info->type_arguments) {
7463                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7464                 MonoReflectionType *the_type;
7465                 MonoType *instance;
7466                 int i;
7467
7468                 for (i = 0; i < info->type_arguments->len; i++) {
7469                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7470
7471                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7472                         if (!type_args [i]) {
7473                                 g_free (type_args);
7474                                 return NULL;
7475                         }
7476                 }
7477
7478                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7479
7480                 instance = mono_reflection_bind_generic_parameters (
7481                         the_type, info->type_arguments->len, type_args);
7482
7483                 g_free (type_args);
7484                 if (!instance)
7485                         return NULL;
7486
7487                 klass = mono_class_from_mono_type (instance);
7488         }
7489
7490         for (mod = info->modifiers; mod; mod = mod->next) {
7491                 modval = GPOINTER_TO_UINT (mod->data);
7492                 if (!modval) { /* byref: must be last modifier */
7493                         return &klass->this_arg;
7494                 } else if (modval == -1) {
7495                         klass = mono_ptr_class_get (&klass->byval_arg);
7496                 } else if (modval == -2) {
7497                         bounded = TRUE;
7498                 } else { /* array rank */
7499                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7500                 }
7501         }
7502
7503         return &klass->byval_arg;
7504 }
7505
7506 /*
7507  * mono_reflection_get_type:
7508  * @image: a metadata context
7509  * @info: type description structure
7510  * @ignorecase: flag for case-insensitive string compares
7511  * @type_resolve: whenever type resolve was already tried
7512  *
7513  * Build a MonoType from the type description in @info.
7514  * 
7515  */
7516
7517 MonoType*
7518 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7519         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7520 }
7521
7522 static MonoType*
7523 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7524 {
7525         MonoReflectionAssemblyBuilder *abuilder;
7526         MonoType *type;
7527         int i;
7528
7529         g_assert (assembly->dynamic);
7530         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7531
7532         /* Enumerate all modules */
7533
7534         type = NULL;
7535         if (abuilder->modules) {
7536                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7537                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7538                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7539                         if (type)
7540                                 break;
7541                 }
7542         }
7543
7544         if (!type && abuilder->loaded_modules) {
7545                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7546                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7547                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7548                         if (type)
7549                                 break;
7550                 }
7551         }
7552
7553         return type;
7554 }
7555         
7556 MonoType*
7557 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7558 {
7559         MonoType *type;
7560         MonoReflectionAssembly *assembly;
7561         GString *fullName;
7562         GList *mod;
7563
7564         if (image && image->dynamic)
7565                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7566         else
7567                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7568         if (type)
7569                 return type;
7570         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7571                 return NULL;
7572
7573         if (type_resolve) {
7574                 if (*type_resolve) 
7575                         return NULL;
7576                 else
7577                         *type_resolve = TRUE;
7578         }
7579         
7580         /* Reconstruct the type name */
7581         fullName = g_string_new ("");
7582         if (info->name_space && (info->name_space [0] != '\0'))
7583                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7584         else
7585                 g_string_printf (fullName, "%s", info->name);
7586         for (mod = info->nested; mod; mod = mod->next)
7587                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7588
7589         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7590         if (assembly) {
7591                 if (assembly->assembly->dynamic)
7592                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7593                 else
7594                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7595                                                                                                           info, ignorecase);
7596         }
7597         g_string_free (fullName, TRUE);
7598         return type;
7599 }
7600
7601 void
7602 mono_reflection_free_type_info (MonoTypeNameParse *info)
7603 {
7604         g_list_free (info->modifiers);
7605         g_list_free (info->nested);
7606
7607         if (info->type_arguments) {
7608                 int i;
7609
7610                 for (i = 0; i < info->type_arguments->len; i++) {
7611                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7612
7613                         mono_reflection_free_type_info (subinfo);
7614                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7615                         g_free (subinfo);
7616                 }
7617
7618                 g_ptr_array_free (info->type_arguments, TRUE);
7619         }
7620 }
7621
7622 /*
7623  * mono_reflection_type_from_name:
7624  * @name: type name.
7625  * @image: a metadata context (can be NULL).
7626  *
7627  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7628  * it defaults to get the type from @image or, if @image is NULL or loading
7629  * from it fails, uses corlib.
7630  * 
7631  */
7632 MonoType*
7633 mono_reflection_type_from_name (char *name, MonoImage *image)
7634 {
7635         MonoType *type = NULL;
7636         MonoTypeNameParse info;
7637         char *tmp;
7638
7639         /* Make a copy since parse_type modifies its argument */
7640         tmp = g_strdup (name);
7641         
7642         /*g_print ("requested type %s\n", str);*/
7643         if (mono_reflection_parse_type (tmp, &info)) {
7644                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7645         }
7646
7647         g_free (tmp);
7648         mono_reflection_free_type_info (&info);
7649         return type;
7650 }
7651
7652 /*
7653  * mono_reflection_get_token:
7654  *
7655  *   Return the metadata token of OBJ which should be an object
7656  * representing a metadata element.
7657  */
7658 guint32
7659 mono_reflection_get_token (MonoObject *obj)
7660 {
7661         MonoClass *klass;
7662         guint32 token = 0;
7663
7664         klass = obj->vtable->klass;
7665
7666         if (strcmp (klass->name, "MethodBuilder") == 0) {
7667                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7668
7669                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7670         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7671                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7672
7673                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7674         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7675                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7676
7677                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7678         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7679                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7680                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7681         } else if (strcmp (klass->name, "MonoType") == 0) {
7682                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7683                 MonoClass *mc = mono_class_from_mono_type (type);
7684                 if (!mono_class_init (mc))
7685                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7686
7687                 token = mc->type_token;
7688         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7689                    strcmp (klass->name, "MonoMethod") == 0 ||
7690                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7691                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7692                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7693                 if (m->method->is_inflated) {
7694                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7695                         return inflated->declaring->token;
7696                 } else {
7697                         token = m->method->token;
7698                 }
7699         } else if (strcmp (klass->name, "MonoField") == 0) {
7700                 MonoReflectionField *f = (MonoReflectionField*)obj;
7701
7702                 if (is_field_on_inst (f->field)) {
7703                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7704                         int field_index = f->field - dgclass->fields;
7705                         MonoObject *obj;
7706
7707                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7708                         obj = dgclass->field_objects [field_index];
7709                         return mono_reflection_get_token (obj);
7710                 }
7711                 token = mono_class_get_field_token (f->field);
7712         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7713                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7714
7715                 token = mono_class_get_property_token (p->property);
7716         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7717                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7718
7719                 token = mono_class_get_event_token (p->event);
7720         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7721                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7722                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7723                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7724
7725                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7726         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7727                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7728
7729                 token = m->token;
7730         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7731                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7732         } else {
7733                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7734                 MonoException *ex = mono_get_exception_not_implemented (msg);
7735                 g_free (msg);
7736                 mono_raise_exception (ex);
7737         }
7738
7739         return token;
7740 }
7741
7742 static void*
7743 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7744 {
7745         int slen, type = t->type;
7746         MonoClass *tklass = t->data.klass;
7747
7748 handle_enum:
7749         switch (type) {
7750         case MONO_TYPE_U1:
7751         case MONO_TYPE_I1:
7752         case MONO_TYPE_BOOLEAN: {
7753                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7754                 *bval = *p;
7755                 *end = p + 1;
7756                 return bval;
7757         }
7758         case MONO_TYPE_CHAR:
7759         case MONO_TYPE_U2:
7760         case MONO_TYPE_I2: {
7761                 guint16 *val = g_malloc (sizeof (guint16));
7762                 *val = read16 (p);
7763                 *end = p + 2;
7764                 return val;
7765         }
7766 #if SIZEOF_VOID_P == 4
7767         case MONO_TYPE_U:
7768         case MONO_TYPE_I:
7769 #endif
7770         case MONO_TYPE_R4:
7771         case MONO_TYPE_U4:
7772         case MONO_TYPE_I4: {
7773                 guint32 *val = g_malloc (sizeof (guint32));
7774                 *val = read32 (p);
7775                 *end = p + 4;
7776                 return val;
7777         }
7778 #if SIZEOF_VOID_P == 8
7779         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7780         case MONO_TYPE_I:
7781 #endif
7782         case MONO_TYPE_U8:
7783         case MONO_TYPE_I8: {
7784                 guint64 *val = g_malloc (sizeof (guint64));
7785                 *val = read64 (p);
7786                 *end = p + 8;
7787                 return val;
7788         }
7789         case MONO_TYPE_R8: {
7790                 double *val = g_malloc (sizeof (double));
7791                 readr8 (p, val);
7792                 *end = p + 8;
7793                 return val;
7794         }
7795         case MONO_TYPE_VALUETYPE:
7796                 if (t->data.klass->enumtype) {
7797                         type = mono_class_enum_basetype (t->data.klass)->type;
7798                         goto handle_enum;
7799                 } else {
7800                         MonoClass *k =  t->data.klass;
7801                         
7802                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7803                                 guint64 *val = g_malloc (sizeof (guint64));
7804                                 *val = read64 (p);
7805                                 *end = p + 8;
7806                                 return val;
7807                         }
7808                 }
7809                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7810                 break;
7811                 
7812         case MONO_TYPE_STRING:
7813                 if (*p == (char)0xFF) {
7814                         *end = p + 1;
7815                         return NULL;
7816                 }
7817                 slen = mono_metadata_decode_value (p, &p);
7818                 *end = p + slen;
7819                 return mono_string_new_len (mono_domain_get (), p, slen);
7820         case MONO_TYPE_CLASS: {
7821                 char *n;
7822                 MonoType *t;
7823                 if (*p == (char)0xFF) {
7824                         *end = p + 1;
7825                         return NULL;
7826                 }
7827 handle_type:
7828                 slen = mono_metadata_decode_value (p, &p);
7829                 n = g_memdup (p, slen + 1);
7830                 n [slen] = 0;
7831                 t = mono_reflection_type_from_name (n, image);
7832                 if (!t)
7833                         g_warning ("Cannot load type '%s'", n);
7834                 g_free (n);
7835                 *end = p + slen;
7836                 if (t)
7837                         return mono_type_get_object (mono_domain_get (), t);
7838                 else
7839                         return NULL;
7840         }
7841         case MONO_TYPE_OBJECT: {
7842                 char subt = *p++;
7843                 MonoObject *obj;
7844                 MonoClass *subc = NULL;
7845                 void *val;
7846
7847                 if (subt == 0x50) {
7848                         goto handle_type;
7849                 } else if (subt == 0x0E) {
7850                         type = MONO_TYPE_STRING;
7851                         goto handle_enum;
7852                 } else if (subt == 0x1D) {
7853                         MonoType simple_type = {{0}};
7854                         int etype = *p;
7855                         p ++;
7856
7857                         if (etype == 0x51)
7858                                 /* See Partition II, Appendix B3 */
7859                                 etype = MONO_TYPE_OBJECT;
7860                         type = MONO_TYPE_SZARRAY;
7861                         simple_type.type = etype;
7862                         tklass = mono_class_from_mono_type (&simple_type);
7863                         goto handle_enum;
7864                 } else if (subt == 0x55) {
7865                         char *n;
7866                         MonoType *t;
7867                         slen = mono_metadata_decode_value (p, &p);
7868                         n = g_memdup (p, slen + 1);
7869                         n [slen] = 0;
7870                         t = mono_reflection_type_from_name (n, image);
7871                         if (!t)
7872                                 g_error ("Cannot load type '%s'", n);
7873                         g_free (n);
7874                         p += slen;
7875                         subc = mono_class_from_mono_type (t);
7876                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7877                         MonoType simple_type = {{0}};
7878                         simple_type.type = subt;
7879                         subc = mono_class_from_mono_type (&simple_type);
7880                 } else {
7881                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7882                 }
7883                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7884                 obj = mono_object_new (mono_domain_get (), subc);
7885                 g_assert (!subc->has_references);
7886                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7887                 g_free (val);
7888                 return obj;
7889         }
7890         case MONO_TYPE_SZARRAY: {
7891                 MonoArray *arr;
7892                 guint32 i, alen, basetype;
7893                 alen = read32 (p);
7894                 p += 4;
7895                 if (alen == 0xffffffff) {
7896                         *end = p;
7897                         return NULL;
7898                 }
7899                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7900                 basetype = tklass->byval_arg.type;
7901                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7902                         basetype = mono_class_enum_basetype (tklass)->type;
7903                 switch (basetype)
7904                 {
7905                         case MONO_TYPE_U1:
7906                         case MONO_TYPE_I1:
7907                         case MONO_TYPE_BOOLEAN:
7908                                 for (i = 0; i < alen; i++) {
7909                                         MonoBoolean val = *p++;
7910                                         mono_array_set (arr, MonoBoolean, i, val);
7911                                 }
7912                                 break;
7913                         case MONO_TYPE_CHAR:
7914                         case MONO_TYPE_U2:
7915                         case MONO_TYPE_I2:
7916                                 for (i = 0; i < alen; i++) {
7917                                         guint16 val = read16 (p);
7918                                         mono_array_set (arr, guint16, i, val);
7919                                         p += 2;
7920                                 }
7921                                 break;
7922                         case MONO_TYPE_R4:
7923                         case MONO_TYPE_U4:
7924                         case MONO_TYPE_I4:
7925                                 for (i = 0; i < alen; i++) {
7926                                         guint32 val = read32 (p);
7927                                         mono_array_set (arr, guint32, i, val);
7928                                         p += 4;
7929                                 }
7930                                 break;
7931                         case MONO_TYPE_R8:
7932                                 for (i = 0; i < alen; i++) {
7933                                         double val;
7934                                         readr8 (p, &val);
7935                                         mono_array_set (arr, double, i, val);
7936                                         p += 8;
7937                                 }
7938                                 break;
7939                         case MONO_TYPE_U8:
7940                         case MONO_TYPE_I8:
7941                                 for (i = 0; i < alen; i++) {
7942                                         guint64 val = read64 (p);
7943                                         mono_array_set (arr, guint64, i, val);
7944                                         p += 8;
7945                                 }
7946                                 break;
7947                         case MONO_TYPE_CLASS:
7948                         case MONO_TYPE_OBJECT:
7949                         case MONO_TYPE_STRING:
7950                                 for (i = 0; i < alen; i++) {
7951                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7952                                         mono_array_setref (arr, i, item);
7953                                 }
7954                                 break;
7955                         default:
7956                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7957                 }
7958                 *end=p;
7959                 return arr;
7960         }
7961         default:
7962                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7963         }
7964         return NULL;
7965 }
7966
7967 static MonoObject*
7968 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7969 {
7970         static MonoClass *klass;
7971         static MonoMethod *ctor;
7972         MonoObject *retval;
7973         void *params [2], *unboxed;
7974
7975         if (!klass)
7976                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7977         if (!ctor)
7978                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7979         
7980         params [0] = mono_type_get_object (mono_domain_get (), t);
7981         params [1] = val;
7982         retval = mono_object_new (mono_domain_get (), klass);
7983         unboxed = mono_object_unbox (retval);
7984         mono_runtime_invoke (ctor, unboxed, params, NULL);
7985
7986         return retval;
7987 }
7988
7989 static MonoObject*
7990 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7991 {
7992         static MonoClass *klass;
7993         static MonoMethod *ctor;
7994         MonoObject *retval;
7995         void *unboxed, *params [2];
7996
7997         if (!klass)
7998                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7999         if (!ctor)
8000                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8001
8002         params [0] = minfo;
8003         params [1] = typedarg;
8004         retval = mono_object_new (mono_domain_get (), klass);
8005         unboxed = mono_object_unbox (retval);
8006         mono_runtime_invoke (ctor, unboxed, params, NULL);
8007
8008         return retval;
8009 }
8010
8011 static gboolean
8012 type_is_reference (MonoType *type)
8013 {
8014         switch (type->type) {
8015         case MONO_TYPE_BOOLEAN:
8016         case MONO_TYPE_CHAR:
8017         case MONO_TYPE_U:
8018         case MONO_TYPE_I:
8019         case MONO_TYPE_U1:
8020         case MONO_TYPE_I1:
8021         case MONO_TYPE_U2:
8022         case MONO_TYPE_I2:
8023         case MONO_TYPE_U4:
8024         case MONO_TYPE_I4:
8025         case MONO_TYPE_U8:
8026         case MONO_TYPE_I8:
8027         case MONO_TYPE_R8:
8028         case MONO_TYPE_R4:
8029         case MONO_TYPE_VALUETYPE:
8030                 return FALSE;
8031         default:
8032                 return TRUE;
8033         }
8034 }
8035
8036 static void
8037 free_param_data (MonoMethodSignature *sig, void **params) {
8038         int i;
8039         for (i = 0; i < sig->param_count; ++i) {
8040                 if (!type_is_reference (sig->params [i]))
8041                         g_free (params [i]);
8042         }
8043 }
8044
8045 /*
8046  * Find the field index in the metadata FieldDef table.
8047  */
8048 static guint32
8049 find_field_index (MonoClass *klass, MonoClassField *field) {
8050         int i;
8051
8052         for (i = 0; i < klass->field.count; ++i) {
8053                 if (field == &klass->fields [i])
8054                         return klass->field.first + 1 + i;
8055         }
8056         return 0;
8057 }
8058
8059 /*
8060  * Find the property index in the metadata Property table.
8061  */
8062 static guint32
8063 find_property_index (MonoClass *klass, MonoProperty *property) {
8064         int i;
8065
8066         for (i = 0; i < klass->ext->property.count; ++i) {
8067                 if (property == &klass->ext->properties [i])
8068                         return klass->ext->property.first + 1 + i;
8069         }
8070         return 0;
8071 }
8072
8073 /*
8074  * Find the event index in the metadata Event table.
8075  */
8076 static guint32
8077 find_event_index (MonoClass *klass, MonoEvent *event) {
8078         int i;
8079
8080         for (i = 0; i < klass->ext->event.count; ++i) {
8081                 if (event == &klass->ext->events [i])
8082                         return klass->ext->event.first + 1 + i;
8083         }
8084         return 0;
8085 }
8086
8087 static MonoObject*
8088 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8089 {
8090         const char *p = (const char*)data;
8091         const char *named;
8092         guint32 i, j, num_named;
8093         MonoObject *attr;
8094         void *params_buf [32];
8095         void **params;
8096         MonoMethodSignature *sig;
8097
8098         mono_error_init (error);
8099
8100         mono_class_init (method->klass);
8101
8102         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8103                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8104                 return NULL;
8105         }
8106
8107         if (len == 0) {
8108                 attr = mono_object_new (mono_domain_get (), method->klass);
8109                 mono_runtime_invoke (method, attr, NULL, NULL);
8110                 return attr;
8111         }
8112
8113         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8114                 return NULL;
8115
8116         /*g_print ("got attr %s\n", method->klass->name);*/
8117
8118         sig = mono_method_signature (method);
8119         if (sig->param_count < 32)
8120                 params = params_buf;
8121         else
8122                 /* Allocate using GC so it gets GC tracking */
8123                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8124
8125         /* skip prolog */
8126         p += 2;
8127         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8128                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8129         }
8130
8131         named = p;
8132         attr = mono_object_new (mono_domain_get (), method->klass);
8133         mono_runtime_invoke (method, attr, params, NULL);
8134         free_param_data (method->signature, params);
8135         num_named = read16 (named);
8136         named += 2;
8137         for (j = 0; j < num_named; j++) {
8138                 gint name_len;
8139                 char *name, named_type, data_type;
8140                 named_type = *named++;
8141                 data_type = *named++; /* type of data */
8142                 if (data_type == MONO_TYPE_SZARRAY)
8143                         data_type = *named++;
8144                 if (data_type == MONO_TYPE_ENUM) {
8145                         gint type_len;
8146                         char *type_name;
8147                         type_len = mono_metadata_decode_blob_size (named, &named);
8148                         type_name = g_malloc (type_len + 1);
8149                         memcpy (type_name, named, type_len);
8150                         type_name [type_len] = 0;
8151                         named += type_len;
8152                         /* FIXME: lookup the type and check type consistency */
8153                         g_free (type_name);
8154                 }
8155                 name_len = mono_metadata_decode_blob_size (named, &named);
8156                 name = g_malloc (name_len + 1);
8157                 memcpy (name, named, name_len);
8158                 name [name_len] = 0;
8159                 named += name_len;
8160                 if (named_type == 0x53) {
8161                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8162                         void *val = load_cattr_value (image, field->type, named, &named);
8163                         mono_field_set_value (attr, field, val);
8164                         if (!type_is_reference (field->type))
8165                                 g_free (val);
8166                 } else if (named_type == 0x54) {
8167                         MonoProperty *prop;
8168                         void *pparams [1];
8169                         MonoType *prop_type;
8170
8171                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8172                         /* can we have more that 1 arg in a custom attr named property? */
8173                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8174                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8175                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8176                         mono_property_set_value (prop, attr, pparams, NULL);
8177                         if (!type_is_reference (prop_type))
8178                                 g_free (pparams [0]);
8179                 }
8180                 g_free (name);
8181         }
8182
8183         if (params != params_buf)
8184                 mono_gc_free_fixed (params);
8185
8186         return attr;
8187 }
8188         
8189 /*
8190  * mono_reflection_create_custom_attr_data_args:
8191  *
8192  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8193  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8194  * NAMED_ARG_INFO will contain information about the named arguments.
8195  */
8196 void
8197 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)
8198 {
8199         MonoArray *typedargs, *namedargs;
8200         MonoClass *attrklass;
8201         MonoDomain *domain;
8202         const char *p = (const char*)data;
8203         const char *named;
8204         guint32 i, j, num_named;
8205         CattrNamedArg *arginfo = NULL;
8206
8207         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8208                 return;
8209
8210         mono_class_init (method->klass);
8211
8212         *typed_args = NULL;
8213         *named_args = NULL;
8214         *named_arg_info = NULL;
8215         
8216         domain = mono_domain_get ();
8217
8218         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8219                 return;
8220
8221         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8222         
8223         /* skip prolog */
8224         p += 2;
8225         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8226                 MonoObject *obj;
8227                 void *val;
8228
8229                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8230                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8231                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8232                 mono_array_setref (typedargs, i, obj);
8233
8234                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8235                         g_free (val);
8236         }
8237
8238         named = p;
8239         num_named = read16 (named);
8240         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8241         named += 2;
8242         attrklass = method->klass;
8243
8244         arginfo = g_new0 (CattrNamedArg, num_named);
8245         *named_arg_info = arginfo;
8246
8247         for (j = 0; j < num_named; j++) {
8248                 gint name_len;
8249                 char *name, named_type, data_type;
8250                 named_type = *named++;
8251                 data_type = *named++; /* type of data */
8252                 if (data_type == MONO_TYPE_SZARRAY)
8253                         data_type = *named++;
8254                 if (data_type == MONO_TYPE_ENUM) {
8255                         gint type_len;
8256                         char *type_name;
8257                         type_len = mono_metadata_decode_blob_size (named, &named);
8258                         type_name = g_malloc (type_len + 1);
8259                         memcpy (type_name, named, type_len);
8260                         type_name [type_len] = 0;
8261                         named += type_len;
8262                         /* FIXME: lookup the type and check type consistency */
8263                         g_free (type_name);
8264                 }
8265                 name_len = mono_metadata_decode_blob_size (named, &named);
8266                 name = g_malloc (name_len + 1);
8267                 memcpy (name, named, name_len);
8268                 name [name_len] = 0;
8269                 named += name_len;
8270                 if (named_type == 0x53) {
8271                         MonoObject *obj;
8272                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8273                         void *val;
8274
8275                         arginfo [j].type = field->type;
8276                         arginfo [j].field = field;
8277
8278                         val = load_cattr_value (image, field->type, named, &named);
8279                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8280                         mono_array_setref (namedargs, j, obj);
8281                         if (!type_is_reference (field->type))
8282                                 g_free (val);
8283                 } else if (named_type == 0x54) {
8284                         MonoObject *obj;
8285                         MonoType *prop_type;
8286                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8287                         void *val;
8288
8289                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8290                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8291
8292                         arginfo [j].type = prop_type;
8293                         arginfo [j].prop = prop;
8294
8295                         val = load_cattr_value (image, prop_type, named, &named);
8296                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8297                         mono_array_setref (namedargs, j, obj);
8298                         if (!type_is_reference (prop_type))
8299                                 g_free (val);
8300                 }
8301                 g_free (name);
8302         }
8303
8304         *typed_args = typedargs;
8305         *named_args = namedargs;
8306 }
8307
8308 void
8309 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8310 {
8311         MonoDomain *domain;
8312         MonoArray *typedargs, *namedargs;
8313         MonoImage *image;
8314         MonoMethod *method;
8315         CattrNamedArg *arginfo;
8316         int i;
8317
8318         *ctor_args = NULL;
8319         *named_args = NULL;
8320
8321         if (len == 0)
8322                 return;
8323
8324         image = assembly->assembly->image;
8325         method = ref_method->method;
8326         domain = mono_object_domain (ref_method);
8327
8328         if (!mono_class_init (method->klass))
8329                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8330
8331         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8332         if (mono_loader_get_last_error ())
8333                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8334
8335         if (!typedargs || !namedargs)
8336                 return;
8337
8338         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8339                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8340                 MonoObject *typedarg;
8341
8342                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8343                 mono_array_setref (typedargs, i, typedarg);
8344         }
8345
8346         for (i = 0; i < mono_array_length (namedargs); ++i) {
8347                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8348                 MonoObject *typedarg, *namedarg, *minfo;
8349
8350                 if (arginfo [i].prop)
8351                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8352                 else
8353                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8354
8355                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8356                 namedarg = create_cattr_named_arg (minfo, typedarg);
8357
8358                 mono_array_setref (namedargs, i, namedarg);
8359         }
8360
8361         *ctor_args = typedargs;
8362         *named_args = namedargs;
8363 }
8364
8365 static MonoObject*
8366 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8367 {
8368         static MonoMethod *ctor;
8369         MonoDomain *domain;
8370         MonoObject *attr;
8371         void *params [4];
8372
8373         g_assert (image->assembly);
8374
8375         if (!ctor)
8376                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8377
8378         domain = mono_domain_get ();
8379         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8380         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8381         params [1] = mono_assembly_get_object (domain, image->assembly);
8382         params [2] = (gpointer)&cattr->data;
8383         params [3] = &cattr->data_size;
8384         mono_runtime_invoke (ctor, attr, params, NULL);
8385         return attr;
8386 }
8387
8388 static MonoArray*
8389 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8390 {
8391         MonoArray *result;
8392         MonoObject *attr;
8393         int i, n;
8394
8395         mono_error_init (error);
8396
8397         n = 0;
8398         for (i = 0; i < cinfo->num_attrs; ++i) {
8399                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8400                         n ++;
8401         }
8402
8403         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8404         n = 0;
8405         for (i = 0; i < cinfo->num_attrs; ++i) {
8406                 if (!cinfo->attrs [i].ctor)
8407                         /* The cattr type is not finished yet */
8408                         /* We should include the type name but cinfo doesn't contain it */
8409                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8410                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8411                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8412                         if (!mono_error_ok (error))
8413                                 return result;
8414                         mono_array_setref (result, n, attr);
8415                         n ++;
8416                 }
8417         }
8418         return result;
8419 }
8420
8421 MonoArray*
8422 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8423 {
8424         MonoError error;
8425
8426         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8427 }
8428
8429 static MonoArray*
8430 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8431 {
8432         MonoArray *result;
8433         MonoObject *attr;
8434         int i;
8435         
8436         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8437         for (i = 0; i < cinfo->num_attrs; ++i) {
8438                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8439                 mono_array_setref (result, i, attr);
8440         }
8441         return result;
8442 }
8443
8444 /**
8445  * mono_custom_attrs_from_index:
8446  *
8447  * Returns: NULL if no attributes are found or if a loading error occurs.
8448  */
8449 MonoCustomAttrInfo*
8450 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8451 {
8452         guint32 mtoken, i, len;
8453         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8454         MonoTableInfo *ca;
8455         MonoCustomAttrInfo *ainfo;
8456         GList *tmp, *list = NULL;
8457         const char *data;
8458
8459         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8460
8461         i = mono_metadata_custom_attrs_from_index (image, idx);
8462         if (!i)
8463                 return NULL;
8464         i --;
8465         while (i < ca->rows) {
8466                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8467                         break;
8468                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8469                 ++i;
8470         }
8471         len = g_list_length (list);
8472         if (!len)
8473                 return NULL;
8474         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8475         ainfo->num_attrs = len;
8476         ainfo->image = image;
8477         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8478                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8479                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8480                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8481                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8482                         mtoken |= MONO_TOKEN_METHOD_DEF;
8483                         break;
8484                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8485                         mtoken |= MONO_TOKEN_MEMBER_REF;
8486                         break;
8487                 default:
8488                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8489                         break;
8490                 }
8491                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8492                 if (!ainfo->attrs [i].ctor) {
8493                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8494                         g_list_free (list);
8495                         g_free (ainfo);
8496                         return NULL;
8497                 }
8498
8499                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8500                         /*FIXME raising an exception here doesn't make any sense*/
8501                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8502                         g_list_free (list);
8503                         g_free (ainfo);
8504                         return NULL;
8505                 }
8506                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8507                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8508                 ainfo->attrs [i].data = (guchar*)data;
8509         }
8510         g_list_free (list);
8511
8512         return ainfo;
8513 }
8514
8515 MonoCustomAttrInfo*
8516 mono_custom_attrs_from_method (MonoMethod *method)
8517 {
8518         guint32 idx;
8519
8520         /*
8521          * An instantiated method has the same cattrs as the generic method definition.
8522          *
8523          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8524          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8525          */
8526         if (method->is_inflated)
8527                 method = ((MonoMethodInflated *) method)->declaring;
8528         
8529         if (method->dynamic || method->klass->image->dynamic)
8530                 return lookup_custom_attr (method->klass->image, method);
8531
8532         if (!method->token)
8533                 /* Synthetic methods */
8534                 return NULL;
8535
8536         idx = mono_method_get_index (method);
8537         idx <<= MONO_CUSTOM_ATTR_BITS;
8538         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8539         return mono_custom_attrs_from_index (method->klass->image, idx);
8540 }
8541
8542 MonoCustomAttrInfo*
8543 mono_custom_attrs_from_class (MonoClass *klass)
8544 {
8545         guint32 idx;
8546
8547         if (klass->generic_class)
8548                 klass = klass->generic_class->container_class;
8549
8550         if (klass->image->dynamic)
8551                 return lookup_custom_attr (klass->image, klass);
8552
8553         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8554                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8555                 idx <<= MONO_CUSTOM_ATTR_BITS;
8556                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8557         } else {
8558                 idx = mono_metadata_token_index (klass->type_token);
8559                 idx <<= MONO_CUSTOM_ATTR_BITS;
8560                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8561         }
8562         return mono_custom_attrs_from_index (klass->image, idx);
8563 }
8564
8565 MonoCustomAttrInfo*
8566 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8567 {
8568         guint32 idx;
8569         
8570         if (assembly->image->dynamic)
8571                 return lookup_custom_attr (assembly->image, assembly);
8572         idx = 1; /* there is only one assembly */
8573         idx <<= MONO_CUSTOM_ATTR_BITS;
8574         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8575         return mono_custom_attrs_from_index (assembly->image, idx);
8576 }
8577
8578 static MonoCustomAttrInfo*
8579 mono_custom_attrs_from_module (MonoImage *image)
8580 {
8581         guint32 idx;
8582         
8583         if (image->dynamic)
8584                 return lookup_custom_attr (image, image);
8585         idx = 1; /* there is only one module */
8586         idx <<= MONO_CUSTOM_ATTR_BITS;
8587         idx |= MONO_CUSTOM_ATTR_MODULE;
8588         return mono_custom_attrs_from_index (image, idx);
8589 }
8590
8591 MonoCustomAttrInfo*
8592 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8593 {
8594         guint32 idx;
8595         
8596         if (klass->image->dynamic) {
8597                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8598                 return lookup_custom_attr (klass->image, property);
8599         }
8600         idx = find_property_index (klass, property);
8601         idx <<= MONO_CUSTOM_ATTR_BITS;
8602         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8603         return mono_custom_attrs_from_index (klass->image, idx);
8604 }
8605
8606 MonoCustomAttrInfo*
8607 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8608 {
8609         guint32 idx;
8610         
8611         if (klass->image->dynamic) {
8612                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8613                 return lookup_custom_attr (klass->image, event);
8614         }
8615         idx = find_event_index (klass, event);
8616         idx <<= MONO_CUSTOM_ATTR_BITS;
8617         idx |= MONO_CUSTOM_ATTR_EVENT;
8618         return mono_custom_attrs_from_index (klass->image, idx);
8619 }
8620
8621 MonoCustomAttrInfo*
8622 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8623 {
8624         guint32 idx;
8625         if (klass->image->dynamic) {
8626                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8627                 return lookup_custom_attr (klass->image, field);
8628         }
8629         idx = find_field_index (klass, field);
8630         idx <<= MONO_CUSTOM_ATTR_BITS;
8631         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8632         return mono_custom_attrs_from_index (klass->image, idx);
8633 }
8634
8635 MonoCustomAttrInfo*
8636 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8637 {
8638         MonoTableInfo *ca;
8639         guint32 i, idx, method_index;
8640         guint32 param_list, param_last, param_pos, found;
8641         MonoImage *image;
8642         MonoReflectionMethodAux *aux;
8643
8644         /*
8645          * An instantiated method has the same cattrs as the generic method definition.
8646          *
8647          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8648          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8649          */
8650         if (method->is_inflated)
8651                 method = ((MonoMethodInflated *) method)->declaring;
8652
8653         if (method->klass->image->dynamic) {
8654                 MonoCustomAttrInfo *res, *ainfo;
8655                 int size;
8656
8657                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8658                 if (!aux || !aux->param_cattr)
8659                         return NULL;
8660
8661                 /* Need to copy since it will be freed later */
8662                 ainfo = aux->param_cattr [param];
8663                 if (!ainfo)
8664                         return NULL;
8665                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8666                 res = g_malloc0 (size);
8667                 memcpy (res, ainfo, size);
8668                 return res;
8669         }
8670
8671         image = method->klass->image;
8672         method_index = mono_method_get_index (method);
8673         if (!method_index)
8674                 return NULL;
8675         ca = &image->tables [MONO_TABLE_METHOD];
8676
8677         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8678         if (method_index == ca->rows) {
8679                 ca = &image->tables [MONO_TABLE_PARAM];
8680                 param_last = ca->rows + 1;
8681         } else {
8682                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8683                 ca = &image->tables [MONO_TABLE_PARAM];
8684         }
8685         found = FALSE;
8686         for (i = param_list; i < param_last; ++i) {
8687                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8688                 if (param_pos == param) {
8689                         found = TRUE;
8690                         break;
8691                 }
8692         }
8693         if (!found)
8694                 return NULL;
8695         idx = i;
8696         idx <<= MONO_CUSTOM_ATTR_BITS;
8697         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8698         return mono_custom_attrs_from_index (image, idx);
8699 }
8700
8701 gboolean
8702 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8703 {
8704         int i;
8705         MonoClass *klass;
8706         for (i = 0; i < ainfo->num_attrs; ++i) {
8707                 klass = ainfo->attrs [i].ctor->klass;
8708                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8709                         return TRUE;
8710         }
8711         return FALSE;
8712 }
8713
8714 MonoObject*
8715 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8716 {
8717         int i, attr_index;
8718         MonoClass *klass;
8719         MonoArray *attrs;
8720
8721         attr_index = -1;
8722         for (i = 0; i < ainfo->num_attrs; ++i) {
8723                 klass = ainfo->attrs [i].ctor->klass;
8724                 if (mono_class_has_parent (klass, attr_klass)) {
8725                         attr_index = i;
8726                         break;
8727                 }
8728         }
8729         if (attr_index == -1)
8730                 return NULL;
8731
8732         attrs = mono_custom_attrs_construct (ainfo);
8733         if (attrs)
8734                 return mono_array_get (attrs, MonoObject*, attr_index);
8735         else
8736                 return NULL;
8737 }
8738
8739 /*
8740  * mono_reflection_get_custom_attrs_info:
8741  * @obj: a reflection object handle
8742  *
8743  * Return the custom attribute info for attributes defined for the
8744  * reflection handle @obj. The objects.
8745  *
8746  * FIXME this function leaks like a sieve for SRE objects.
8747  */
8748 MonoCustomAttrInfo*
8749 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8750 {
8751         MonoClass *klass;
8752         MonoCustomAttrInfo *cinfo = NULL;
8753         
8754         klass = obj->vtable->klass;
8755         if (klass == mono_defaults.monotype_class) {
8756                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8757                 klass = mono_class_from_mono_type (type);
8758                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8759                 cinfo = mono_custom_attrs_from_class (klass);
8760         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8761                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8762                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8763         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8764                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8765                 cinfo = mono_custom_attrs_from_module (module->image);
8766         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8767                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8768                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8769         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8770                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8771                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8772         } else if (strcmp ("MonoField", klass->name) == 0) {
8773                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8774                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8775         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8776                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8777                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8778         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8779                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8780                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8781         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8782                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8783                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8784                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8785                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8786                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8787                 } else if (is_sr_mono_property (member_class)) {
8788                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8789                         MonoMethod *method;
8790                         if (!(method = prop->property->get))
8791                                 method = prop->property->set;
8792                         g_assert (method);
8793
8794                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8795                 } 
8796 #ifndef DISABLE_REFLECTION_EMIT
8797                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8798                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8799                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8800                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8801                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8802                         MonoMethod *method = NULL;
8803                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8804                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8805                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8806                                 method = ((MonoReflectionMethod *)c->cb)->method;
8807                         else
8808                                 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));
8809
8810                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8811                 } 
8812 #endif
8813                 else {
8814                         char *type_name = mono_type_get_full_name (member_class);
8815                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8816                         MonoException *ex = mono_get_exception_not_supported  (msg);
8817                         g_free (type_name);
8818                         g_free (msg);
8819                         mono_raise_exception (ex);
8820                 }
8821         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8822                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8823                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8824         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8825                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8826                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8827         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8828                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8829                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8830         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8831                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8832                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8833         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8834                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8835                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8836         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8837                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8838                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8839         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8840                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8841                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8842         } else { /* handle other types here... */
8843                 g_error ("get custom attrs not yet supported for %s", klass->name);
8844         }
8845
8846         return cinfo;
8847 }
8848
8849 /*
8850  * mono_reflection_get_custom_attrs_by_type:
8851  * @obj: a reflection object handle
8852  *
8853  * Return an array with all the custom attributes defined of the
8854  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8855  * of that type are returned. The objects are fully build. Return NULL if a loading error
8856  * occurs.
8857  */
8858 MonoArray*
8859 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8860 {
8861         MonoArray *result;
8862         MonoCustomAttrInfo *cinfo;
8863
8864         mono_error_init (error);
8865
8866         cinfo = mono_reflection_get_custom_attrs_info (obj);
8867         if (cinfo) {
8868                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8869                 if (!cinfo->cached)
8870                         mono_custom_attrs_free (cinfo);
8871         } else {
8872                 if (mono_loader_get_last_error ())
8873                         return NULL;
8874                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8875         }
8876
8877         return result;
8878 }
8879
8880 /*
8881  * mono_reflection_get_custom_attrs:
8882  * @obj: a reflection object handle
8883  *
8884  * Return an array with all the custom attributes defined of the
8885  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8886  * occurs.
8887  */
8888 MonoArray*
8889 mono_reflection_get_custom_attrs (MonoObject *obj)
8890 {
8891         MonoError error;
8892
8893         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8894 }
8895
8896 /*
8897  * mono_reflection_get_custom_attrs_data:
8898  * @obj: a reflection obj handle
8899  *
8900  * Returns an array of System.Reflection.CustomAttributeData,
8901  * which include information about attributes reflected on
8902  * types loaded using the Reflection Only methods
8903  */
8904 MonoArray*
8905 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8906 {
8907         MonoArray *result;
8908         MonoCustomAttrInfo *cinfo;
8909
8910         cinfo = mono_reflection_get_custom_attrs_info (obj);
8911         if (cinfo) {
8912                 result = mono_custom_attrs_data_construct (cinfo);
8913                 if (!cinfo->cached)
8914                         mono_custom_attrs_free (cinfo);
8915         } else
8916                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8917
8918         return result;
8919 }
8920
8921 static MonoReflectionType*
8922 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8923 {
8924         static MonoMethod *method_get_underlying_system_type = NULL;
8925         MonoMethod *usertype_method;
8926
8927         if (!method_get_underlying_system_type)
8928                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8929         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8930         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8931 }
8932
8933
8934 static gboolean
8935 is_corlib_type (MonoClass *class)
8936 {
8937         return class->image == mono_defaults.corlib;
8938 }
8939
8940 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8941         static MonoClass *cached_class; \
8942         if (cached_class) \
8943                 return cached_class == _class; \
8944         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8945                 cached_class = _class; \
8946                 return TRUE; \
8947         } \
8948         return FALSE; \
8949 } while (0) \
8950
8951
8952 #ifndef DISABLE_REFLECTION_EMIT
8953 static gboolean
8954 is_sre_array (MonoClass *class)
8955 {
8956         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8957 }
8958
8959 static gboolean
8960 is_sre_byref (MonoClass *class)
8961 {
8962         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8963 }
8964
8965 static gboolean
8966 is_sre_pointer (MonoClass *class)
8967 {
8968         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8969 }
8970
8971 static gboolean
8972 is_sre_generic_instance (MonoClass *class)
8973 {
8974         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8975 }
8976
8977 static gboolean
8978 is_sre_type_builder (MonoClass *class)
8979 {
8980         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8981 }
8982
8983 static gboolean
8984 is_sre_method_builder (MonoClass *class)
8985 {
8986         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8987 }
8988
8989 static gboolean
8990 is_sre_ctor_builder (MonoClass *class)
8991 {
8992         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8993 }
8994
8995 static gboolean
8996 is_sre_field_builder (MonoClass *class)
8997 {
8998         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8999 }
9000
9001 static gboolean
9002 is_sre_method_on_tb_inst (MonoClass *class)
9003 {
9004         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9005 }
9006
9007 static gboolean
9008 is_sre_ctor_on_tb_inst (MonoClass *class)
9009 {
9010         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9011 }
9012
9013 MonoType*
9014 mono_reflection_type_get_handle (MonoReflectionType* ref)
9015 {
9016         MonoClass *class;
9017         if (!ref)
9018                 return NULL;
9019         if (ref->type)
9020                 return ref->type;
9021
9022         if (is_usertype (ref)) {
9023                 ref = mono_reflection_type_get_underlying_system_type (ref);
9024                 if (ref == NULL || is_usertype (ref))
9025                         return NULL;
9026                 if (ref->type)
9027                         return ref->type;
9028         }
9029
9030         class = mono_object_class (ref);
9031
9032         if (is_sre_array (class)) {
9033                 MonoType *res;
9034                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9035                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9036                 g_assert (base);
9037                 if (sre_array->rank == 0) //single dimentional array
9038                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9039                 else
9040                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9041                 sre_array->type.type = res;
9042                 return res;
9043         } else if (is_sre_byref (class)) {
9044                 MonoType *res;
9045                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9046                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9047                 g_assert (base);
9048                 res = &mono_class_from_mono_type (base)->this_arg;
9049                 sre_byref->type.type = res;
9050                 return res;
9051         } else if (is_sre_pointer (class)) {
9052                 MonoType *res;
9053                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9054                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9055                 g_assert (base);
9056                 res = &mono_ptr_class_get (base)->byval_arg;
9057                 sre_pointer->type.type = res;
9058                 return res;
9059         } else if (is_sre_generic_instance (class)) {
9060                 MonoType *res, **types;
9061                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9062                 int i, count;
9063
9064                 count = mono_array_length (gclass->type_arguments);
9065                 types = g_new0 (MonoType*, count);
9066                 for (i = 0; i < count; ++i) {
9067                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9068                         types [i] = mono_reflection_type_get_handle (t);
9069                         if (!types[i]) {
9070                                 g_free (types);
9071                                 return NULL;
9072                         }
9073                 }
9074
9075                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9076                 g_free (types);
9077                 g_assert (res);
9078                 gclass->type.type = res;
9079                 return res;
9080         }
9081
9082         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9083         return NULL;
9084 }
9085
9086
9087
9088 void
9089 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9090 {
9091         mono_reflection_type_get_handle (type);
9092 }
9093
9094 void
9095 mono_reflection_register_with_runtime (MonoReflectionType *type)
9096 {
9097         MonoType *res = mono_reflection_type_get_handle (type);
9098         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9099         MonoClass *class;
9100
9101         if (!res)
9102                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9103
9104         class = mono_class_from_mono_type (res);
9105
9106         mono_loader_lock (); /*same locking as mono_type_get_object*/
9107         mono_domain_lock (domain);
9108
9109         if (!class->image->dynamic) {
9110                 mono_class_setup_supertypes (class);
9111         } else {
9112                 if (!domain->type_hash)
9113                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9114                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9115                 mono_g_hash_table_insert (domain->type_hash, res, type);
9116         }
9117         mono_domain_unlock (domain);
9118         mono_loader_unlock ();
9119 }
9120
9121 /**
9122  * LOCKING: Assumes the loader lock is held.
9123  */
9124 static MonoMethodSignature*
9125 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9126         MonoMethodSignature *sig;
9127         int count, i;
9128
9129         count = parameters? mono_array_length (parameters): 0;
9130
9131         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9132         sig->param_count = count;
9133         sig->sentinelpos = -1; /* FIXME */
9134         for (i = 0; i < count; ++i)
9135                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9136         return sig;
9137 }
9138
9139 /**
9140  * LOCKING: Assumes the loader lock is held.
9141  */
9142 static MonoMethodSignature*
9143 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9144         MonoMethodSignature *sig;
9145
9146         sig = parameters_to_signature (image, ctor->parameters);
9147         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9148         sig->ret = &mono_defaults.void_class->byval_arg;
9149         return sig;
9150 }
9151
9152 /**
9153  * LOCKING: Assumes the loader lock is held.
9154  */
9155 static MonoMethodSignature*
9156 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9157         MonoMethodSignature *sig;
9158
9159         sig = parameters_to_signature (image, method->parameters);
9160         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9161         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9162         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9163         return sig;
9164 }
9165
9166 static MonoMethodSignature*
9167 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9168         MonoMethodSignature *sig;
9169
9170         sig = parameters_to_signature (NULL, method->parameters);
9171         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9172         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9173         sig->generic_param_count = 0;
9174         return sig;
9175 }
9176
9177 static void
9178 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9179 {
9180         MonoClass *klass = mono_object_class (prop);
9181         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9182                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9183                 *name = mono_string_to_utf8 (pb->name);
9184                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9185         } else {
9186                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9187                 *name = g_strdup (p->property->name);
9188                 if (p->property->get)
9189                         *type = mono_method_signature (p->property->get)->ret;
9190                 else
9191                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9192         }
9193 }
9194
9195 static void
9196 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9197 {
9198         MonoClass *klass = mono_object_class (field);
9199         if (strcmp (klass->name, "FieldBuilder") == 0) {
9200                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9201                 *name = mono_string_to_utf8 (fb->name);
9202                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9203         } else {
9204                 MonoReflectionField *f = (MonoReflectionField *)field;
9205                 *name = g_strdup (mono_field_get_name (f->field));
9206                 *type = f->field->type;
9207         }
9208 }
9209
9210 #else /* DISABLE_REFLECTION_EMIT */
9211
9212 void
9213 mono_reflection_register_with_runtime (MonoReflectionType *type)
9214 {
9215         /* This is empty */
9216 }
9217
9218 static gboolean
9219 is_sre_type_builder (MonoClass *class)
9220 {
9221         return FALSE;
9222 }
9223
9224 static gboolean
9225 is_sre_generic_instance (MonoClass *class)
9226 {
9227         return FALSE;
9228 }
9229
9230 static void
9231 init_type_builder_generics (MonoObject *type)
9232 {
9233 }
9234
9235 #endif /* !DISABLE_REFLECTION_EMIT */
9236
9237
9238 static gboolean
9239 is_sr_mono_field (MonoClass *class)
9240 {
9241         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9242 }
9243
9244 static gboolean
9245 is_sr_mono_property (MonoClass *class)
9246 {
9247         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9248 }
9249
9250 static gboolean
9251 is_sr_mono_method (MonoClass *class)
9252 {
9253         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9254 }
9255
9256 static gboolean
9257 is_sr_mono_cmethod (MonoClass *class)
9258 {
9259         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9260 }
9261
9262 static gboolean
9263 is_sr_mono_generic_method (MonoClass *class)
9264 {
9265         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9266 }
9267
9268 static gboolean
9269 is_sr_mono_generic_cmethod (MonoClass *class)
9270 {
9271         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9272 }
9273
9274 gboolean
9275 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9276 {
9277         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9278 }
9279
9280 static gboolean
9281 is_usertype (MonoReflectionType *ref)
9282 {
9283         MonoClass *class = mono_object_class (ref);
9284         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9285 }
9286
9287 static MonoReflectionType*
9288 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9289 {
9290         if (!type || type->type)
9291                 return type;
9292
9293         if (is_usertype (type)) {
9294                 type = mono_reflection_type_get_underlying_system_type (type);
9295                 if (is_usertype (type))
9296                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9297         }
9298
9299         return type;
9300 }
9301 /*
9302  * Encode a value in a custom attribute stream of bytes.
9303  * The value to encode is either supplied as an object in argument val
9304  * (valuetypes are boxed), or as a pointer to the data in the
9305  * argument argval.
9306  * @type represents the type of the value
9307  * @buffer is the start of the buffer
9308  * @p the current position in the buffer
9309  * @buflen contains the size of the buffer and is used to return the new buffer size
9310  * if this needs to be realloced.
9311  * @retbuffer and @retp return the start and the position of the buffer
9312  */
9313 static void
9314 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9315 {
9316         MonoTypeEnum simple_type;
9317         
9318         if ((p-buffer) + 10 >= *buflen) {
9319                 char *newbuf;
9320                 *buflen *= 2;
9321                 newbuf = g_realloc (buffer, *buflen);
9322                 p = newbuf + (p-buffer);
9323                 buffer = newbuf;
9324         }
9325         if (!argval)
9326                 argval = ((char*)arg + sizeof (MonoObject));
9327         simple_type = type->type;
9328 handle_enum:
9329         switch (simple_type) {
9330         case MONO_TYPE_BOOLEAN:
9331         case MONO_TYPE_U1:
9332         case MONO_TYPE_I1:
9333                 *p++ = *argval;
9334                 break;
9335         case MONO_TYPE_CHAR:
9336         case MONO_TYPE_U2:
9337         case MONO_TYPE_I2:
9338                 swap_with_size (p, argval, 2, 1);
9339                 p += 2;
9340                 break;
9341         case MONO_TYPE_U4:
9342         case MONO_TYPE_I4:
9343         case MONO_TYPE_R4:
9344                 swap_with_size (p, argval, 4, 1);
9345                 p += 4;
9346                 break;
9347         case MONO_TYPE_R8:
9348 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9349                 p [0] = argval [4];
9350                 p [1] = argval [5];
9351                 p [2] = argval [6];
9352                 p [3] = argval [7];
9353                 p [4] = argval [0];
9354                 p [5] = argval [1];
9355                 p [6] = argval [2];
9356                 p [7] = argval [3];
9357 #else
9358                 swap_with_size (p, argval, 8, 1);
9359 #endif
9360                 p += 8;
9361                 break;
9362         case MONO_TYPE_U8:
9363         case MONO_TYPE_I8:
9364                 swap_with_size (p, argval, 8, 1);
9365                 p += 8;
9366                 break;
9367         case MONO_TYPE_VALUETYPE:
9368                 if (type->data.klass->enumtype) {
9369                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9370                         goto handle_enum;
9371                 } else {
9372                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9373                 }
9374                 break;
9375         case MONO_TYPE_STRING: {
9376                 char *str;
9377                 guint32 slen;
9378                 if (!arg) {
9379                         *p++ = 0xFF;
9380                         break;
9381                 }
9382                 str = mono_string_to_utf8 ((MonoString*)arg);
9383                 slen = strlen (str);
9384                 if ((p-buffer) + 10 + slen >= *buflen) {
9385                         char *newbuf;
9386                         *buflen *= 2;
9387                         *buflen += slen;
9388                         newbuf = g_realloc (buffer, *buflen);
9389                         p = newbuf + (p-buffer);
9390                         buffer = newbuf;
9391                 }
9392                 mono_metadata_encode_value (slen, p, &p);
9393                 memcpy (p, str, slen);
9394                 p += slen;
9395                 g_free (str);
9396                 break;
9397         }
9398         case MONO_TYPE_CLASS: {
9399                 char *str;
9400                 guint32 slen;
9401                 if (!arg) {
9402                         *p++ = 0xFF;
9403                         break;
9404                 }
9405 handle_type:
9406                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9407                 slen = strlen (str);
9408                 if ((p-buffer) + 10 + slen >= *buflen) {
9409                         char *newbuf;
9410                         *buflen *= 2;
9411                         *buflen += slen;
9412                         newbuf = g_realloc (buffer, *buflen);
9413                         p = newbuf + (p-buffer);
9414                         buffer = newbuf;
9415                 }
9416                 mono_metadata_encode_value (slen, p, &p);
9417                 memcpy (p, str, slen);
9418                 p += slen;
9419                 g_free (str);
9420                 break;
9421         }
9422         case MONO_TYPE_SZARRAY: {
9423                 int len, i;
9424                 MonoClass *eclass, *arg_eclass;
9425
9426                 if (!arg) {
9427                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9428                         break;
9429                 }
9430                 len = mono_array_length ((MonoArray*)arg);
9431                 *p++ = len & 0xff;
9432                 *p++ = (len >> 8) & 0xff;
9433                 *p++ = (len >> 16) & 0xff;
9434                 *p++ = (len >> 24) & 0xff;
9435                 *retp = p;
9436                 *retbuffer = buffer;
9437                 eclass = type->data.klass;
9438                 arg_eclass = mono_object_class (arg)->element_class;
9439
9440                 if (!eclass) {
9441                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9442                         eclass = mono_defaults.object_class;
9443                 }
9444                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9445                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9446                         int elsize = mono_class_array_element_size (arg_eclass);
9447                         for (i = 0; i < len; ++i) {
9448                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9449                                 elptr += elsize;
9450                         }
9451                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9452                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9453                         int elsize = mono_class_array_element_size (eclass);
9454                         for (i = 0; i < len; ++i) {
9455                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9456                                 elptr += elsize;
9457                         }
9458                 } else {
9459                         for (i = 0; i < len; ++i) {
9460                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9461                         }
9462                 }
9463                 break;
9464         }
9465         case MONO_TYPE_OBJECT: {
9466                 MonoClass *klass;
9467                 char *str;
9468                 guint32 slen;
9469
9470                 /*
9471                  * The parameter type is 'object' but the type of the actual
9472                  * argument is not. So we have to add type information to the blob
9473                  * too. This is completely undocumented in the spec.
9474                  */
9475
9476                 if (arg == NULL) {
9477                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9478                         *p++ = 0xFF;
9479                         break;
9480                 }
9481                 
9482                 klass = mono_object_class (arg);
9483
9484                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9485                         *p++ = 0x50;
9486                         goto handle_type;
9487                 } else if (klass->enumtype) {
9488                         *p++ = 0x55;
9489                 } else if (klass == mono_defaults.string_class) {
9490                         simple_type = MONO_TYPE_STRING;
9491                         *p++ = 0x0E;
9492                         goto handle_enum;
9493                 } else if (klass->rank == 1) {
9494                         *p++ = 0x1D;
9495                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9496                                 /* See Partition II, Appendix B3 */
9497                                 *p++ = 0x51;
9498                         else
9499                                 *p++ = klass->element_class->byval_arg.type;
9500                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9501                         break;
9502                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9503                         *p++ = simple_type = klass->byval_arg.type;
9504                         goto handle_enum;
9505                 } else {
9506                         g_error ("unhandled type in custom attr");
9507                 }
9508                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9509                 slen = strlen (str);
9510                 if ((p-buffer) + 10 + slen >= *buflen) {
9511                         char *newbuf;
9512                         *buflen *= 2;
9513                         *buflen += slen;
9514                         newbuf = g_realloc (buffer, *buflen);
9515                         p = newbuf + (p-buffer);
9516                         buffer = newbuf;
9517                 }
9518                 mono_metadata_encode_value (slen, p, &p);
9519                 memcpy (p, str, slen);
9520                 p += slen;
9521                 g_free (str);
9522                 simple_type = mono_class_enum_basetype (klass)->type;
9523                 goto handle_enum;
9524         }
9525         default:
9526                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9527         }
9528         *retp = p;
9529         *retbuffer = buffer;
9530 }
9531
9532 static void
9533 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9534 {
9535         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9536                 char *str = type_get_qualified_name (type, NULL);
9537                 int slen = strlen (str);
9538
9539                 *p++ = 0x55;
9540                 /*
9541                  * This seems to be optional...
9542                  * *p++ = 0x80;
9543                  */
9544                 mono_metadata_encode_value (slen, p, &p);
9545                 memcpy (p, str, slen);
9546                 p += slen;
9547                 g_free (str);
9548         } else if (type->type == MONO_TYPE_OBJECT) {
9549                 *p++ = 0x51;
9550         } else if (type->type == MONO_TYPE_CLASS) {
9551                 /* it should be a type: encode_cattr_value () has the check */
9552                 *p++ = 0x50;
9553         } else {
9554                 mono_metadata_encode_value (type->type, p, &p);
9555                 if (type->type == MONO_TYPE_SZARRAY)
9556                         /* See the examples in Partition VI, Annex B */
9557                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9558         }
9559
9560         *retp = p;
9561 }
9562
9563 #ifndef DISABLE_REFLECTION_EMIT
9564 static void
9565 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9566 {
9567         int len;
9568         /* Preallocate a large enough buffer */
9569         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9570                 char *str = type_get_qualified_name (type, NULL);
9571                 len = strlen (str);
9572                 g_free (str);
9573         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9574                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9575                 len = strlen (str);
9576                 g_free (str);
9577         } else {
9578                 len = 0;
9579         }
9580         len += strlen (name);
9581
9582         if ((p-buffer) + 20 + len >= *buflen) {
9583                 char *newbuf;
9584                 *buflen *= 2;
9585                 *buflen += len;
9586                 newbuf = g_realloc (buffer, *buflen);
9587                 p = newbuf + (p-buffer);
9588                 buffer = newbuf;
9589         }
9590
9591         encode_field_or_prop_type (type, p, &p);
9592
9593         len = strlen (name);
9594         mono_metadata_encode_value (len, p, &p);
9595         memcpy (p, name, len);
9596         p += len;
9597         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9598         *retp = p;
9599         *retbuffer = buffer;
9600 }
9601
9602 /*
9603  * mono_reflection_get_custom_attrs_blob:
9604  * @ctor: custom attribute constructor
9605  * @ctorArgs: arguments o the constructor
9606  * @properties:
9607  * @propValues:
9608  * @fields:
9609  * @fieldValues:
9610  * 
9611  * Creates the blob of data that needs to be saved in the metadata and that represents
9612  * the custom attributed described by @ctor, @ctorArgs etc.
9613  * Returns: a Byte array representing the blob of data.
9614  */
9615 MonoArray*
9616 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9617 {
9618         MonoArray *result;
9619         MonoMethodSignature *sig;
9620         MonoObject *arg;
9621         char *buffer, *p;
9622         guint32 buflen, i;
9623
9624         MONO_ARCH_SAVE_REGS;
9625
9626         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9627                 /* sig is freed later so allocate it in the heap */
9628                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9629         } else {
9630                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9631         }
9632
9633         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9634         buflen = 256;
9635         p = buffer = g_malloc (buflen);
9636         /* write the prolog */
9637         *p++ = 1;
9638         *p++ = 0;
9639         for (i = 0; i < sig->param_count; ++i) {
9640                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9641                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9642         }
9643         i = 0;
9644         if (properties)
9645                 i += mono_array_length (properties);
9646         if (fields)
9647                 i += mono_array_length (fields);
9648         *p++ = i & 0xff;
9649         *p++ = (i >> 8) & 0xff;
9650         if (properties) {
9651                 MonoObject *prop;
9652                 for (i = 0; i < mono_array_length (properties); ++i) {
9653                         MonoType *ptype;
9654                         char *pname;
9655
9656                         prop = mono_array_get (properties, gpointer, i);
9657                         get_prop_name_and_type (prop, &pname, &ptype);
9658                         *p++ = 0x54; /* PROPERTY signature */
9659                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9660                         g_free (pname);
9661                 }
9662         }
9663
9664         if (fields) {
9665                 MonoObject *field;
9666                 for (i = 0; i < mono_array_length (fields); ++i) {
9667                         MonoType *ftype;
9668                         char *fname;
9669
9670                         field = mono_array_get (fields, gpointer, i);
9671                         get_field_name_and_type (field, &fname, &ftype);
9672                         *p++ = 0x53; /* FIELD signature */
9673                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9674                         g_free (fname);
9675                 }
9676         }
9677
9678         g_assert (p - buffer <= buflen);
9679         buflen = p - buffer;
9680         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9681         p = mono_array_addr (result, char, 0);
9682         memcpy (p, buffer, buflen);
9683         g_free (buffer);
9684         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9685                 g_free (sig);
9686         return result;
9687 }
9688
9689 /*
9690  * mono_reflection_setup_internal_class:
9691  * @tb: a TypeBuilder object
9692  *
9693  * Creates a MonoClass that represents the TypeBuilder.
9694  * This is a trick that lets us simplify a lot of reflection code
9695  * (and will allow us to support Build and Run assemblies easier).
9696  */
9697 void
9698 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9699 {
9700         MonoError error;
9701         MonoClass *klass, *parent;
9702
9703         MONO_ARCH_SAVE_REGS;
9704
9705         RESOLVE_TYPE (tb->parent);
9706
9707         mono_loader_lock ();
9708
9709         if (tb->parent) {
9710                 /* check so we can compile corlib correctly */
9711                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9712                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9713                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9714                 } else {
9715                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9716                 }
9717         } else {
9718                 parent = NULL;
9719         }
9720         
9721         /* the type has already being created: it means we just have to change the parent */
9722         if (tb->type.type) {
9723                 klass = mono_class_from_mono_type (tb->type.type);
9724                 klass->parent = NULL;
9725                 /* fool mono_class_setup_parent */
9726                 klass->supertypes = NULL;
9727                 mono_class_setup_parent (klass, parent);
9728                 mono_class_setup_mono_type (klass);
9729                 mono_loader_unlock ();
9730                 return;
9731         }
9732
9733         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9734
9735         klass->image = &tb->module->dynamic_image->image;
9736
9737         klass->inited = 1; /* we lie to the runtime */
9738         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9739         if (!mono_error_ok (&error))
9740                 goto failure;
9741         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9742         if (!mono_error_ok (&error))
9743                 goto failure;
9744         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9745         klass->flags = tb->attrs;
9746         
9747         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9748
9749         klass->element_class = klass;
9750
9751         if (mono_class_get_ref_info (klass) == NULL) {
9752
9753                 mono_class_set_ref_info (klass, tb);
9754
9755                 /* Put into cache so mono_class_get () will find it.
9756                 Skip nested types as those should not be available on the global scope. */
9757                 if (!tb->nesting_type) {
9758                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9759                 } else {
9760                         klass->image->reflection_info_unregister_classes =
9761                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9762                 }
9763         } else {
9764                 g_assert (mono_class_get_ref_info (klass) == tb);
9765         }
9766
9767         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9768                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9769
9770         if (parent != NULL) {
9771                 mono_class_setup_parent (klass, parent);
9772         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9773                 const char *old_n = klass->name;
9774                 /* trick to get relative numbering right when compiling corlib */
9775                 klass->name = "BuildingObject";
9776                 mono_class_setup_parent (klass, mono_defaults.object_class);
9777                 klass->name = old_n;
9778         }
9779
9780         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9781                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9782                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9783                 klass->instance_size = sizeof (MonoObject);
9784                 klass->size_inited = 1;
9785                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9786         }
9787
9788         mono_class_setup_mono_type (klass);
9789
9790         mono_class_setup_supertypes (klass);
9791
9792         /*
9793          * FIXME: handle interfaces.
9794          */
9795
9796         tb->type.type = &klass->byval_arg;
9797
9798         if (tb->nesting_type) {
9799                 g_assert (tb->nesting_type->type);
9800                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9801         }
9802
9803         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9804
9805         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9806         
9807         mono_loader_unlock ();
9808         return;
9809
9810 failure:
9811         mono_loader_unlock ();
9812         mono_error_raise_exception (&error);
9813 }
9814
9815 /*
9816  * mono_reflection_setup_generic_class:
9817  * @tb: a TypeBuilder object
9818  *
9819  * Setup the generic class before adding the first generic parameter.
9820  */
9821 void
9822 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9823 {
9824 }
9825
9826 /*
9827  * mono_reflection_create_generic_class:
9828  * @tb: a TypeBuilder object
9829  *
9830  * Creates the generic class after all generic parameters have been added.
9831  */
9832 void
9833 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9834 {
9835         MonoClass *klass;
9836         int count, i;
9837
9838         MONO_ARCH_SAVE_REGS;
9839
9840         klass = mono_class_from_mono_type (tb->type.type);
9841
9842         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9843
9844         if (klass->generic_container || (count == 0))
9845                 return;
9846
9847         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9848
9849         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9850
9851         klass->generic_container->owner.klass = klass;
9852         klass->generic_container->type_argc = count;
9853         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9854
9855         klass->is_generic = 1;
9856
9857         for (i = 0; i < count; i++) {
9858                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9859                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9860                 klass->generic_container->type_params [i] = *param;
9861                 /*Make sure we are a diferent type instance */
9862                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9863                 klass->generic_container->type_params [i].info.pklass = NULL;
9864                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9865
9866                 g_assert (klass->generic_container->type_params [i].param.owner);
9867         }
9868
9869         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9870 }
9871
9872 /*
9873  * mono_reflection_create_internal_class:
9874  * @tb: a TypeBuilder object
9875  *
9876  * Actually create the MonoClass that is associated with the TypeBuilder.
9877  */
9878 void
9879 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9880 {
9881         MonoClass *klass;
9882
9883         MONO_ARCH_SAVE_REGS;
9884
9885         klass = mono_class_from_mono_type (tb->type.type);
9886
9887         mono_loader_lock ();
9888         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9889                 MonoReflectionFieldBuilder *fb;
9890                 MonoClass *ec;
9891                 MonoType *enum_basetype;
9892
9893                 g_assert (tb->fields != NULL);
9894                 g_assert (mono_array_length (tb->fields) >= 1);
9895
9896                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9897
9898                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9899                         mono_loader_unlock ();
9900                         return;
9901                 }
9902
9903                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9904                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9905                 if (!klass->element_class)
9906                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9907
9908                 /*
9909                  * get the element_class from the current corlib.
9910                  */
9911                 ec = default_class_from_mono_type (enum_basetype);
9912                 klass->instance_size = ec->instance_size;
9913                 klass->size_inited = 1;
9914                 /* 
9915                  * this is almost safe to do with enums and it's needed to be able
9916                  * to create objects of the enum type (for use in SetConstant).
9917                  */
9918                 /* FIXME: Does this mean enums can't have method overrides ? */
9919                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9920         }
9921         mono_loader_unlock ();
9922 }
9923
9924 static MonoMarshalSpec*
9925 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9926                                                                 MonoReflectionMarshal *minfo)
9927 {
9928         MonoMarshalSpec *res;
9929
9930         res = image_g_new0 (image, MonoMarshalSpec, 1);
9931         res->native = minfo->type;
9932
9933         switch (minfo->type) {
9934         case MONO_NATIVE_LPARRAY:
9935                 res->data.array_data.elem_type = minfo->eltype;
9936                 if (minfo->has_size) {
9937                         res->data.array_data.param_num = minfo->param_num;
9938                         res->data.array_data.num_elem = minfo->count;
9939                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9940                 }
9941                 else {
9942                         res->data.array_data.param_num = -1;
9943                         res->data.array_data.num_elem = -1;
9944                         res->data.array_data.elem_mult = -1;
9945                 }
9946                 break;
9947
9948         case MONO_NATIVE_BYVALTSTR:
9949         case MONO_NATIVE_BYVALARRAY:
9950                 res->data.array_data.num_elem = minfo->count;
9951                 break;
9952
9953         case MONO_NATIVE_CUSTOM:
9954                 if (minfo->marshaltyperef)
9955                         res->data.custom_data.custom_name =
9956                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9957                 if (minfo->mcookie)
9958                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9959                 break;
9960
9961         default:
9962                 break;
9963         }
9964
9965         return res;
9966 }
9967 #endif /* !DISABLE_REFLECTION_EMIT */
9968
9969 MonoReflectionMarshal*
9970 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9971                                                                                    MonoMarshalSpec *spec)
9972 {
9973         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9974         MonoReflectionMarshal *minfo;
9975         MonoType *mtype;
9976
9977         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9978                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9979                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9980                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9981         }
9982
9983         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9984         minfo->type = spec->native;
9985
9986         switch (minfo->type) {
9987         case MONO_NATIVE_LPARRAY:
9988                 minfo->eltype = spec->data.array_data.elem_type;
9989                 minfo->count = spec->data.array_data.num_elem;
9990                 minfo->param_num = spec->data.array_data.param_num;
9991                 break;
9992
9993         case MONO_NATIVE_BYVALTSTR:
9994         case MONO_NATIVE_BYVALARRAY:
9995                 minfo->count = spec->data.array_data.num_elem;
9996                 break;
9997
9998         case MONO_NATIVE_CUSTOM:
9999                 if (spec->data.custom_data.custom_name) {
10000                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10001                         if (mtype)
10002                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10003
10004                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10005                 }
10006                 if (spec->data.custom_data.cookie)
10007                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10008                 break;
10009
10010         default:
10011                 break;
10012         }
10013
10014         return minfo;
10015 }
10016
10017 #ifndef DISABLE_REFLECTION_EMIT
10018 static MonoMethod*
10019 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10020                                          ReflectionMethodBuilder *rmb,
10021                                          MonoMethodSignature *sig)
10022 {
10023         MonoError error;
10024         MonoMethod *m;
10025         MonoMethodWrapper *wrapperm;
10026         MonoMarshalSpec **specs;
10027         MonoReflectionMethodAux *method_aux;
10028         MonoImage *image;
10029         gboolean dynamic;
10030         int i;
10031
10032         mono_error_init (&error);
10033         /*
10034          * Methods created using a MethodBuilder should have their memory allocated
10035          * inside the image mempool, while dynamic methods should have their memory
10036          * malloc'd.
10037          */
10038         dynamic = rmb->refs != NULL;
10039         image = dynamic ? NULL : klass->image;
10040
10041         if (!dynamic)
10042                 g_assert (!klass->generic_class);
10043
10044         mono_loader_lock ();
10045
10046         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10047                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10048                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10049         else
10050                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10051
10052         wrapperm = (MonoMethodWrapper*)m;
10053
10054         m->dynamic = dynamic;
10055         m->slot = -1;
10056         m->flags = rmb->attrs;
10057         m->iflags = rmb->iattrs;
10058         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10059         g_assert (mono_error_ok (&error));
10060         m->klass = klass;
10061         m->signature = sig;
10062         m->sre_method = TRUE;
10063         m->skip_visibility = rmb->skip_visibility;
10064         if (rmb->table_idx)
10065                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10066
10067         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10068                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10069                         m->string_ctor = 1;
10070
10071                 m->signature->pinvoke = 1;
10072         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10073                 m->signature->pinvoke = 1;
10074
10075                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10076
10077                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10078                 g_assert (mono_error_ok (&error));
10079                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10080                 g_assert (mono_error_ok (&error));
10081                 
10082                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10083
10084                 if (klass->image->dynamic)
10085                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10086
10087                 mono_loader_unlock ();
10088
10089                 return m;
10090         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10091                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10092                 MonoMethodHeader *header;
10093                 guint32 code_size;
10094                 gint32 max_stack, i;
10095                 gint32 num_locals = 0;
10096                 gint32 num_clauses = 0;
10097                 guint8 *code;
10098
10099                 if (rmb->ilgen) {
10100                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10101                         code_size = rmb->ilgen->code_len;
10102                         max_stack = rmb->ilgen->max_stack;
10103                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10104                         if (rmb->ilgen->ex_handlers)
10105                                 num_clauses = method_count_clauses (rmb->ilgen);
10106                 } else {
10107                         if (rmb->code) {
10108                                 code = mono_array_addr (rmb->code, guint8, 0);
10109                                 code_size = mono_array_length (rmb->code);
10110                                 /* we probably need to run a verifier on the code... */
10111                                 max_stack = 8; 
10112                         }
10113                         else {
10114                                 code = NULL;
10115                                 code_size = 0;
10116                                 max_stack = 8;
10117                         }
10118                 }
10119
10120                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10121                 header->code_size = code_size;
10122                 header->code = image_g_malloc (image, code_size);
10123                 memcpy ((char*)header->code, code, code_size);
10124                 header->max_stack = max_stack;
10125                 header->init_locals = rmb->init_locals;
10126                 header->num_locals = num_locals;
10127
10128                 for (i = 0; i < num_locals; ++i) {
10129                         MonoReflectionLocalBuilder *lb = 
10130                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10131
10132                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10133                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10134                 }
10135
10136                 header->num_clauses = num_clauses;
10137                 if (num_clauses) {
10138                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10139                                  rmb->ilgen, num_clauses);
10140                 }
10141
10142                 wrapperm->header = header;
10143         }
10144
10145         if (rmb->generic_params) {
10146                 int count = mono_array_length (rmb->generic_params);
10147                 MonoGenericContainer *container = rmb->generic_container;
10148
10149                 g_assert (container);
10150
10151                 container->type_argc = count;
10152                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10153                 container->owner.method = m;
10154
10155                 m->is_generic = TRUE;
10156                 mono_method_set_generic_container (m, container);
10157
10158                 for (i = 0; i < count; i++) {
10159                         MonoReflectionGenericParam *gp =
10160                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10161                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10162                         container->type_params [i] = *param;
10163                 }
10164
10165                 /*
10166                  * The method signature might have pointers to generic parameters that belong to other methods.
10167                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10168                  * generic parameters.
10169                  */
10170                 for (i = 0; i < m->signature->param_count; ++i) {
10171                         MonoType *t = m->signature->params [i];
10172                         if (t->type == MONO_TYPE_MVAR) {
10173                                 MonoGenericParam *gparam =  t->data.generic_param;
10174                                 if (gparam->num < count) {
10175                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10176                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10177                                 }
10178
10179                         }
10180                 }
10181
10182                 if (klass->generic_container) {
10183                         container->parent = klass->generic_container;
10184                         container->context.class_inst = klass->generic_container->context.class_inst;
10185                 }
10186                 container->context.method_inst = mono_get_shared_generic_inst (container);
10187         }
10188
10189         if (rmb->refs) {
10190                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10191                 int i;
10192                 void **data;
10193
10194                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10195
10196                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10197                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10198                 for (i = 0; i < rmb->nrefs; ++i)
10199                         data [i + 1] = rmb->refs [i];
10200         }
10201
10202         method_aux = NULL;
10203
10204         /* Parameter info */
10205         if (rmb->pinfo) {
10206                 if (!method_aux)
10207                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10208                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10209                 for (i = 0; i <= m->signature->param_count; ++i) {
10210                         MonoReflectionParamBuilder *pb;
10211                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10212                                 if ((i > 0) && (pb->attrs)) {
10213                                         /* Make a copy since it might point to a shared type structure */
10214                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10215                                         m->signature->params [i - 1]->attrs = pb->attrs;
10216                                 }
10217
10218                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10219                                         MonoDynamicImage *assembly;
10220                                         guint32 idx, def_type, len;
10221                                         char *p;
10222                                         const char *p2;
10223
10224                                         if (!method_aux->param_defaults) {
10225                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10226                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10227                                         }
10228                                         assembly = (MonoDynamicImage*)klass->image;
10229                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10230                                         /* Copy the data from the blob since it might get realloc-ed */
10231                                         p = assembly->blob.data + idx;
10232                                         len = mono_metadata_decode_blob_size (p, &p2);
10233                                         len += p2 - p;
10234                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10235                                         method_aux->param_default_types [i] = def_type;
10236                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10237                                 }
10238
10239                                 if (pb->name) {
10240                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10241                                         g_assert (mono_error_ok (&error));
10242                                 }
10243                                 if (pb->cattrs) {
10244                                         if (!method_aux->param_cattr)
10245                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10246                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10247                                 }
10248                         }
10249                 }
10250         }
10251
10252         /* Parameter marshalling */
10253         specs = NULL;
10254         if (rmb->pinfo)         
10255                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10256                         MonoReflectionParamBuilder *pb;
10257                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10258                                 if (pb->marshal_info) {
10259                                         if (specs == NULL)
10260                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10261                                         specs [pb->position] = 
10262                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10263                                 }
10264                         }
10265                 }
10266         if (specs != NULL) {
10267                 if (!method_aux)
10268                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10269                 method_aux->param_marshall = specs;
10270         }
10271
10272         if (klass->image->dynamic && method_aux)
10273                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10274
10275         mono_loader_unlock ();
10276
10277         return m;
10278 }       
10279
10280 static MonoMethod*
10281 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10282 {
10283         ReflectionMethodBuilder rmb;
10284         MonoMethodSignature *sig;
10285
10286         mono_loader_lock ();
10287         sig = ctor_builder_to_signature (klass->image, mb);
10288         mono_loader_unlock ();
10289
10290         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10291
10292         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10293         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10294
10295         /* If we are in a generic class, we might be called multiple times from inflate_method */
10296         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10297                 /* ilgen is no longer needed */
10298                 mb->ilgen = NULL;
10299         }
10300
10301         return mb->mhandle;
10302 }
10303
10304 static MonoMethod*
10305 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10306 {
10307         ReflectionMethodBuilder rmb;
10308         MonoMethodSignature *sig;
10309
10310         mono_loader_lock ();
10311         sig = method_builder_to_signature (klass->image, mb);
10312         mono_loader_unlock ();
10313
10314         reflection_methodbuilder_from_method_builder (&rmb, mb);
10315
10316         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10317         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10318
10319         /* If we are in a generic class, we might be called multiple times from inflate_method */
10320         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10321                 /* ilgen is no longer needed */
10322                 mb->ilgen = NULL;
10323         }
10324         return mb->mhandle;
10325 }
10326
10327 static MonoClassField*
10328 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10329 {
10330         MonoClassField *field;
10331         MonoType *custom;
10332         MonoError error;
10333
10334         field = g_new0 (MonoClassField, 1);
10335
10336         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10337         g_assert (mono_error_ok (&error));
10338         if (fb->attrs || fb->modreq || fb->modopt) {
10339                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10340                 field->type->attrs = fb->attrs;
10341
10342                 g_assert (klass->image->dynamic);
10343                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10344                 g_free (field->type);
10345                 field->type = mono_metadata_type_dup (klass->image, custom);
10346                 g_free (custom);
10347         } else {
10348                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10349         }
10350         if (fb->offset != -1)
10351                 field->offset = fb->offset;
10352         field->parent = klass;
10353         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10354
10355         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10356
10357         return field;
10358 }
10359 #endif
10360
10361 MonoType*
10362 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10363 {
10364         MonoClass *klass;
10365         MonoReflectionTypeBuilder *tb = NULL;
10366         gboolean is_dynamic = FALSE;
10367         MonoDomain *domain;
10368         MonoClass *geninst;
10369
10370         mono_loader_lock ();
10371
10372         domain = mono_object_domain (type);
10373
10374         if (is_sre_type_builder (mono_object_class (type))) {
10375                 tb = (MonoReflectionTypeBuilder *) type;
10376
10377                 is_dynamic = TRUE;
10378         } else if (is_sre_generic_instance (mono_object_class (type))) {
10379                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10380                 MonoReflectionType *gtd = rgi->generic_type;
10381
10382                 if (is_sre_type_builder (mono_object_class (gtd))) {
10383                         tb = (MonoReflectionTypeBuilder *)gtd;
10384                         is_dynamic = TRUE;
10385                 }
10386         }
10387
10388         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10389         if (tb && tb->generic_container)
10390                 mono_reflection_create_generic_class (tb);
10391
10392         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10393         if (!klass->generic_container) {
10394                 mono_loader_unlock ();
10395                 return NULL;
10396         }
10397
10398         if (klass->wastypebuilder) {
10399                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10400
10401                 is_dynamic = TRUE;
10402         }
10403
10404         mono_loader_unlock ();
10405
10406         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10407
10408         return &geninst->byval_arg;
10409 }
10410
10411 MonoClass*
10412 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10413 {
10414         MonoGenericClass *gclass;
10415         MonoGenericInst *inst;
10416
10417         g_assert (klass->generic_container);
10418
10419         inst = mono_metadata_get_generic_inst (type_argc, types);
10420         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10421
10422         return mono_generic_class_get_class (gclass);
10423 }
10424
10425 MonoReflectionMethod*
10426 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10427 {
10428         MonoClass *klass;
10429         MonoMethod *method, *inflated;
10430         MonoMethodInflated *imethod;
10431         MonoGenericContext tmp_context;
10432         MonoGenericInst *ginst;
10433         MonoType **type_argv;
10434         int count, i;
10435
10436         MONO_ARCH_SAVE_REGS;
10437
10438         /*FIXME but this no longer should happen*/
10439         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10440 #ifndef DISABLE_REFLECTION_EMIT
10441                 MonoReflectionMethodBuilder *mb = NULL;
10442                 MonoReflectionTypeBuilder *tb;
10443                 MonoClass *klass;
10444
10445                 mb = (MonoReflectionMethodBuilder *) rmethod;
10446                 tb = (MonoReflectionTypeBuilder *) mb->type;
10447                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10448
10449                 method = methodbuilder_to_mono_method (klass, mb);
10450 #else
10451                 g_assert_not_reached ();
10452                 method = NULL;
10453 #endif
10454         } else {
10455                 method = rmethod->method;
10456         }
10457
10458         klass = method->klass;
10459
10460         if (method->is_inflated)
10461                 method = ((MonoMethodInflated *) method)->declaring;
10462
10463         count = mono_method_signature (method)->generic_param_count;
10464         if (count != mono_array_length (types))
10465                 return NULL;
10466
10467         type_argv = g_new0 (MonoType *, count);
10468         for (i = 0; i < count; i++) {
10469                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10470                 type_argv [i] = mono_reflection_type_get_handle (garg);
10471         }
10472         ginst = mono_metadata_get_generic_inst (count, type_argv);
10473         g_free (type_argv);
10474
10475         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10476         tmp_context.method_inst = ginst;
10477
10478         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10479         imethod = (MonoMethodInflated *) inflated;
10480
10481         /*FIXME but I think this is no longer necessary*/
10482         if (method->klass->image->dynamic) {
10483                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10484                 /*
10485                  * This table maps metadata structures representing inflated methods/fields
10486                  * to the reflection objects representing their generic definitions.
10487                  */
10488                 mono_loader_lock ();
10489                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10490                 mono_loader_unlock ();
10491         }
10492
10493         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10494                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10495         
10496         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10497 }
10498
10499 #ifndef DISABLE_REFLECTION_EMIT
10500
10501 static MonoMethod *
10502 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10503 {
10504         MonoMethodInflated *imethod;
10505         MonoGenericContext *context;
10506         int i;
10507
10508         /*
10509          * With generic code sharing the klass might not be inflated.
10510          * This can happen because classes inflated with their own
10511          * type arguments are "normalized" to the uninflated class.
10512          */
10513         if (!klass->generic_class)
10514                 return method;
10515
10516         context = mono_class_get_context (klass);
10517
10518         if (klass->method.count && klass->methods) {
10519                 /* Find the already created inflated method */
10520                 for (i = 0; i < klass->method.count; ++i) {
10521                         g_assert (klass->methods [i]->is_inflated);
10522                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10523                                 break;
10524                 }
10525                 g_assert (i < klass->method.count);
10526                 imethod = (MonoMethodInflated*)klass->methods [i];
10527         } else {
10528                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10529         }
10530
10531         if (method->is_generic && method->klass->image->dynamic) {
10532                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10533
10534                 mono_loader_lock ();
10535                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10536                 mono_loader_unlock ();
10537         }
10538         return (MonoMethod *) imethod;
10539 }
10540
10541 static MonoMethod *
10542 inflate_method (MonoReflectionType *type, MonoObject *obj)
10543 {
10544         MonoMethod *method;
10545         MonoClass *gklass;
10546
10547         MonoClass *type_class = mono_object_class (type);
10548
10549         if (is_sre_generic_instance (type_class)) {
10550                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10551                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10552         } else if (is_sre_type_builder (type_class)) {
10553                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10554         } else if (type->type) {
10555                 gklass = mono_class_from_mono_type (type->type);
10556                 gklass = mono_class_get_generic_type_definition (gklass);
10557         } else {
10558                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10559         }
10560
10561         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10562                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10563                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10564                 else
10565                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10566         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10567                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10568         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10569                 method = ((MonoReflectionMethod *) obj)->method;
10570         else {
10571                 method = NULL; /* prevent compiler warning */
10572                 g_error ("can't handle type %s", obj->vtable->klass->name);
10573         }
10574
10575         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10576 }
10577
10578 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10579 void
10580 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10581                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10582                                           MonoArray *events)
10583 {
10584         MonoGenericClass *gclass;
10585         MonoDynamicGenericClass *dgclass;
10586         MonoClass *klass, *gklass;
10587         MonoType *gtype;
10588         int i;
10589
10590         MONO_ARCH_SAVE_REGS;
10591
10592         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10593         klass = mono_class_from_mono_type (gtype);
10594         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10595         gclass = gtype->data.generic_class;
10596
10597         if (!gclass->is_dynamic)
10598                 return;
10599
10600         dgclass = (MonoDynamicGenericClass *) gclass;
10601
10602         if (dgclass->initialized)
10603                 return;
10604
10605         gklass = gclass->container_class;
10606         mono_class_init (gklass);
10607
10608         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10609         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10610         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10611
10612         dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
10613         dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
10614         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10615         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10616         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10617
10618         for (i = 0; i < dgclass->count_methods; i++) {
10619                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10620
10621                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10622         }
10623
10624         for (i = 0; i < dgclass->count_ctors; i++) {
10625                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10626
10627                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10628         }
10629
10630         for (i = 0; i < dgclass->count_fields; i++) {
10631                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10632                 MonoClassField *field, *inflated_field = NULL;
10633
10634                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10635                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10636                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10637                         field = ((MonoReflectionField *) obj)->field;
10638                 else {
10639                         field = NULL; /* prevent compiler warning */
10640                         g_assert_not_reached ();
10641                 }
10642
10643                 dgclass->fields [i] = *field;
10644                 dgclass->fields [i].parent = klass;
10645                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10646                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10647                 dgclass->field_generic_types [i] = field->type;
10648                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10649                 dgclass->field_objects [i] = obj;
10650
10651                 if (inflated_field) {
10652                         g_free (inflated_field);
10653                 } else {
10654                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10655                 }
10656         }
10657
10658         dgclass->initialized = TRUE;
10659 }
10660
10661 void
10662 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10663 {
10664         MonoDynamicGenericClass *dgclass;
10665         int i;
10666
10667         g_assert (gclass->is_dynamic);
10668
10669         dgclass = (MonoDynamicGenericClass *)gclass;
10670
10671         for (i = 0; i < dgclass->count_fields; ++i) {
10672                 MonoClassField *field = dgclass->fields + i;
10673                 mono_metadata_free_type (field->type);
10674                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10675         }
10676 }
10677
10678 static void
10679 fix_partial_generic_class (MonoClass *klass)
10680 {
10681         MonoClass *gklass = klass->generic_class->container_class;
10682         MonoDynamicGenericClass *dgclass;
10683         int i;
10684
10685         if (klass->wastypebuilder)
10686                 return;
10687
10688         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10689         if (klass->parent != gklass->parent) {
10690                 MonoError error;
10691                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10692                 if (mono_error_ok (&error)) {
10693                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10694                         mono_metadata_free_type (parent_type);
10695                         if (parent != klass->parent) {
10696                                 /*fool mono_class_setup_parent*/
10697                                 klass->supertypes = NULL;
10698                                 mono_class_setup_parent (klass, parent);
10699                         }
10700                 } else {
10701                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10702                         mono_error_cleanup (&error);
10703                         if (gklass->wastypebuilder)
10704                                 klass->wastypebuilder = TRUE;
10705                         return;
10706                 }
10707         }
10708
10709         if (!dgclass->initialized)
10710                 return;
10711
10712         if (klass->method.count != gklass->method.count) {
10713                 klass->method.count = gklass->method.count;
10714                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10715
10716                 for (i = 0; i < klass->method.count; i++) {
10717                         klass->methods [i] = mono_class_inflate_generic_method_full (
10718                                 gklass->methods [i], klass, mono_class_get_context (klass));
10719                 }
10720         }
10721
10722         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10723                 klass->interface_count = gklass->interface_count;
10724                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10725                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10726
10727                 for (i = 0; i < gklass->interface_count; ++i) {
10728                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10729                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10730                         mono_metadata_free_type (iface_type);
10731
10732                         ensure_runtime_vtable (klass->interfaces [i]);
10733                 }
10734                 klass->interfaces_inited = 1;
10735         }
10736
10737         if (klass->field.count != gklass->field.count) {
10738                 klass->field.count = gklass->field.count;
10739                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10740
10741                 for (i = 0; i < klass->field.count; i++) {
10742                         klass->fields [i] = gklass->fields [i];
10743                         klass->fields [i].parent = klass;
10744                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10745                 }
10746         }
10747
10748         /*We can only finish with this klass once it's parent has as well*/
10749         if (gklass->wastypebuilder)
10750                 klass->wastypebuilder = TRUE;
10751         return;
10752 }
10753
10754 static void
10755 ensure_generic_class_runtime_vtable (MonoClass *klass)
10756 {
10757         MonoClass *gklass = klass->generic_class->container_class;
10758
10759         ensure_runtime_vtable (gklass); 
10760
10761         fix_partial_generic_class (klass);
10762 }
10763
10764 static void
10765 ensure_runtime_vtable (MonoClass *klass)
10766 {
10767         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10768         int i, num, j;
10769
10770         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10771                 return;
10772         if (klass->parent)
10773                 ensure_runtime_vtable (klass->parent);
10774
10775         if (tb) {
10776                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10777                 num += tb->num_methods;
10778                 klass->method.count = num;
10779                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10780                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10781                 for (i = 0; i < num; ++i)
10782                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10783                 num = tb->num_methods;
10784                 j = i;
10785                 for (i = 0; i < num; ++i)
10786                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10787         
10788                 if (tb->interfaces) {
10789                         klass->interface_count = mono_array_length (tb->interfaces);
10790                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10791                         for (i = 0; i < klass->interface_count; ++i) {
10792                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10793                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10794                                 ensure_runtime_vtable (klass->interfaces [i]);
10795                         }
10796                         klass->interfaces_inited = 1;
10797                 }
10798         } else if (klass->generic_class){
10799                 ensure_generic_class_runtime_vtable (klass);
10800         }
10801
10802         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10803                 int slot_num = 0;
10804                 for (i = 0; i < klass->method.count; ++i) {
10805                         MonoMethod *im = klass->methods [i];
10806                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10807                                 im->slot = slot_num++;
10808                 }
10809                 
10810                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10811                 mono_class_setup_interface_offsets (klass);
10812                 mono_class_setup_interface_id (klass);
10813         }
10814
10815         /*
10816          * The generic vtable is needed even if image->run is not set since some
10817          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10818          * method->slot being defined.
10819          */
10820
10821         /* 
10822          * tb->methods could not be freed since it is used for determining 
10823          * overrides during dynamic vtable construction.
10824          */
10825 }
10826
10827 static MonoMethod*
10828 mono_reflection_method_get_handle (MonoObject *method)
10829 {
10830         MonoClass *class = mono_object_class (method);
10831         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10832                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10833                 return sr_method->method;
10834         }
10835         if (is_sre_method_builder (class)) {
10836                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10837                 return mb->mhandle;
10838         }
10839         if (is_sre_method_on_tb_inst (class)) {
10840                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10841                 MonoMethod *result;
10842                 /*FIXME move this to a proper method and unify with resolve_object*/
10843                 if (m->method_args) {
10844                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10845                 } else {
10846                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10847                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10848                         MonoMethod *mono_method;
10849
10850                         if (is_sre_method_builder (mono_object_class (m->mb)))
10851                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10852                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10853                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10854                         else
10855                                 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)));
10856
10857                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10858                 }
10859                 return result;
10860         }
10861
10862         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10863         return NULL;
10864 }
10865
10866 void
10867 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10868 {
10869         MonoReflectionTypeBuilder *tb;
10870         int i, onum;
10871
10872         *overrides = NULL;
10873         *num_overrides = 0;
10874
10875         g_assert (klass->image->dynamic);
10876
10877         if (!mono_class_get_ref_info (klass))
10878                 return;
10879
10880         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10881
10882         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10883
10884         onum = 0;
10885         if (tb->methods) {
10886                 for (i = 0; i < tb->num_methods; ++i) {
10887                         MonoReflectionMethodBuilder *mb = 
10888                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10889                         if (mb->override_method)
10890                                 onum ++;
10891                 }
10892         }
10893
10894         if (onum) {
10895                 *overrides = g_new0 (MonoMethod*, onum * 2);
10896
10897                 onum = 0;
10898                 for (i = 0; i < tb->num_methods; ++i) {
10899                         MonoReflectionMethodBuilder *mb = 
10900                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10901                         if (mb->override_method) {
10902                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10903                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10904
10905                                 g_assert (mb->mhandle);
10906
10907                                 onum ++;
10908                         }
10909                 }
10910         }
10911
10912         *num_overrides = onum;
10913 }
10914
10915 static void
10916 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10917 {
10918         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10919         MonoReflectionFieldBuilder *fb;
10920         MonoClassField *field;
10921         MonoImage *image = klass->image;
10922         const char *p, *p2;
10923         int i;
10924         guint32 len, idx, real_size = 0;
10925
10926         klass->field.count = tb->num_fields;
10927         klass->field.first = 0;
10928
10929         mono_error_init (error);
10930
10931         if (tb->class_size) {
10932                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10933                 klass->packing_size = tb->packing_size;
10934                 real_size = klass->instance_size + tb->class_size;
10935         }
10936
10937         if (!klass->field.count) {
10938                 klass->instance_size = MAX (klass->instance_size, real_size);
10939                 return;
10940         }
10941         
10942         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10943         mono_class_alloc_ext (klass);
10944         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10945         /*
10946         This is, guess what, a hack.
10947         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10948         On the static path no field class is resolved, only types are built. This is the right thing to do
10949         but we suck.
10950         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10951         */
10952         klass->size_inited = 1;
10953
10954         for (i = 0; i < klass->field.count; ++i) {
10955                 fb = mono_array_get (tb->fields, gpointer, i);
10956                 field = &klass->fields [i];
10957                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10958                 if (!mono_error_ok (error))
10959                         return;
10960                 if (fb->attrs) {
10961                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10962                         field->type->attrs = fb->attrs;
10963                 } else {
10964                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10965                 }
10966                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10967                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10968                 if (fb->offset != -1)
10969                         field->offset = fb->offset;
10970                 field->parent = klass;
10971                 fb->handle = field;
10972                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10973
10974                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10975                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10976                 }
10977                 if (fb->def_value) {
10978                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10979                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10980                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10981                         /* Copy the data from the blob since it might get realloc-ed */
10982                         p = assembly->blob.data + idx;
10983                         len = mono_metadata_decode_blob_size (p, &p2);
10984                         len += p2 - p;
10985                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10986                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10987                 }
10988         }
10989
10990         klass->instance_size = MAX (klass->instance_size, real_size);
10991         mono_class_layout_fields (klass);
10992 }
10993
10994 static void
10995 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10996 {
10997         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10998         MonoReflectionPropertyBuilder *pb;
10999         MonoImage *image = klass->image;
11000         MonoProperty *properties;
11001         int i;
11002
11003         mono_error_init (error);
11004
11005         if (!klass->ext)
11006                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11007
11008         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11009         klass->ext->property.first = 0;
11010
11011         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11012         klass->ext->properties = properties;
11013         for (i = 0; i < klass->ext->property.count; ++i) {
11014                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11015                 properties [i].parent = klass;
11016                 properties [i].attrs = pb->attrs;
11017                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11018                 if (!mono_error_ok (error))
11019                         return;
11020                 if (pb->get_method)
11021                         properties [i].get = pb->get_method->mhandle;
11022                 if (pb->set_method)
11023                         properties [i].set = pb->set_method->mhandle;
11024
11025                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11026                 if (pb->def_value) {
11027                         guint32 len, idx;
11028                         const char *p, *p2;
11029                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11030                         if (!klass->ext->prop_def_values)
11031                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11032                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11033                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11034                         /* Copy the data from the blob since it might get realloc-ed */
11035                         p = assembly->blob.data + idx;
11036                         len = mono_metadata_decode_blob_size (p, &p2);
11037                         len += p2 - p;
11038                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11039                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11040                 }
11041         }
11042 }
11043
11044 MonoReflectionEvent *
11045 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11046 {
11047         MonoEvent *event = g_new0 (MonoEvent, 1);
11048         MonoClass *klass;
11049
11050         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11051
11052         event->parent = klass;
11053         event->attrs = eb->attrs;
11054         event->name = mono_string_to_utf8 (eb->name);
11055         if (eb->add_method)
11056                 event->add = eb->add_method->mhandle;
11057         if (eb->remove_method)
11058                 event->remove = eb->remove_method->mhandle;
11059         if (eb->raise_method)
11060                 event->raise = eb->raise_method->mhandle;
11061
11062 #ifndef MONO_SMALL_CONFIG
11063         if (eb->other_methods) {
11064                 int j;
11065                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11066                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11067                         MonoReflectionMethodBuilder *mb = 
11068                                 mono_array_get (eb->other_methods,
11069                                                 MonoReflectionMethodBuilder*, j);
11070                         event->other [j] = mb->mhandle;
11071                 }
11072         }
11073 #endif
11074
11075         return mono_event_get_object (mono_object_domain (tb), klass, event);
11076 }
11077
11078 static void
11079 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11080 {
11081         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11082         MonoReflectionEventBuilder *eb;
11083         MonoImage *image = klass->image;
11084         MonoEvent *events;
11085         int i;
11086
11087         mono_error_init (error);
11088
11089         if (!klass->ext)
11090                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11091
11092         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11093         klass->ext->event.first = 0;
11094
11095         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11096         klass->ext->events = events;
11097         for (i = 0; i < klass->ext->event.count; ++i) {
11098                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11099                 events [i].parent = klass;
11100                 events [i].attrs = eb->attrs;
11101                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11102                 if (!mono_error_ok (error))
11103                         return;
11104                 if (eb->add_method)
11105                         events [i].add = eb->add_method->mhandle;
11106                 if (eb->remove_method)
11107                         events [i].remove = eb->remove_method->mhandle;
11108                 if (eb->raise_method)
11109                         events [i].raise = eb->raise_method->mhandle;
11110
11111 #ifndef MONO_SMALL_CONFIG
11112                 if (eb->other_methods) {
11113                         int j;
11114                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11115                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11116                                 MonoReflectionMethodBuilder *mb = 
11117                                         mono_array_get (eb->other_methods,
11118                                                                         MonoReflectionMethodBuilder*, j);
11119                                 events [i].other [j] = mb->mhandle;
11120                         }
11121                 }
11122 #endif
11123                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11124         }
11125 }
11126
11127 static gboolean
11128 remove_instantiations_of_and_ensure_contents (gpointer key,
11129                                                   gpointer value,
11130                                                   gpointer user_data)
11131 {
11132         MonoType *type = (MonoType*)key;
11133         MonoClass *klass = (MonoClass*)user_data;
11134
11135         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11136                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11137                 return TRUE;
11138         } else
11139                 return FALSE;
11140 }
11141
11142 static void
11143 check_array_for_usertypes (MonoArray *arr)
11144 {
11145         int i;
11146
11147         if (!arr)
11148                 return;
11149
11150         for (i = 0; i < mono_array_length (arr); ++i)
11151                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11152 }
11153
11154 MonoReflectionType*
11155 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11156 {
11157         MonoError error;
11158         MonoClass *klass;
11159         MonoDomain* domain;
11160         MonoReflectionType* res;
11161         int i, j;
11162
11163         MONO_ARCH_SAVE_REGS;
11164
11165         domain = mono_object_domain (tb);
11166         klass = mono_class_from_mono_type (tb->type.type);
11167
11168         /*
11169          * Check for user defined Type subclasses.
11170          */
11171         RESOLVE_TYPE (tb->parent);
11172         check_array_for_usertypes (tb->interfaces);
11173         if (tb->fields) {
11174                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11175                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11176                         if (fb) {
11177                                 RESOLVE_TYPE (fb->type);
11178                                 check_array_for_usertypes (fb->modreq);
11179                                 check_array_for_usertypes (fb->modopt);
11180                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11181                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11182                         }
11183                 }
11184         }
11185         if (tb->methods) {
11186                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11187                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11188                         if (mb) {
11189                                 RESOLVE_TYPE (mb->rtype);
11190                                 check_array_for_usertypes (mb->return_modreq);
11191                                 check_array_for_usertypes (mb->return_modopt);
11192                                 check_array_for_usertypes (mb->parameters);
11193                                 if (mb->param_modreq)
11194                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11195                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11196                                 if (mb->param_modopt)
11197                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11198                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11199                         }
11200                 }
11201         }
11202         if (tb->ctors) {
11203                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11204                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11205                         if (mb) {
11206                                 check_array_for_usertypes (mb->parameters);
11207                                 if (mb->param_modreq)
11208                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11209                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11210                                 if (mb->param_modopt)
11211                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11212                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11213                         }
11214                 }
11215         }
11216
11217         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11218
11219         /* 
11220          * we need to lock the domain because the lock will be taken inside
11221          * So, we need to keep the locking order correct.
11222          */
11223         mono_loader_lock ();
11224         mono_domain_lock (domain);
11225         if (klass->wastypebuilder) {
11226                 mono_domain_unlock (domain);
11227                 mono_loader_unlock ();
11228                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11229         }
11230         /*
11231          * Fields to set in klass:
11232          * the various flags: delegate/unicode/contextbound etc.
11233          */
11234         klass->flags = tb->attrs;
11235         klass->has_cctor = 1;
11236         klass->has_finalize = 1;
11237
11238         /* fool mono_class_setup_parent */
11239         klass->supertypes = NULL;
11240         mono_class_setup_parent (klass, klass->parent);
11241         mono_class_setup_mono_type (klass);
11242
11243 #if 0
11244         if (!((MonoDynamicImage*)klass->image)->run) {
11245                 if (klass->generic_container) {
11246                         /* FIXME: The code below can't handle generic classes */
11247                         klass->wastypebuilder = TRUE;
11248                         mono_loader_unlock ();
11249                         mono_domain_unlock (domain);
11250                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11251                 }
11252         }
11253 #endif
11254
11255         /* enums are done right away */
11256         if (!klass->enumtype)
11257                 ensure_runtime_vtable (klass);
11258
11259         if (tb->subtypes) {
11260                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11261                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11262                         mono_class_alloc_ext (klass);
11263                         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)));
11264                 }
11265         }
11266
11267         klass->nested_classes_inited = TRUE;
11268
11269         /* fields and object layout */
11270         if (klass->parent) {
11271                 if (!klass->parent->size_inited)
11272                         mono_class_init (klass->parent);
11273                 klass->instance_size = klass->parent->instance_size;
11274                 klass->sizes.class_size = 0;
11275                 klass->min_align = klass->parent->min_align;
11276                 /* if the type has no fields we won't call the field_setup
11277                  * routine which sets up klass->has_references.
11278                  */
11279                 klass->has_references |= klass->parent->has_references;
11280         } else {
11281                 klass->instance_size = sizeof (MonoObject);
11282                 klass->min_align = 1;
11283         }
11284
11285         /* FIXME: handle packing_size and instance_size */
11286         typebuilder_setup_fields (klass, &error);
11287         if (!mono_error_ok (&error))
11288                 goto failure;
11289         typebuilder_setup_properties (klass, &error);
11290         if (!mono_error_ok (&error))
11291                 goto failure;
11292
11293         typebuilder_setup_events (klass, &error);
11294         if (!mono_error_ok (&error))
11295                 goto failure;
11296
11297         klass->wastypebuilder = TRUE;
11298
11299         /* 
11300          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11301          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11302          * we want to return normal System.MonoType objects, so clear these out from the cache.
11303          *
11304          * Together with this we must ensure the contents of all instances to match the created type.
11305          */
11306         if (domain->type_hash && klass->generic_container)
11307                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11308
11309         mono_domain_unlock (domain);
11310         mono_loader_unlock ();
11311
11312         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11313                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11314                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11315         }
11316
11317         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11318         g_assert (res != (MonoReflectionType*)tb);
11319
11320         return res;
11321
11322 failure:
11323         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11324         klass->wastypebuilder = TRUE;
11325         mono_domain_unlock (domain);
11326         mono_loader_unlock ();
11327         mono_error_raise_exception (&error);
11328         return NULL;
11329 }
11330
11331 void
11332 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11333 {
11334         MonoGenericParamFull *param;
11335         MonoImage *image;
11336         MonoClass *pklass;
11337         MonoError error;
11338
11339         MONO_ARCH_SAVE_REGS;
11340
11341         image = &gparam->tbuilder->module->dynamic_image->image;
11342
11343         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11344
11345         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11346         g_assert (mono_error_ok (&error));
11347         param->param.num = gparam->index;
11348
11349         if (gparam->mbuilder) {
11350                 if (!gparam->mbuilder->generic_container) {
11351                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11352                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11353                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11354                         gparam->mbuilder->generic_container->is_method = TRUE;
11355                         /* 
11356                          * Cannot set owner.method, since the MonoMethod is not created yet.
11357                          * Set the image field instead, so type_in_image () works.
11358                          */
11359                         gparam->mbuilder->generic_container->image = klass->image;
11360                 }
11361                 param->param.owner = gparam->mbuilder->generic_container;
11362         } else if (gparam->tbuilder) {
11363                 if (!gparam->tbuilder->generic_container) {
11364                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11365                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11366                         gparam->tbuilder->generic_container->owner.klass = klass;
11367                 }
11368                 param->param.owner = gparam->tbuilder->generic_container;
11369         }
11370
11371         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11372
11373         gparam->type.type = &pklass->byval_arg;
11374
11375         mono_class_set_ref_info (pklass, gparam);
11376         mono_image_lock (image);
11377         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11378         mono_image_unlock (image);
11379 }
11380
11381 MonoArray *
11382 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11383 {
11384         MonoReflectionModuleBuilder *module = sig->module;
11385         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11386         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11387         guint32 buflen, i;
11388         MonoArray *result;
11389         SigBuffer buf;
11390
11391         check_array_for_usertypes (sig->arguments);
11392
11393         sigbuffer_init (&buf, 32);
11394
11395         sigbuffer_add_value (&buf, 0x07);
11396         sigbuffer_add_value (&buf, na);
11397         if (assembly != NULL){
11398                 for (i = 0; i < na; ++i) {
11399                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11400                         encode_reflection_type (assembly, type, &buf);
11401                 }
11402         }
11403
11404         buflen = buf.p - buf.buf;
11405         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11406         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11407         sigbuffer_free (&buf);
11408
11409         return result;
11410 }
11411
11412 MonoArray *
11413 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11414 {
11415         MonoDynamicImage *assembly = sig->module->dynamic_image;
11416         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11417         guint32 buflen, i;
11418         MonoArray *result;
11419         SigBuffer buf;
11420
11421         check_array_for_usertypes (sig->arguments);
11422
11423         sigbuffer_init (&buf, 32);
11424
11425         sigbuffer_add_value (&buf, 0x06);
11426         for (i = 0; i < na; ++i) {
11427                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11428                 encode_reflection_type (assembly, type, &buf);
11429         }
11430
11431         buflen = buf.p - buf.buf;
11432         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11433         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11434         sigbuffer_free (&buf);
11435
11436         return result;
11437 }
11438
11439 void 
11440 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11441 {
11442         ReflectionMethodBuilder rmb;
11443         MonoMethodSignature *sig;
11444         MonoClass *klass;
11445         GSList *l;
11446         int i;
11447
11448         sig = dynamic_method_to_signature (mb);
11449
11450         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11451
11452         /*
11453          * Resolve references.
11454          */
11455         /* 
11456          * Every second entry in the refs array is reserved for storing handle_class,
11457          * which is needed by the ldtoken implementation in the JIT.
11458          */
11459         rmb.nrefs = mb->nrefs;
11460         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11461         for (i = 0; i < mb->nrefs; i += 2) {
11462                 MonoClass *handle_class;
11463                 gpointer ref;
11464                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11465
11466                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11467                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11468                         /*
11469                          * The referenced DynamicMethod should already be created by the managed
11470                          * code, except in the case of circular references. In that case, we store
11471                          * method in the refs array, and fix it up later when the referenced 
11472                          * DynamicMethod is created.
11473                          */
11474                         if (method->mhandle) {
11475                                 ref = method->mhandle;
11476                         } else {
11477                                 /* FIXME: GC object stored in unmanaged memory */
11478                                 ref = method;
11479
11480                                 /* FIXME: GC object stored in unmanaged memory */
11481                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11482                         }
11483                         handle_class = mono_defaults.methodhandle_class;
11484                 } else {
11485                         MonoException *ex = NULL;
11486                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11487                         if (!ref)
11488                                 ex = mono_get_exception_type_load (NULL, NULL);
11489                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11490                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11491
11492                         if (ex) {
11493                                 g_free (rmb.refs);
11494                                 mono_raise_exception (ex);
11495                                 return;
11496                         }
11497                 }
11498
11499                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11500                 rmb.refs [i + 1] = handle_class;
11501         }               
11502
11503         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11504
11505         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11506
11507         /* Fix up refs entries pointing at us */
11508         for (l = mb->referenced_by; l; l = l->next) {
11509                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11510                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11511                 gpointer *data;
11512                 
11513                 g_assert (method->mhandle);
11514
11515                 data = (gpointer*)wrapper->method_data;
11516                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11517                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11518                                 data [i + 1] = mb->mhandle;
11519                 }
11520         }
11521         g_slist_free (mb->referenced_by);
11522
11523         g_free (rmb.refs);
11524
11525         /* ilgen is no longer needed */
11526         mb->ilgen = NULL;
11527 }
11528
11529 #endif /* DISABLE_REFLECTION_EMIT */
11530
11531 void
11532 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11533 {
11534         g_assert (mb);
11535
11536         if (mb->mhandle)
11537                 mono_runtime_free_method (
11538                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11539 }
11540
11541 /**
11542  * 
11543  * mono_reflection_is_valid_dynamic_token:
11544  * 
11545  * Returns TRUE if token is valid.
11546  * 
11547  */
11548 gboolean
11549 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11550 {
11551         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11552 }
11553
11554 MonoMethodSignature *
11555 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11556 {
11557         MonoMethodSignature *sig;
11558         g_assert (image->dynamic);
11559
11560         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11561         if (sig)
11562                 return sig;
11563
11564         return mono_method_signature (method);
11565 }
11566
11567 #ifndef DISABLE_REFLECTION_EMIT
11568
11569 /**
11570  * mono_reflection_lookup_dynamic_token:
11571  *
11572  * Finish the Builder object pointed to by TOKEN and return the corresponding
11573  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11574  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11575  * mapping table.
11576  *
11577  * LOCKING: Take the loader lock
11578  */
11579 gpointer
11580 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11581 {
11582         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11583         MonoObject *obj;
11584         MonoClass *klass;
11585
11586         mono_loader_lock ();
11587         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11588         mono_loader_unlock ();
11589         if (!obj) {
11590                 if (valid_token)
11591                         g_error ("Could not find required dynamic token 0x%08x", token);
11592                 else
11593                         return NULL;
11594         }
11595
11596         if (!handle_class)
11597                 handle_class = &klass;
11598         return resolve_object (image, obj, handle_class, context);
11599 }
11600
11601 /*
11602  * ensure_complete_type:
11603  *
11604  *   Ensure that KLASS is completed if it is a dynamic type, or references
11605  * dynamic types.
11606  */
11607 static void
11608 ensure_complete_type (MonoClass *klass)
11609 {
11610         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11611                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11612
11613                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11614
11615                 // Asserting here could break a lot of code
11616                 //g_assert (klass->wastypebuilder);
11617         }
11618
11619         if (klass->generic_class) {
11620                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11621                 int i;
11622
11623                 for (i = 0; i < inst->type_argc; ++i) {
11624                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11625                 }
11626         }
11627 }
11628
11629 static gpointer
11630 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11631 {
11632         gpointer result = NULL;
11633
11634         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11635                 result = mono_string_intern ((MonoString*)obj);
11636                 *handle_class = mono_defaults.string_class;
11637                 g_assert (result);
11638         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11639                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11640                 MonoClass *mc = mono_class_from_mono_type (type);
11641                 if (!mono_class_init (mc))
11642                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11643
11644                 if (context) {
11645                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11646                         result = mono_class_from_mono_type (inflated);
11647                         mono_metadata_free_type (inflated);
11648                 } else {
11649                         result = mono_class_from_mono_type (type);
11650                 }
11651                 *handle_class = mono_defaults.typehandle_class;
11652                 g_assert (result);
11653         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11654                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11655                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11656                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11657                 result = ((MonoReflectionMethod*)obj)->method;
11658                 if (context)
11659                         result = mono_class_inflate_generic_method (result, context);
11660                 *handle_class = mono_defaults.methodhandle_class;
11661                 g_assert (result);
11662         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11663                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11664                 result = mb->mhandle;
11665                 if (!result) {
11666                         /* Type is not yet created */
11667                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11668
11669                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11670
11671                         /*
11672                          * Hopefully this has been filled in by calling CreateType() on the
11673                          * TypeBuilder.
11674                          */
11675                         /*
11676                          * TODO: This won't work if the application finishes another 
11677                          * TypeBuilder instance instead of this one.
11678                          */
11679                         result = mb->mhandle;
11680                 }
11681                 if (context)
11682                         result = mono_class_inflate_generic_method (result, context);
11683                 *handle_class = mono_defaults.methodhandle_class;
11684         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11685                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11686
11687                 result = cb->mhandle;
11688                 if (!result) {
11689                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11690
11691                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11692                         result = cb->mhandle;
11693                 }
11694                 if (context)
11695                         result = mono_class_inflate_generic_method (result, context);
11696                 *handle_class = mono_defaults.methodhandle_class;
11697         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11698                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11699
11700                 ensure_complete_type (field->parent);
11701                 if (context) {
11702                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11703                         MonoClass *class = mono_class_from_mono_type (inflated);
11704                         MonoClassField *inflated_field;
11705                         gpointer iter = NULL;
11706                         mono_metadata_free_type (inflated);
11707                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11708                                 if (!strcmp (field->name, inflated_field->name))
11709                                         break;
11710                         }
11711                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11712                         result = inflated_field;
11713                 } else {
11714                         result = field;
11715                 }
11716                 *handle_class = mono_defaults.fieldhandle_class;
11717                 g_assert (result);
11718         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11719                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11720                 result = fb->handle;
11721
11722                 if (!result) {
11723                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11724
11725                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11726                         result = fb->handle;
11727                 }
11728
11729                 if (fb->handle && fb->handle->parent->generic_container) {
11730                         MonoClass *klass = fb->handle->parent;
11731                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11732                         MonoClass *inflated = mono_class_from_mono_type (type);
11733
11734                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11735                         g_assert (result);
11736                         mono_metadata_free_type (type);
11737                 }
11738                 *handle_class = mono_defaults.fieldhandle_class;
11739         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11740                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11741                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11742                 MonoClass *klass;
11743
11744                 klass = type->data.klass;
11745                 if (klass->wastypebuilder) {
11746                         /* Already created */
11747                         result = klass;
11748                 }
11749                 else {
11750                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11751                         result = type->data.klass;
11752                         g_assert (result);
11753                 }
11754                 *handle_class = mono_defaults.typehandle_class;
11755         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11756                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11757                 MonoMethodSignature *sig;
11758                 int nargs, i;
11759
11760                 if (helper->arguments)
11761                         nargs = mono_array_length (helper->arguments);
11762                 else
11763                         nargs = 0;
11764
11765                 sig = mono_metadata_signature_alloc (image, nargs);
11766                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11767                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11768
11769                 if (helper->unmanaged_call_conv) { /* unmanaged */
11770                         sig->call_convention = helper->unmanaged_call_conv - 1;
11771                         sig->pinvoke = TRUE;
11772                 } else if (helper->call_conv & 0x02) {
11773                         sig->call_convention = MONO_CALL_VARARG;
11774                 } else {
11775                         sig->call_convention = MONO_CALL_DEFAULT;
11776                 }
11777
11778                 sig->param_count = nargs;
11779                 /* TODO: Copy type ? */
11780                 sig->ret = helper->return_type->type;
11781                 for (i = 0; i < nargs; ++i)
11782                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11783
11784                 result = sig;
11785                 *handle_class = NULL;
11786         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11787                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11788                 /* Already created by the managed code */
11789                 g_assert (method->mhandle);
11790                 result = method->mhandle;
11791                 *handle_class = mono_defaults.methodhandle_class;
11792         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11793                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11794                 type = mono_class_inflate_generic_type (type, context);
11795                 result = mono_class_from_mono_type (type);
11796                 *handle_class = mono_defaults.typehandle_class;
11797                 g_assert (result);
11798                 mono_metadata_free_type (type);
11799         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11800                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11801                 type = mono_class_inflate_generic_type (type, context);
11802                 result = mono_class_from_mono_type (type);
11803                 *handle_class = mono_defaults.typehandle_class;
11804                 g_assert (result);
11805                 mono_metadata_free_type (type);
11806         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11807                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11808                 MonoClass *inflated;
11809                 MonoType *type;
11810                 MonoClassField *field;
11811
11812                 if (is_sre_field_builder (mono_object_class (f->fb)))
11813                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11814                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11815                         field = ((MonoReflectionField*)f->fb)->field;
11816                 else
11817                         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)));
11818
11819                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11820                 inflated = mono_class_from_mono_type (type);
11821
11822                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11823                 ensure_complete_type (field->parent);
11824                 g_assert (result);
11825                 mono_metadata_free_type (type);
11826                 *handle_class = mono_defaults.fieldhandle_class;
11827         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11828                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11829                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11830                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11831                 MonoMethod *method;
11832
11833                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11834                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11835                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11836                         method = ((MonoReflectionMethod *)c->cb)->method;
11837                 else
11838                         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)));
11839
11840                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11841                 *handle_class = mono_defaults.methodhandle_class;
11842                 mono_metadata_free_type (type);
11843         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11844                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11845                 if (m->method_args) {
11846                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11847                         if (context)
11848                                 result = mono_class_inflate_generic_method (result, context);
11849                 } else {
11850                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11851                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11852                         MonoMethod *method;
11853
11854                         if (is_sre_method_builder (mono_object_class (m->mb)))
11855                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11856                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11857                                 method = ((MonoReflectionMethod *)m->mb)->method;
11858                         else
11859                                 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)));
11860
11861                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11862                         mono_metadata_free_type (type);
11863                 }
11864                 *handle_class = mono_defaults.methodhandle_class;
11865         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11866                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11867                 MonoType *mtype;
11868                 MonoClass *klass;
11869                 MonoMethod *method;
11870                 gpointer iter;
11871                 char *name;
11872
11873                 mtype = mono_reflection_type_get_handle (m->parent);
11874                 klass = mono_class_from_mono_type (mtype);
11875
11876                 /* Find the method */
11877
11878                 name = mono_string_to_utf8 (m->name);
11879                 iter = NULL;
11880                 while ((method = mono_class_get_methods (klass, &iter))) {
11881                         if (!strcmp (method->name, name))
11882                                 break;
11883                 }
11884                 g_free (name);
11885
11886                 // FIXME:
11887                 g_assert (method);
11888                 // FIXME: Check parameters/return value etc. match
11889
11890                 result = method;
11891                 *handle_class = mono_defaults.methodhandle_class;
11892         } else if (is_sre_array (mono_object_get_class(obj)) ||
11893                                 is_sre_byref (mono_object_get_class(obj)) ||
11894                                 is_sre_pointer (mono_object_get_class(obj))) {
11895                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11896                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11897                 result = mono_class_from_mono_type (type);
11898                 *handle_class = mono_defaults.typehandle_class;
11899         } else {
11900                 g_print ("%s\n", obj->vtable->klass->name);
11901                 g_assert_not_reached ();
11902         }
11903         return result;
11904 }
11905
11906 #else /* DISABLE_REFLECTION_EMIT */
11907
11908 MonoArray*
11909 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11910 {
11911         g_assert_not_reached ();
11912         return NULL;
11913 }
11914
11915 void
11916 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11917 {
11918         g_assert_not_reached ();
11919 }
11920
11921 void
11922 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11923 {
11924         g_assert_not_reached ();
11925 }
11926
11927 void
11928 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11929 {
11930         g_assert_not_reached ();
11931 }
11932
11933 void
11934 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11935 {
11936         g_assert_not_reached ();
11937 }
11938
11939 void
11940 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11941 {
11942         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11943 }
11944
11945 void
11946 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11947 {
11948         g_assert_not_reached ();
11949 }
11950
11951 void
11952 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11953 {
11954         g_assert_not_reached ();
11955 }
11956
11957 MonoReflectionModule *
11958 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11959 {
11960         g_assert_not_reached ();
11961         return NULL;
11962 }
11963
11964 guint32
11965 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11966 {
11967         g_assert_not_reached ();
11968         return 0;
11969 }
11970
11971 guint32
11972 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11973 {
11974         g_assert_not_reached ();
11975         return 0;
11976 }
11977
11978 guint32
11979 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11980                                                  gboolean create_open_instance, gboolean register_token)
11981 {
11982         g_assert_not_reached ();
11983         return 0;
11984 }
11985
11986 void
11987 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11988 {
11989 }
11990
11991 void
11992 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11993                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11994                                           MonoArray *events)
11995 {
11996         g_assert_not_reached ();
11997 }
11998
11999 void
12000 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12001 {
12002         *overrides = NULL;
12003         *num_overrides = 0;
12004 }
12005
12006 MonoReflectionEvent *
12007 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12008 {
12009         g_assert_not_reached ();
12010         return NULL;
12011 }
12012
12013 MonoReflectionType*
12014 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12015 {
12016         g_assert_not_reached ();
12017         return NULL;
12018 }
12019
12020 void
12021 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12022 {
12023         g_assert_not_reached ();
12024 }
12025
12026 MonoArray *
12027 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12028 {
12029         g_assert_not_reached ();
12030         return NULL;
12031 }
12032
12033 MonoArray *
12034 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12035 {
12036         g_assert_not_reached ();
12037         return NULL;
12038 }
12039
12040 void 
12041 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12042 {
12043 }
12044
12045 gpointer
12046 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12047 {
12048         return NULL;
12049 }
12050
12051 MonoType*
12052 mono_reflection_type_get_handle (MonoReflectionType* ref)
12053 {
12054         if (!ref)
12055                 return NULL;
12056         return ref->type;
12057 }
12058
12059 void
12060 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12061 {
12062         g_assert_not_reached ();
12063 }
12064
12065 #endif /* DISABLE_REFLECTION_EMIT */
12066
12067 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12068 const static guint32 declsec_flags_map[] = {
12069         0x00000000,                                     /* empty */
12070         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12071         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12072         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12073         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12074         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12075         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12076         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12077         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12078         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12079         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12080         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12081         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12082         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12083         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12084         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12085         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12086         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12087         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12088 };
12089
12090 /*
12091  * Returns flags that includes all available security action associated to the handle.
12092  * @token: metadata token (either for a class or a method)
12093  * @image: image where resides the metadata.
12094  */
12095 static guint32
12096 mono_declsec_get_flags (MonoImage *image, guint32 token)
12097 {
12098         int index = mono_metadata_declsec_from_index (image, token);
12099         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12100         guint32 result = 0;
12101         guint32 action;
12102         int i;
12103
12104         /* HasSecurity can be present for other, not specially encoded, attributes,
12105            e.g. SuppressUnmanagedCodeSecurityAttribute */
12106         if (index < 0)
12107                 return 0;
12108
12109         for (i = index; i < t->rows; i++) {
12110                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12111
12112                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12113                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12114                         break;
12115
12116                 action = cols [MONO_DECL_SECURITY_ACTION];
12117                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12118                         result |= declsec_flags_map [action];
12119                 } else {
12120                         g_assert_not_reached ();
12121                 }
12122         }
12123         return result;
12124 }
12125
12126 /*
12127  * Get the security actions (in the form of flags) associated with the specified method.
12128  *
12129  * @method: The method for which we want the declarative security flags.
12130  * Return the declarative security flags for the method (only).
12131  *
12132  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12133  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12134  */
12135 guint32
12136 mono_declsec_flags_from_method (MonoMethod *method)
12137 {
12138         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12139                 /* FIXME: No cache (for the moment) */
12140                 guint32 idx = mono_method_get_index (method);
12141                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12142                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12143                 return mono_declsec_get_flags (method->klass->image, idx);
12144         }
12145         return 0;
12146 }
12147
12148 /*
12149  * Get the security actions (in the form of flags) associated with the specified class.
12150  *
12151  * @klass: The class for which we want the declarative security flags.
12152  * Return the declarative security flags for the class.
12153  *
12154  * Note: We cache the flags inside the MonoClass structure as this will get 
12155  *       called very often (at least for each method).
12156  */
12157 guint32
12158 mono_declsec_flags_from_class (MonoClass *klass)
12159 {
12160         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12161                 if (!klass->ext || !klass->ext->declsec_flags) {
12162                         guint32 idx;
12163
12164                         idx = mono_metadata_token_index (klass->type_token);
12165                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12166                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12167                         mono_loader_lock ();
12168                         mono_class_alloc_ext (klass);
12169                         mono_loader_unlock ();
12170                         /* we cache the flags on classes */
12171                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12172                 }
12173                 return klass->ext->declsec_flags;
12174         }
12175         return 0;
12176 }
12177
12178 /*
12179  * Get the security actions (in the form of flags) associated with the specified assembly.
12180  *
12181  * @assembly: The assembly for which we want the declarative security flags.
12182  * Return the declarative security flags for the assembly.
12183  */
12184 guint32
12185 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12186 {
12187         guint32 idx = 1; /* there is only one assembly */
12188         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12189         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12190         return mono_declsec_get_flags (assembly->image, idx);
12191 }
12192
12193
12194 /*
12195  * Fill actions for the specific index (which may either be an encoded class token or
12196  * an encoded method token) from the metadata image.
12197  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12198  */
12199 static MonoBoolean
12200 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12201         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12202 {
12203         MonoBoolean result = FALSE;
12204         MonoTableInfo *t;
12205         guint32 cols [MONO_DECL_SECURITY_SIZE];
12206         int index = mono_metadata_declsec_from_index (image, token);
12207         int i;
12208
12209         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12210         for (i = index; i < t->rows; i++) {
12211                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12212
12213                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12214                         return result;
12215
12216                 /* if present only replace (class) permissions with method permissions */
12217                 /* if empty accept either class or method permissions */
12218                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12219                         if (!actions->demand.blob) {
12220                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12221                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12222                                 actions->demand.blob = (char*) (blob + 2);
12223                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12224                                 result = TRUE;
12225                         }
12226                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12227                         if (!actions->noncasdemand.blob) {
12228                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12229                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12230                                 actions->noncasdemand.blob = (char*) (blob + 2);
12231                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12232                                 result = TRUE;
12233                         }
12234                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12235                         if (!actions->demandchoice.blob) {
12236                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12237                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12238                                 actions->demandchoice.blob = (char*) (blob + 2);
12239                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12240                                 result = TRUE;
12241                         }
12242                 }
12243         }
12244
12245         return result;
12246 }
12247
12248 static MonoBoolean
12249 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12250         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12251 {
12252         guint32 idx = mono_metadata_token_index (klass->type_token);
12253         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12254         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12255         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12256 }
12257
12258 static MonoBoolean
12259 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12260         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12261 {
12262         guint32 idx = mono_method_get_index (method);
12263         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12264         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12265         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12266 }
12267
12268 /*
12269  * Collect all actions (that requires to generate code in mini) assigned for
12270  * the specified method.
12271  * Note: Don't use the content of actions if the function return FALSE.
12272  */
12273 MonoBoolean
12274 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12275 {
12276         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12277                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12278         MonoBoolean result = FALSE;
12279         guint32 flags;
12280
12281         /* quick exit if no declarative security is present in the metadata */
12282         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12283                 return FALSE;
12284
12285         /* we want the original as the wrapper is "free" of the security informations */
12286         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12287                 method = mono_marshal_method_from_wrapper (method);
12288                 if (!method)
12289                         return FALSE;
12290         }
12291
12292         /* First we look for method-level attributes */
12293         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12294                 mono_class_init (method->klass);
12295                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12296
12297                 result = mono_declsec_get_method_demands_params (method, demands, 
12298                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12299         }
12300
12301         /* Here we use (or create) the class declarative cache to look for demands */
12302         flags = mono_declsec_flags_from_class (method->klass);
12303         if (flags & mask) {
12304                 if (!result) {
12305                         mono_class_init (method->klass);
12306                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12307                 }
12308                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12309                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12310         }
12311
12312         /* The boolean return value is used as a shortcut in case nothing needs to
12313            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12314         return result;
12315 }
12316
12317
12318 /*
12319  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12320  *
12321  * Note: Don't use the content of actions if the function return FALSE.
12322  */
12323 MonoBoolean
12324 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12325 {
12326         MonoBoolean result = FALSE;
12327         guint32 flags;
12328
12329         /* quick exit if no declarative security is present in the metadata */
12330         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12331                 return FALSE;
12332
12333         /* we want the original as the wrapper is "free" of the security informations */
12334         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12335                 method = mono_marshal_method_from_wrapper (method);
12336                 if (!method)
12337                         return FALSE;
12338         }
12339
12340         /* results are independant - zeroize both */
12341         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12342         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12343
12344         /* First we look for method-level attributes */
12345         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12346                 mono_class_init (method->klass);
12347
12348                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12349                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12350         }
12351
12352         /* Here we use (or create) the class declarative cache to look for demands */
12353         flags = mono_declsec_flags_from_class (method->klass);
12354         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12355                 mono_class_init (method->klass);
12356
12357                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12358                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12359         }
12360
12361         return result;
12362 }
12363
12364 /*
12365  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12366  *
12367  * @klass       The inherited class - this is the class that provides the security check (attributes)
12368  * @demans      
12369  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12370  * 
12371  * Note: Don't use the content of actions if the function return FALSE.
12372  */
12373 MonoBoolean
12374 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12375 {
12376         MonoBoolean result = FALSE;
12377         guint32 flags;
12378
12379         /* quick exit if no declarative security is present in the metadata */
12380         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12381                 return FALSE;
12382
12383         /* Here we use (or create) the class declarative cache to look for demands */
12384         flags = mono_declsec_flags_from_class (klass);
12385         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12386                 mono_class_init (klass);
12387                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12388
12389                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12390                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12391         }
12392
12393         return result;
12394 }
12395
12396 /*
12397  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12398  *
12399  * Note: Don't use the content of actions if the function return FALSE.
12400  */
12401 MonoBoolean
12402 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12403 {
12404         /* quick exit if no declarative security is present in the metadata */
12405         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12406                 return FALSE;
12407
12408         /* we want the original as the wrapper is "free" of the security informations */
12409         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12410                 method = mono_marshal_method_from_wrapper (method);
12411                 if (!method)
12412                         return FALSE;
12413         }
12414
12415         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12416                 mono_class_init (method->klass);
12417                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12418
12419                 return mono_declsec_get_method_demands_params (method, demands, 
12420                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12421         }
12422         return FALSE;
12423 }
12424
12425
12426 static MonoBoolean
12427 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12428 {
12429         guint32 cols [MONO_DECL_SECURITY_SIZE];
12430         MonoTableInfo *t;
12431         int i;
12432
12433         int index = mono_metadata_declsec_from_index (image, token);
12434         if (index == -1)
12435                 return FALSE;
12436
12437         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12438         for (i = index; i < t->rows; i++) {
12439                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12440
12441                 /* shortcut - index are ordered */
12442                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12443                         return FALSE;
12444
12445                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12446                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12447                         entry->blob = (char*) (metadata + 2);
12448                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12449                         return TRUE;
12450                 }
12451         }
12452
12453         return FALSE;
12454 }
12455
12456 MonoBoolean
12457 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12458 {
12459         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12460                 guint32 idx = mono_method_get_index (method);
12461                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12462                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12463                 return get_declsec_action (method->klass->image, idx, action, entry);
12464         }
12465         return FALSE;
12466 }
12467
12468 MonoBoolean
12469 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12470 {
12471         /* use cache */
12472         guint32 flags = mono_declsec_flags_from_class (klass);
12473         if (declsec_flags_map [action] & flags) {
12474                 guint32 idx = mono_metadata_token_index (klass->type_token);
12475                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12476                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12477                 return get_declsec_action (klass->image, idx, action, entry);
12478         }
12479         return FALSE;
12480 }
12481
12482 MonoBoolean
12483 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12484 {
12485         guint32 idx = 1; /* there is only one assembly */
12486         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12487         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12488
12489         return get_declsec_action (assembly->image, idx, action, entry);
12490 }
12491
12492 gboolean
12493 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12494 {
12495         MonoObject *res, *exc;
12496         void *params [1];
12497         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12498         static MonoMethod *method = NULL;
12499
12500         if (!System_Reflection_Emit_TypeBuilder) {
12501                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12502                 g_assert (System_Reflection_Emit_TypeBuilder);
12503         }
12504         if (method == NULL) {
12505                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12506                 g_assert (method);
12507         }
12508
12509         /* 
12510          * The result of mono_type_get_object () might be a System.MonoType but we
12511          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12512          */
12513         g_assert (mono_class_get_ref_info (klass));
12514         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12515
12516         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12517
12518         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12519         if (exc)
12520                 return FALSE;
12521         else
12522                 return *(MonoBoolean*)mono_object_unbox (res);
12523 }