5bcc7405920bf54a1322c080470c10dc9fcc96a4
[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         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2673
2674         if (tb->generic_params)
2675                 parent = create_generic_typespec (assembly, tb);
2676         else
2677                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2678         
2679         name = mono_string_to_utf8 (rmb.name);
2680         sig = method_builder_encode_signature (assembly, &rmb);
2681
2682         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2683
2684         g_free (name);
2685         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2686         return token;
2687 }
2688 #endif
2689
2690 static gboolean
2691 is_field_on_inst (MonoClassField *field)
2692 {
2693         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2694 }
2695
2696 /*
2697  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2698  */
2699 static MonoType*
2700 get_field_on_inst_generic_type (MonoClassField *field)
2701 {
2702         MonoClass *class, *gtd;
2703         MonoDynamicGenericClass *dgclass;
2704         int field_index;
2705
2706         g_assert (is_field_on_inst (field));
2707
2708         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2709
2710         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2711                 field_index = field - dgclass->fields;
2712                 return dgclass->field_generic_types [field_index];              
2713         }
2714
2715         class = field->parent;
2716         gtd = class->generic_class->container_class;
2717
2718         if (field >= class->fields && field - class->fields < class->field.count) {
2719                 field_index = field - class->fields;
2720                 return gtd->fields [field_index].type;
2721         }
2722
2723         g_assert_not_reached ();
2724         return 0;
2725 }
2726
2727 #ifndef DISABLE_REFLECTION_EMIT
2728 static guint32
2729 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2730 {
2731         MonoType *type;
2732         guint32 token;
2733
2734         g_assert (field);
2735         g_assert (field->parent);
2736
2737         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2738         if (token)
2739                 return token;
2740
2741         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2742                 int index = field - field->parent->fields;
2743                 type = field->parent->generic_class->container_class->fields [index].type;
2744         } else {
2745                 if (is_field_on_inst (field))
2746                         type = get_field_on_inst_generic_type (field);
2747                 else
2748                         type = field->type;
2749         }
2750         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2751                                                                                         mono_field_get_name (field),
2752                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2753         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2754         return token;
2755 }
2756
2757 static guint32
2758 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2759 {
2760         guint32 token;
2761         MonoClass *klass;
2762         MonoGenericClass *gclass;
2763         MonoDynamicGenericClass *dgclass;
2764         MonoType *type;
2765         char *name;
2766
2767         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2768         if (token)
2769                 return token;
2770         if (is_sre_field_builder (mono_object_class (f->fb))) {
2771                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2772                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2773                 klass = mono_class_from_mono_type (type);
2774                 gclass = type->data.generic_class;
2775                 g_assert (gclass->is_dynamic);
2776                 dgclass = (MonoDynamicGenericClass *) gclass;
2777
2778                 name = mono_string_to_utf8 (fb->name);
2779                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2780                                                                                                 field_encode_signature (assembly, fb));
2781                 g_free (name);          
2782         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2783                 guint32 sig;
2784                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2785
2786                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2787                 klass = mono_class_from_mono_type (type);
2788
2789                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2790                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2791         } else {
2792                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2793                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2794         }
2795
2796         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2797         return token;
2798 }
2799
2800 static guint32
2801 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2802 {
2803         guint32 sig, token;
2804         MonoClass *klass;
2805         MonoGenericClass *gclass;
2806         MonoType *type;
2807
2808         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2809
2810         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2811         if (token)
2812                 return token;
2813
2814         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2815                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2816                 MonoDynamicGenericClass *dgclass;
2817                 ReflectionMethodBuilder rmb;
2818                 char *name;
2819
2820                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2821                 klass = mono_class_from_mono_type (type);
2822
2823                 gclass = type->data.generic_class;
2824                 g_assert (gclass->is_dynamic);
2825                 dgclass = (MonoDynamicGenericClass *) gclass;
2826
2827                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2828
2829                 name = mono_string_to_utf8 (rmb.name);
2830
2831                 sig = method_builder_encode_signature (assembly, &rmb);
2832
2833                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2834                 g_free (name);
2835         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2836                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2837
2838                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2839                 klass = mono_class_from_mono_type (type);
2840
2841                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2842                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2843         } else {
2844                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2845                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2846         }
2847
2848
2849         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2850         return token;
2851 }
2852
2853 static MonoMethod*
2854 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2855 {
2856         MonoClass *klass;
2857         MonoGenericContext tmp_context;
2858         MonoType **type_argv;
2859         MonoGenericInst *ginst;
2860         MonoMethod *method, *inflated;
2861         int count, i;
2862
2863         init_type_builder_generics ((MonoObject*)m->inst);
2864
2865         method = inflate_method (m->inst, (MonoObject*)m->mb);
2866
2867         klass = method->klass;
2868
2869         if (m->method_args == NULL)
2870                 return method;
2871
2872         if (method->is_inflated)
2873                 method = ((MonoMethodInflated *) method)->declaring;
2874
2875         count = mono_array_length (m->method_args);
2876
2877         type_argv = g_new0 (MonoType *, count);
2878         for (i = 0; i < count; i++) {
2879                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2880                 type_argv [i] = mono_reflection_type_get_handle (garg);
2881         }
2882         ginst = mono_metadata_get_generic_inst (count, type_argv);
2883         g_free (type_argv);
2884
2885         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2886         tmp_context.method_inst = ginst;
2887
2888         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2889         return inflated;
2890 }
2891
2892 static guint32
2893 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2894 {
2895         guint32 sig, token = 0;
2896         MonoType *type;
2897         MonoClass *klass;
2898
2899         if (m->method_args) {
2900                 MonoMethod *inflated;
2901
2902                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2903                 if (create_methodspec)
2904                         token = mono_image_get_methodspec_token (assembly, inflated);
2905                 else
2906                         token = mono_image_get_inflated_method_token (assembly, inflated);
2907                 return token;
2908         }
2909
2910         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2911         if (token)
2912                 return token;
2913
2914         if (is_sre_method_builder (mono_object_class (m->mb))) {
2915                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2916                 MonoGenericClass *gclass;
2917                 ReflectionMethodBuilder rmb;
2918                 char *name;
2919
2920                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2921                 klass = mono_class_from_mono_type (type);
2922                 gclass = type->data.generic_class;
2923                 g_assert (gclass->is_dynamic);
2924
2925                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2926
2927                 name = mono_string_to_utf8 (rmb.name);
2928
2929                 sig = method_builder_encode_signature (assembly, &rmb);
2930
2931                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2932                 g_free (name);          
2933         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2934                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2935
2936                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2937                 klass = mono_class_from_mono_type (type);
2938
2939                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2940                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2941         } else {
2942                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2943                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2944         }
2945
2946         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2947         return token;
2948 }
2949
2950 static guint32
2951 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2952 {
2953         SigBuffer buf;
2954         int i;
2955         guint32 nparams = context->method_inst->type_argc;
2956         guint32 idx;
2957
2958         if (!assembly->save)
2959                 return 0;
2960
2961         sigbuffer_init (&buf, 32);
2962         /*
2963          * FIXME: vararg, explicit_this, differenc call_conv values...
2964          */
2965         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2966         sigbuffer_add_value (&buf, nparams);
2967
2968         for (i = 0; i < nparams; i++)
2969                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2970
2971         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2972         sigbuffer_free (&buf);
2973         return idx;
2974 }
2975
2976 static guint32
2977 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2978 {
2979         MonoDynamicTable *table;
2980         guint32 *values;
2981         guint32 token, mtoken = 0, sig;
2982         MonoMethodInflated *imethod;
2983         MonoMethod *declaring;
2984
2985         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2986
2987         g_assert (method->is_inflated);
2988         imethod = (MonoMethodInflated *) method;
2989         declaring = imethod->declaring;
2990
2991         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2992         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2993
2994         if (!mono_method_signature (declaring)->generic_param_count)
2995                 return mtoken;
2996
2997         switch (mono_metadata_token_table (mtoken)) {
2998         case MONO_TABLE_MEMBERREF:
2999                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3000                 break;
3001         case MONO_TABLE_METHOD:
3002                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3003                 break;
3004         default:
3005                 g_assert_not_reached ();
3006         }
3007
3008         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3009
3010         if (assembly->save) {
3011                 alloc_table (table, table->rows + 1);
3012                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3013                 values [MONO_METHODSPEC_METHOD] = mtoken;
3014                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3015         }
3016
3017         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3018         table->next_idx ++;
3019
3020         return token;
3021 }
3022
3023 static guint32
3024 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3025 {
3026         MonoMethodInflated *imethod;
3027         guint32 token;
3028         
3029         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3030         if (token)
3031                 return token;
3032
3033         g_assert (method->is_inflated);
3034         imethod = (MonoMethodInflated *) method;
3035
3036         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3037                 token = method_encode_methodspec (assembly, method);
3038         } else {
3039                 guint32 sig = method_encode_signature (
3040                         assembly, mono_method_signature (imethod->declaring));
3041                 token = mono_image_get_memberref_token (
3042                         assembly, &method->klass->byval_arg, method->name, sig);
3043         }
3044
3045         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3046         return token;
3047 }
3048
3049 static guint32
3050 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3051 {
3052         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3053         guint32 sig, token;
3054
3055         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3056         token = mono_image_get_memberref_token (
3057                 assembly, &m->klass->byval_arg, m->name, sig);
3058
3059         return token;
3060 }
3061
3062 static guint32
3063 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3064 {
3065         MonoDynamicTable *table;
3066         MonoClass *klass;
3067         MonoType *type;
3068         guint32 *values;
3069         guint32 token;
3070         SigBuffer buf;
3071         int count, i;
3072
3073         /*
3074          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3075          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3076          * Because of this, we must not insert it into the `typeref' hash table.
3077          */
3078         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3079         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3080         if (token)
3081                 return token;
3082
3083         sigbuffer_init (&buf, 32);
3084
3085         g_assert (tb->generic_params);
3086         klass = mono_class_from_mono_type (type);
3087
3088         if (tb->generic_container)
3089                 mono_reflection_create_generic_class (tb);
3090
3091         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3092         g_assert (klass->generic_container);
3093         sigbuffer_add_value (&buf, klass->byval_arg.type);
3094         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3095
3096         count = mono_array_length (tb->generic_params);
3097         sigbuffer_add_value (&buf, count);
3098         for (i = 0; i < count; i++) {
3099                 MonoReflectionGenericParam *gparam;
3100
3101                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3102
3103                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3104         }
3105
3106         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3107
3108         if (assembly->save) {
3109                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3110                 alloc_table (table, table->rows + 1);
3111                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3112                 values [MONO_TYPESPEC_SIGNATURE] = token;
3113         }
3114         sigbuffer_free (&buf);
3115
3116         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3117         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3118         table->next_idx ++;
3119         return token;
3120 }
3121
3122 /*
3123  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3124  */
3125 static MonoType*
3126 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3127 {
3128         int i, count, len, pos;
3129         MonoType *t;
3130
3131         count = 0;
3132         if (modreq)
3133                 count += mono_array_length (modreq);
3134         if (modopt)
3135                 count += mono_array_length (modopt);
3136
3137         if (count == 0)
3138                 return mono_metadata_type_dup (NULL, type);
3139
3140         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3141         t = g_malloc (len);
3142         memcpy (t, type, MONO_SIZEOF_TYPE);
3143
3144         t->num_mods = count;
3145         pos = 0;
3146         if (modreq) {
3147                 for (i = 0; i < mono_array_length (modreq); ++i) {
3148                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3149                         t->modifiers [pos].required = 1;
3150                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3151                         pos ++;
3152                 }
3153         }
3154         if (modopt) {
3155                 for (i = 0; i < mono_array_length (modopt); ++i) {
3156                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3157                         t->modifiers [pos].required = 0;
3158                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3159                         pos ++;
3160                 }
3161         }
3162
3163         return t;
3164 }
3165
3166 static void
3167 init_type_builder_generics (MonoObject *type)
3168 {
3169         MonoReflectionTypeBuilder *tb;
3170
3171         if (!is_sre_type_builder(mono_object_class (type)))
3172                 return;
3173         tb = (MonoReflectionTypeBuilder *)type;
3174
3175         if (tb && tb->generic_container)
3176                 mono_reflection_create_generic_class (tb);
3177 }
3178
3179 static guint32
3180 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3181 {
3182         MonoDynamicTable *table;
3183         MonoClass *klass;
3184         MonoType *custom = NULL, *type;
3185         guint32 *values;
3186         guint32 token, pclass, parent, sig;
3187         gchar *name;
3188
3189         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3190         if (token)
3191                 return token;
3192
3193         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3194         name = mono_string_to_utf8 (fb->name);
3195
3196         /*FIXME this is one more layer of ugliness due how types are created.*/
3197         init_type_builder_generics (fb->type);
3198
3199         /* fb->type does not include the custom modifiers */
3200         /* FIXME: We should do this in one place when a fieldbuilder is created */
3201         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3202         if (fb->modreq || fb->modopt)
3203                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3204
3205         sig = fieldref_encode_signature (assembly, NULL, type);
3206         g_free (custom);
3207
3208         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3209         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3210         
3211         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3212         parent >>= MONO_TYPEDEFORREF_BITS;
3213
3214         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3215
3216         if (assembly->save) {
3217                 alloc_table (table, table->rows + 1);
3218                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3219                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3220                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3221                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3222         }
3223
3224         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3225         table->next_idx ++;
3226         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3227         g_free (name);
3228         return token;
3229 }
3230
3231 static guint32
3232 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3233 {
3234         SigBuffer buf;
3235         guint32 nargs;
3236         guint32 size;
3237         guint32 i, idx;
3238
3239         if (!assembly->save)
3240                 return 0;
3241
3242         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3243         g_assert (helper->type == 2);
3244
3245         if (helper->arguments)
3246                 nargs = mono_array_length (helper->arguments);
3247         else
3248                 nargs = 0;
3249
3250         size = 10 + (nargs * 10);
3251         
3252         sigbuffer_init (&buf, 32);
3253
3254         /* Encode calling convention */
3255         /* Change Any to Standard */
3256         if ((helper->call_conv & 0x03) == 0x03)
3257                 helper->call_conv = 0x01;
3258         /* explicit_this implies has_this */
3259         if (helper->call_conv & 0x40)
3260                 helper->call_conv &= 0x20;
3261
3262         if (helper->call_conv == 0) { /* Unmanaged */
3263                 idx = helper->unmanaged_call_conv - 1;
3264         } else {
3265                 /* Managed */
3266                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3267                 if (helper->call_conv & 0x02) /* varargs */
3268                         idx += 0x05;
3269         }
3270
3271         sigbuffer_add_byte (&buf, idx);
3272         sigbuffer_add_value (&buf, nargs);
3273         encode_reflection_type (assembly, helper->return_type, &buf);
3274         for (i = 0; i < nargs; ++i) {
3275                 MonoArray *modreqs = NULL;
3276                 MonoArray *modopts = NULL;
3277                 MonoReflectionType *pt;
3278
3279                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3280                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3281                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3282                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3283
3284                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3285                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3286                 encode_reflection_type (assembly, pt, &buf);
3287         }
3288         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3289         sigbuffer_free (&buf);
3290
3291         return idx;
3292 }
3293
3294 static guint32 
3295 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3296 {
3297         guint32 idx;
3298         MonoDynamicTable *table;
3299         guint32 *values;
3300
3301         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3302         idx = table->next_idx ++;
3303         table->rows ++;
3304         alloc_table (table, table->rows);
3305         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3306
3307         values [MONO_STAND_ALONE_SIGNATURE] =
3308                 mono_reflection_encode_sighelper (assembly, helper);
3309
3310         return idx;
3311 }
3312
3313 static int
3314 reflection_cc_to_file (int call_conv) {
3315         switch (call_conv & 0x3) {
3316         case 0:
3317         case 1: return MONO_CALL_DEFAULT;
3318         case 2: return MONO_CALL_VARARG;
3319         default:
3320                 g_assert_not_reached ();
3321         }
3322         return 0;
3323 }
3324 #endif /* !DISABLE_REFLECTION_EMIT */
3325
3326 typedef struct {
3327         MonoType *parent;
3328         MonoMethodSignature *sig;
3329         char *name;
3330         guint32 token;
3331 } ArrayMethod;
3332
3333 #ifndef DISABLE_REFLECTION_EMIT
3334 static guint32
3335 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3336 {
3337         guint32 nparams, i;
3338         GList *tmp;
3339         char *name;
3340         MonoMethodSignature *sig;
3341         ArrayMethod *am;
3342         MonoType *mtype;
3343
3344         name = mono_string_to_utf8 (m->name);
3345         nparams = mono_array_length (m->parameters);
3346         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3347         sig->hasthis = 1;
3348         sig->sentinelpos = -1;
3349         sig->call_convention = reflection_cc_to_file (m->call_conv);
3350         sig->param_count = nparams;
3351         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3352         mtype = mono_reflection_type_get_handle (m->parent);
3353         for (i = 0; i < nparams; ++i)
3354                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3355
3356         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3357                 am = tmp->data;
3358                 if (strcmp (name, am->name) == 0 && 
3359                                 mono_metadata_type_equal (am->parent, mtype) &&
3360                                 mono_metadata_signature_equal (am->sig, sig)) {
3361                         g_free (name);
3362                         g_free (sig);
3363                         m->table_idx = am->token & 0xffffff;
3364                         return am->token;
3365                 }
3366         }
3367         am = g_new0 (ArrayMethod, 1);
3368         am->name = name;
3369         am->sig = sig;
3370         am->parent = mtype;
3371         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3372                 method_encode_signature (assembly, sig));
3373         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3374         m->table_idx = am->token & 0xffffff;
3375         return am->token;
3376 }
3377
3378 /*
3379  * Insert into the metadata tables all the info about the TypeBuilder tb.
3380  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3381  */
3382 static void
3383 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3384 {
3385         MonoDynamicTable *table;
3386         guint *values;
3387         int i, is_object = 0, is_system = 0;
3388         char *n;
3389
3390         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3391         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3392         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3393         n = mono_string_to_utf8 (tb->name);
3394         if (strcmp (n, "Object") == 0)
3395                 is_object++;
3396         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3397         g_free (n);
3398         n = mono_string_to_utf8 (tb->nspace);
3399         if (strcmp (n, "System") == 0)
3400                 is_system++;
3401         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3402         g_free (n);
3403         if (tb->parent && !(is_system && is_object) && 
3404                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3405                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3406         } else {
3407                 values [MONO_TYPEDEF_EXTENDS] = 0;
3408         }
3409         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3410         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3411
3412         /*
3413          * if we have explicitlayout or sequentiallayouts, output data in the
3414          * ClassLayout table.
3415          */
3416         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3417                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3418                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3419                 table->rows++;
3420                 alloc_table (table, table->rows);
3421                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3422                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3423                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3424                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3425         }
3426
3427         /* handle interfaces */
3428         if (tb->interfaces) {
3429                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3430                 i = table->rows;
3431                 table->rows += mono_array_length (tb->interfaces);
3432                 alloc_table (table, table->rows);
3433                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3434                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3435                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3436                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3437                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3438                         values += MONO_INTERFACEIMPL_SIZE;
3439                 }
3440         }
3441
3442         /* handle fields */
3443         if (tb->fields) {
3444                 table = &assembly->tables [MONO_TABLE_FIELD];
3445                 table->rows += tb->num_fields;
3446                 alloc_table (table, table->rows);
3447                 for (i = 0; i < tb->num_fields; ++i)
3448                         mono_image_get_field_info (
3449                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3450         }
3451
3452         /* handle constructors */
3453         if (tb->ctors) {
3454                 table = &assembly->tables [MONO_TABLE_METHOD];
3455                 table->rows += mono_array_length (tb->ctors);
3456                 alloc_table (table, table->rows);
3457                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3458                         mono_image_get_ctor_info (domain,
3459                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3460         }
3461
3462         /* handle methods */
3463         if (tb->methods) {
3464                 table = &assembly->tables [MONO_TABLE_METHOD];
3465                 table->rows += tb->num_methods;
3466                 alloc_table (table, table->rows);
3467                 for (i = 0; i < tb->num_methods; ++i)
3468                         mono_image_get_method_info (
3469                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3470         }
3471
3472         /* Do the same with properties etc.. */
3473         if (tb->events && mono_array_length (tb->events)) {
3474                 table = &assembly->tables [MONO_TABLE_EVENT];
3475                 table->rows += mono_array_length (tb->events);
3476                 alloc_table (table, table->rows);
3477                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3478                 table->rows ++;
3479                 alloc_table (table, table->rows);
3480                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3481                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3482                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3483                 for (i = 0; i < mono_array_length (tb->events); ++i)
3484                         mono_image_get_event_info (
3485                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3486         }
3487         if (tb->properties && mono_array_length (tb->properties)) {
3488                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3489                 table->rows += mono_array_length (tb->properties);
3490                 alloc_table (table, table->rows);
3491                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3492                 table->rows ++;
3493                 alloc_table (table, table->rows);
3494                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3495                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3496                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3497                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3498                         mono_image_get_property_info (
3499                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3500         }
3501
3502         /* handle generic parameters */
3503         if (tb->generic_params) {
3504                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3505                 table->rows += mono_array_length (tb->generic_params);
3506                 alloc_table (table, table->rows);
3507                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3508                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3509
3510                         mono_image_get_generic_param_info (
3511                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3512                 }
3513         }
3514
3515         mono_image_add_decl_security (assembly, 
3516                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3517
3518         if (tb->subtypes) {
3519                 MonoDynamicTable *ntable;
3520                 
3521                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3522                 ntable->rows += mono_array_length (tb->subtypes);
3523                 alloc_table (ntable, ntable->rows);
3524                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3525
3526                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3527                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3528
3529                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3530                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3531                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3532                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3533                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3534                                 ntable->next_idx, ntable->rows);*/
3535                         values += MONO_NESTED_CLASS_SIZE;
3536                         ntable->next_idx++;
3537                 }
3538         }
3539 }
3540 #endif
3541
3542 static void
3543 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3544 {
3545         int i;
3546
3547         mono_ptr_array_append (*types, type);
3548
3549         if (!type->subtypes)
3550                 return;
3551
3552         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3553                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3554                 collect_types (types, subtype);
3555         }
3556 }
3557
3558 static gint
3559 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3560 {
3561         if ((*type1)->table_idx < (*type2)->table_idx)
3562                 return -1;
3563         else
3564                 if ((*type1)->table_idx > (*type2)->table_idx)
3565                         return 1;
3566         else
3567                 return 0;
3568 }
3569
3570 static void
3571 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3572         int i;
3573
3574         if (!pinfo)
3575                 return;
3576         for (i = 0; i < mono_array_length (pinfo); ++i) {
3577                 MonoReflectionParamBuilder *pb;
3578                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3579                 if (!pb)
3580                         continue;
3581                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3582         }
3583 }
3584
3585 static void
3586 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3587         int i;
3588         
3589         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3590         if (tb->fields) {
3591                 for (i = 0; i < tb->num_fields; ++i) {
3592                         MonoReflectionFieldBuilder* fb;
3593                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3594                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3595                 }
3596         }
3597         if (tb->events) {
3598                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3599                         MonoReflectionEventBuilder* eb;
3600                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3601                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3602                 }
3603         }
3604         if (tb->properties) {
3605                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3606                         MonoReflectionPropertyBuilder* pb;
3607                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3608                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3609                 }
3610         }
3611         if (tb->ctors) {
3612                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3613                         MonoReflectionCtorBuilder* cb;
3614                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3615                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3616                         params_add_cattrs (assembly, cb->pinfo);
3617                 }
3618         }
3619
3620         if (tb->methods) {
3621                 for (i = 0; i < tb->num_methods; ++i) {
3622                         MonoReflectionMethodBuilder* mb;
3623                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3624                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3625                         params_add_cattrs (assembly, mb->pinfo);
3626                 }
3627         }
3628
3629         if (tb->subtypes) {
3630                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3631                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3632         }
3633 }
3634
3635 static void
3636 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3637 {
3638         int i;
3639         
3640         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3641
3642         if (moduleb->global_methods) {
3643                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3644                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3645                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3646                         params_add_cattrs (assembly, mb->pinfo);
3647                 }
3648         }
3649
3650         if (moduleb->global_fields) {
3651                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3652                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3653                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3654                 }
3655         }
3656         
3657         if (moduleb->types) {
3658                 for (i = 0; i < moduleb->num_types; ++i)
3659                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3660         }
3661 }
3662
3663 static void
3664 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3665 {
3666         MonoDynamicTable *table;
3667         guint32 *values;
3668         char blob_size [6];
3669         guchar hash [20];
3670         char *b = blob_size;
3671         char *dir, *path;
3672
3673         table = &assembly->tables [MONO_TABLE_FILE];
3674         table->rows++;
3675         alloc_table (table, table->rows);
3676         values = table->values + table->next_idx * MONO_FILE_SIZE;
3677         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3678         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3679         if (module->image->dynamic) {
3680                 /* This depends on the fact that the main module is emitted last */
3681                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3682                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3683         } else {
3684                 dir = NULL;
3685                 path = g_strdup (module->image->name);
3686         }
3687         mono_sha1_get_digest_from_file (path, hash);
3688         g_free (dir);
3689         g_free (path);
3690         mono_metadata_encode_value (20, b, &b);
3691         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3692         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3693         table->next_idx ++;
3694 }
3695
3696 static void
3697 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3698 {
3699         MonoDynamicTable *table;
3700         int i;
3701
3702         table = &assembly->tables [MONO_TABLE_MODULE];
3703         mb->table_idx = table->next_idx ++;
3704         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3705         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3706         i /= 16;
3707         ++i;
3708         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3709         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3710         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3711         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3712 }
3713
3714 static guint32
3715 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3716         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3717 {
3718         MonoDynamicTable *table;
3719         guint32 *values;
3720         guint32 visib, res;
3721
3722         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3723         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3724                 return 0;
3725
3726         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3727         table->rows++;
3728         alloc_table (table, table->rows);
3729         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3730
3731         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3732         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3733         if (klass->nested_in)
3734                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3735         else
3736                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3737         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3738         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3739
3740         res = table->next_idx;
3741
3742         table->next_idx ++;
3743
3744         /* Emit nested types */
3745         if (klass->ext && klass->ext->nested_classes) {
3746                 GList *tmp;
3747
3748                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3749                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3750         }
3751
3752         return res;
3753 }
3754
3755 static void
3756 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3757         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3758 {
3759         MonoClass *klass;
3760         guint32 idx, i;
3761
3762         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3763
3764         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3765
3766         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3767                                                                                                    parent_index, assembly);
3768
3769         /* 
3770          * Emit nested types
3771          * We need to do this ourselves since klass->nested_classes is not set up.
3772          */
3773         if (tb->subtypes) {
3774                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3775                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3776         }
3777 }
3778
3779 static void
3780 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3781         guint32 module_index, MonoDynamicImage *assembly)
3782 {
3783         MonoImage *image = module->image;
3784         MonoTableInfo  *t;
3785         guint32 i;
3786
3787         t = &image->tables [MONO_TABLE_TYPEDEF];
3788
3789         for (i = 0; i < t->rows; ++i) {
3790                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3791
3792                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3793                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3794         }
3795 }
3796
3797 static void
3798 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3799 {
3800         MonoDynamicTable *table;
3801         guint32 *values;
3802         guint32 scope, scope_idx, impl, current_idx;
3803         gboolean forwarder = TRUE;
3804         gpointer iter = NULL;
3805         MonoClass *nested;
3806
3807         if (klass->nested_in) {
3808                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3809                 forwarder = FALSE;
3810         } else {
3811                 scope = resolution_scope_from_image (assembly, klass->image);
3812                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3813                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3814                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3815         }
3816
3817         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3818
3819         table->rows++;
3820         alloc_table (table, table->rows);
3821         current_idx = table->next_idx;
3822         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3823
3824         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3825         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3826         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3827         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3828         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3829
3830         table->next_idx++;
3831
3832         while ((nested = mono_class_get_nested_types (klass, &iter)))
3833                 add_exported_type (assemblyb, assembly, nested, current_idx);
3834 }
3835
3836 static void
3837 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3838 {
3839         MonoClass *klass;
3840         int i;
3841
3842         if (!assemblyb->type_forwarders)
3843                 return;
3844
3845         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3846                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3847                 MonoType *type;
3848                 if (!t)
3849                         continue;
3850
3851                 type = mono_reflection_type_get_handle (t);
3852                 g_assert (type);
3853
3854                 klass = mono_class_from_mono_type (type);
3855
3856                 add_exported_type (assemblyb, assembly, klass, 0);
3857         }
3858 }
3859
3860 #define align_pointer(base,p)\
3861         do {\
3862                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3863                 if (__diff & 3)\
3864                         (p) += 4 - (__diff & 3);\
3865         } while (0)
3866
3867 static int
3868 compare_constants (const void *a, const void *b)
3869 {
3870         const guint32 *a_values = a;
3871         const guint32 *b_values = b;
3872         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3873 }
3874
3875 static int
3876 compare_semantics (const void *a, const void *b)
3877 {
3878         const guint32 *a_values = a;
3879         const guint32 *b_values = b;
3880         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3881         if (assoc)
3882                 return assoc;
3883         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3884 }
3885
3886 static int
3887 compare_custom_attrs (const void *a, const void *b)
3888 {
3889         const guint32 *a_values = a;
3890         const guint32 *b_values = b;
3891
3892         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3893 }
3894
3895 static int
3896 compare_field_marshal (const void *a, const void *b)
3897 {
3898         const guint32 *a_values = a;
3899         const guint32 *b_values = b;
3900
3901         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3902 }
3903
3904 static int
3905 compare_nested (const void *a, const void *b)
3906 {
3907         const guint32 *a_values = a;
3908         const guint32 *b_values = b;
3909
3910         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3911 }
3912
3913 static int
3914 compare_genericparam (const void *a, const void *b)
3915 {
3916         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3917         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3918
3919         if ((*b_entry)->owner == (*a_entry)->owner)
3920                 return 
3921                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3922                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3923         else
3924                 return (*a_entry)->owner - (*b_entry)->owner;
3925 }
3926
3927 static int
3928 compare_declsecurity_attrs (const void *a, const void *b)
3929 {
3930         const guint32 *a_values = a;
3931         const guint32 *b_values = b;
3932
3933         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3934 }
3935
3936 static int
3937 compare_interface_impl (const void *a, const void *b)
3938 {
3939         const guint32 *a_values = a;
3940         const guint32 *b_values = b;
3941
3942         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3943         if (klass)
3944                 return klass;
3945
3946         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3947 }
3948
3949 static void
3950 pad_heap (MonoDynamicStream *sh)
3951 {
3952         if (sh->index & 3) {
3953                 int sz = 4 - (sh->index & 3);
3954                 memset (sh->data + sh->index, 0, sz);
3955                 sh->index += sz;
3956         }
3957 }
3958
3959 struct StreamDesc {
3960         const char *name;
3961         MonoDynamicStream *stream;
3962 };
3963
3964 /*
3965  * build_compressed_metadata() fills in the blob of data that represents the 
3966  * raw metadata as it will be saved in the PE file. The five streams are output 
3967  * and the metadata tables are comnpressed from the guint32 array representation, 
3968  * to the compressed on-disk format.
3969  */
3970 static void
3971 build_compressed_metadata (MonoDynamicImage *assembly)
3972 {
3973         MonoDynamicTable *table;
3974         int i;
3975         guint64 valid_mask = 0;
3976         guint64 sorted_mask;
3977         guint32 heapt_size = 0;
3978         guint32 meta_size = 256; /* allow for header and other stuff */
3979         guint32 table_offset;
3980         guint32 ntables = 0;
3981         guint64 *int64val;
3982         guint32 *int32val;
3983         guint16 *int16val;
3984         MonoImage *meta;
3985         unsigned char *p;
3986         struct StreamDesc stream_desc [5];
3987
3988         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3989         for (i = 0; i < assembly->gen_params->len; i++){
3990                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3991                 write_generic_param_entry (assembly, entry);
3992         }
3993
3994         stream_desc [0].name  = "#~";
3995         stream_desc [0].stream = &assembly->tstream;
3996         stream_desc [1].name  = "#Strings";
3997         stream_desc [1].stream = &assembly->sheap;
3998         stream_desc [2].name  = "#US";
3999         stream_desc [2].stream = &assembly->us;
4000         stream_desc [3].name  = "#Blob";
4001         stream_desc [3].stream = &assembly->blob;
4002         stream_desc [4].name  = "#GUID";
4003         stream_desc [4].stream = &assembly->guid;
4004         
4005         /* tables that are sorted */
4006         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4007                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4008                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4009                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4010                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4011                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4012                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4013         
4014         /* Compute table sizes */
4015         /* the MonoImage has already been created in mono_image_basic_init() */
4016         meta = &assembly->image;
4017
4018         /* sizes should be multiple of 4 */
4019         pad_heap (&assembly->blob);
4020         pad_heap (&assembly->guid);
4021         pad_heap (&assembly->sheap);
4022         pad_heap (&assembly->us);
4023
4024         /* Setup the info used by compute_sizes () */
4025         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4026         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4027         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4028
4029         meta_size += assembly->blob.index;
4030         meta_size += assembly->guid.index;
4031         meta_size += assembly->sheap.index;
4032         meta_size += assembly->us.index;
4033
4034         for (i=0; i < MONO_TABLE_NUM; ++i)
4035                 meta->tables [i].rows = assembly->tables [i].rows;
4036         
4037         for (i = 0; i < MONO_TABLE_NUM; i++){
4038                 if (meta->tables [i].rows == 0)
4039                         continue;
4040                 valid_mask |= (guint64)1 << i;
4041                 ntables ++;
4042                 meta->tables [i].row_size = mono_metadata_compute_size (
4043                         meta, i, &meta->tables [i].size_bitfield);
4044                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4045         }
4046         heapt_size += 24; /* #~ header size */
4047         heapt_size += ntables * 4;
4048         /* make multiple of 4 */
4049         heapt_size += 3;
4050         heapt_size &= ~3;
4051         meta_size += heapt_size;
4052         meta->raw_metadata = g_malloc0 (meta_size);
4053         p = (unsigned char*)meta->raw_metadata;
4054         /* the metadata signature */
4055         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4056         /* version numbers and 4 bytes reserved */
4057         int16val = (guint16*)p;
4058         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4059         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4060         p += 8;
4061         /* version string */
4062         int32val = (guint32*)p;
4063         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4064         p += 4;
4065         memcpy (p, meta->version, strlen (meta->version));
4066         p += GUINT32_FROM_LE (*int32val);
4067         align_pointer (meta->raw_metadata, p);
4068         int16val = (guint16*)p;
4069         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4070         *int16val = GUINT16_TO_LE (5); /* number of streams */
4071         p += 4;
4072
4073         /*
4074          * write the stream info.
4075          */
4076         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4077         table_offset += 3; table_offset &= ~3;
4078
4079         assembly->tstream.index = heapt_size;
4080         for (i = 0; i < 5; ++i) {
4081                 int32val = (guint32*)p;
4082                 stream_desc [i].stream->offset = table_offset;
4083                 *int32val++ = GUINT32_TO_LE (table_offset);
4084                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4085                 table_offset += GUINT32_FROM_LE (*int32val);
4086                 table_offset += 3; table_offset &= ~3;
4087                 p += 8;
4088                 strcpy ((char*)p, stream_desc [i].name);
4089                 p += strlen (stream_desc [i].name) + 1;
4090                 align_pointer (meta->raw_metadata, p);
4091         }
4092         /* 
4093          * now copy the data, the table stream header and contents goes first.
4094          */
4095         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4096         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4097         int32val = (guint32*)p;
4098         *int32val = GUINT32_TO_LE (0); /* reserved */
4099         p += 4;
4100
4101         *p++ = 2; /* version */
4102         *p++ = 0;
4103
4104         if (meta->idx_string_wide)
4105                 *p |= 0x01;
4106         if (meta->idx_guid_wide)
4107                 *p |= 0x02;
4108         if (meta->idx_blob_wide)
4109                 *p |= 0x04;
4110         ++p;
4111         *p++ = 1; /* reserved */
4112         int64val = (guint64*)p;
4113         *int64val++ = GUINT64_TO_LE (valid_mask);
4114         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4115         p += 16;
4116         int32val = (guint32*)p;
4117         for (i = 0; i < MONO_TABLE_NUM; i++){
4118                 if (meta->tables [i].rows == 0)
4119                         continue;
4120                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4121         }
4122         p = (unsigned char*)int32val;
4123
4124         /* sort the tables that still need sorting */
4125         table = &assembly->tables [MONO_TABLE_CONSTANT];
4126         if (table->rows)
4127                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4128         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4129         if (table->rows)
4130                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4131         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4132         if (table->rows)
4133                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4134         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4135         if (table->rows)
4136                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4137         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4138         if (table->rows)
4139                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4140         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4141         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4142         if (table->rows)
4143                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4144         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4145         if (table->rows)
4146                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4147
4148         /* compress the tables */
4149         for (i = 0; i < MONO_TABLE_NUM; i++){
4150                 int row, col;
4151                 guint32 *values;
4152                 guint32 bitfield = meta->tables [i].size_bitfield;
4153                 if (!meta->tables [i].rows)
4154                         continue;
4155                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4156                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4157                 meta->tables [i].base = (char*)p;
4158                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4159                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4160                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4161                                 switch (mono_metadata_table_size (bitfield, col)) {
4162                                 case 1:
4163                                         *p++ = values [col];
4164                                         break;
4165                                 case 2:
4166                                         *p++ = values [col] & 0xff;
4167                                         *p++ = (values [col] >> 8) & 0xff;
4168                                         break;
4169                                 case 4:
4170                                         *p++ = values [col] & 0xff;
4171                                         *p++ = (values [col] >> 8) & 0xff;
4172                                         *p++ = (values [col] >> 16) & 0xff;
4173                                         *p++ = (values [col] >> 24) & 0xff;
4174                                         break;
4175                                 default:
4176                                         g_assert_not_reached ();
4177                                 }
4178                         }
4179                 }
4180                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4181         }
4182         
4183         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4184         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4185         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4186         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4187         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4188
4189         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4190 }
4191
4192 /*
4193  * Some tables in metadata need to be sorted according to some criteria, but
4194  * when methods and fields are first created with reflection, they may be assigned a token
4195  * that doesn't correspond to the final token they will get assigned after the sorting.
4196  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4197  * with the reflection objects that represent them. Once all the tables are set up, the 
4198  * reflection objects will contains the correct table index. fixup_method() will fixup the
4199  * tokens for the method with ILGenerator @ilgen.
4200  */
4201 static void
4202 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4203 {
4204         guint32 code_idx = GPOINTER_TO_UINT (value);
4205         MonoReflectionILTokenInfo *iltoken;
4206         MonoReflectionFieldBuilder *field;
4207         MonoReflectionCtorBuilder *ctor;
4208         MonoReflectionMethodBuilder *method;
4209         MonoReflectionTypeBuilder *tb;
4210         MonoReflectionArrayMethod *am;
4211         guint32 i, idx = 0;
4212         unsigned char *target;
4213
4214         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4215                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4216                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4217                 switch (target [3]) {
4218                 case MONO_TABLE_FIELD:
4219                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4220                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4221                                 idx = field->table_idx;
4222                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4223                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4224                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4225                         } else {
4226                                 g_assert_not_reached ();
4227                         }
4228                         break;
4229                 case MONO_TABLE_METHOD:
4230                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4231                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4232                                 idx = method->table_idx;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4234                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4235                                 idx = ctor->table_idx;
4236                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4237                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4238                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4239                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4240                         } else {
4241                                 g_assert_not_reached ();
4242                         }
4243                         break;
4244                 case MONO_TABLE_TYPEDEF:
4245                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4246                                 g_assert_not_reached ();
4247                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4248                         idx = tb->table_idx;
4249                         break;
4250                 case MONO_TABLE_MEMBERREF:
4251                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4252                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4253                                 idx = am->table_idx;
4254                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4255                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4256                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4257                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4258                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4259                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4260                                 continue;
4261                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4262                                 continue;
4263                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4264                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4265                                 g_assert (is_field_on_inst (f));
4266                                 continue;
4267                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4268                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4269                                 continue;
4270                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4273                                 continue;
4274                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4275                                 continue;
4276                         } else {
4277                                 g_assert_not_reached ();
4278                         }
4279                         break;
4280                 case MONO_TABLE_METHODSPEC:
4281                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4282                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4283                                 g_assert (mono_method_signature (m)->generic_param_count);
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4286                                 continue;
4287                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4288                                 continue;
4289                         } else {
4290                                 g_assert_not_reached ();
4291                         }
4292                         break;
4293                 default:
4294                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4295                 }
4296                 target [0] = idx & 0xff;
4297                 target [1] = (idx >> 8) & 0xff;
4298                 target [2] = (idx >> 16) & 0xff;
4299         }
4300 }
4301
4302 /*
4303  * fixup_cattrs:
4304  *
4305  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4306  * value is not known when the table is emitted.
4307  */
4308 static void
4309 fixup_cattrs (MonoDynamicImage *assembly)
4310 {
4311         MonoDynamicTable *table;
4312         guint32 *values;
4313         guint32 type, i, idx, token;
4314         MonoObject *ctor;
4315
4316         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4317
4318         for (i = 0; i < table->rows; ++i) {
4319                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4320
4321                 type = values [MONO_CUSTOM_ATTR_TYPE];
4322                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4323                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4324                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4325                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4326                         g_assert (ctor);
4327
4328                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4329                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4330                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4331                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4332                         }
4333                 }
4334         }
4335 }
4336
4337 static void
4338 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4339 {
4340         MonoDynamicTable *table;
4341         guint32 *values;
4342
4343         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4344         table->rows++;
4345         alloc_table (table, table->rows);
4346         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4347         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4348         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4349         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4350         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4351         table->next_idx++;
4352 }
4353
4354 static void
4355 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4356 {
4357         MonoDynamicTable *table;
4358         guint32 *values;
4359         char blob_size [6];
4360         guchar hash [20];
4361         char *b = blob_size;
4362         char *name, *sname;
4363         guint32 idx, offset;
4364
4365         if (rsrc->filename) {
4366                 name = mono_string_to_utf8 (rsrc->filename);
4367                 sname = g_path_get_basename (name);
4368         
4369                 table = &assembly->tables [MONO_TABLE_FILE];
4370                 table->rows++;
4371                 alloc_table (table, table->rows);
4372                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4373                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4374                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4375                 g_free (sname);
4376
4377                 mono_sha1_get_digest_from_file (name, hash);
4378                 mono_metadata_encode_value (20, b, &b);
4379                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4380                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4381                 g_free (name);
4382                 idx = table->next_idx++;
4383                 rsrc->offset = 0;
4384                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4385         } else {
4386                 char sizebuf [4];
4387                 char *data;
4388                 guint len;
4389                 if (rsrc->data) {
4390                         data = mono_array_addr (rsrc->data, char, 0);
4391                         len = mono_array_length (rsrc->data);
4392                 } else {
4393                         data = NULL;
4394                         len = 0;
4395                 }
4396                 offset = len;
4397                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4398                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4399                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4400                 mono_image_add_stream_data (&assembly->resources, data, len);
4401
4402                 if (!mb->is_main)
4403                         /* 
4404                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4405                          * the main module, but that needs to reference the FILE table
4406                          * which isn't emitted yet.
4407                          */
4408                         return;
4409                 else
4410                         idx = 0;
4411         }
4412
4413         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4414 }
4415
4416 static void
4417 set_version_from_string (MonoString *version, guint32 *values)
4418 {
4419         gchar *ver, *p, *str;
4420         guint32 i;
4421         
4422         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4423         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4424         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4425         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4426         if (!version)
4427                 return;
4428         ver = str = mono_string_to_utf8 (version);
4429         for (i = 0; i < 4; ++i) {
4430                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4431                 switch (*p) {
4432                 case '.':
4433                         p++;
4434                         break;
4435                 case '*':
4436                         /* handle Revision and Build */
4437                         p++;
4438                         break;
4439                 }
4440                 ver = p;
4441         }
4442         g_free (str);
4443 }
4444
4445 static guint32
4446 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4447         gsize len;
4448         guint32 token = 0;
4449         char blob_size [6];
4450         char *b = blob_size;
4451
4452         if (!pkey)
4453                 return token;
4454
4455         len = mono_array_length (pkey);
4456         mono_metadata_encode_value (len, b, &b);
4457         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4458         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4459
4460         assembly->public_key = g_malloc (len);
4461         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4462         assembly->public_key_len = len;
4463
4464         /* Special case: check for ECMA key (16 bytes) */
4465         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4466                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4467                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4468         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4469                 /* minimum key size (in 2.0) is 384 bits */
4470                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4471         } else {
4472                 /* FIXME - verifier */
4473                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4474                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4475         }
4476         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4477
4478         return token;
4479 }
4480
4481 static void
4482 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4483 {
4484         MonoDynamicTable *table;
4485         MonoDynamicImage *assembly;
4486         MonoReflectionAssemblyBuilder *assemblyb;
4487         MonoDomain *domain;
4488         guint32 *values;
4489         int i;
4490         guint32 module_index;
4491
4492         assemblyb = moduleb->assemblyb;
4493         assembly = moduleb->dynamic_image;
4494         domain = mono_object_domain (assemblyb);
4495
4496         /* Emit ASSEMBLY table */
4497         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4498         alloc_table (table, 1);
4499         values = table->values + MONO_ASSEMBLY_SIZE;
4500         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4501         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4502         if (assemblyb->culture) {
4503                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4504         } else {
4505                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4506         }
4507         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4508         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4509         set_version_from_string (assemblyb->version, values);
4510
4511         /* Emit FILE + EXPORTED_TYPE table */
4512         module_index = 0;
4513         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4514                 int j;
4515                 MonoReflectionModuleBuilder *file_module = 
4516                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4517                 if (file_module != moduleb) {
4518                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4519                         module_index ++;
4520                         if (file_module->types) {
4521                                 for (j = 0; j < file_module->num_types; ++j) {
4522                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4523                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4524                                 }
4525                         }
4526                 }
4527         }
4528         if (assemblyb->loaded_modules) {
4529                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4530                         MonoReflectionModule *file_module = 
4531                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4532                         mono_image_fill_file_table (domain, file_module, assembly);
4533                         module_index ++;
4534                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4535                 }
4536         }
4537         if (assemblyb->type_forwarders)
4538                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4539
4540         /* Emit MANIFESTRESOURCE table */
4541         module_index = 0;
4542         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4543                 int j;
4544                 MonoReflectionModuleBuilder *file_module = 
4545                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4546                 /* The table for the main module is emitted later */
4547                 if (file_module != moduleb) {
4548                         module_index ++;
4549                         if (file_module->resources) {
4550                                 int len = mono_array_length (file_module->resources);
4551                                 for (j = 0; j < len; ++j) {
4552                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4553                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4554                                 }
4555                         }
4556                 }
4557         }               
4558 }
4559
4560 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4561
4562 /*
4563  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4564  * for the modulebuilder @moduleb.
4565  * At the end of the process, method and field tokens are fixed up and the 
4566  * on-disk compressed metadata representation is created.
4567  */
4568 void
4569 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4570 {
4571         MonoDynamicTable *table;
4572         MonoDynamicImage *assembly;
4573         MonoReflectionAssemblyBuilder *assemblyb;
4574         MonoDomain *domain;
4575         MonoPtrArray types;
4576         guint32 *values;
4577         int i, j;
4578
4579         assemblyb = moduleb->assemblyb;
4580         assembly = moduleb->dynamic_image;
4581         domain = mono_object_domain (assemblyb);
4582
4583         if (assembly->text_rva)
4584                 return;
4585
4586         assembly->text_rva = START_TEXT_RVA;
4587
4588         if (moduleb->is_main) {
4589                 mono_image_emit_manifest (moduleb);
4590         }
4591
4592         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4593         table->rows = 1; /* .<Module> */
4594         table->next_idx++;
4595         alloc_table (table, table->rows);
4596         /*
4597          * Set the first entry.
4598          */
4599         values = table->values + table->columns;
4600         values [MONO_TYPEDEF_FLAGS] = 0;
4601         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4602         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4603         values [MONO_TYPEDEF_EXTENDS] = 0;
4604         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4605         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4606
4607         /* 
4608          * handle global methods 
4609          * FIXME: test what to do when global methods are defined in multiple modules.
4610          */
4611         if (moduleb->global_methods) {
4612                 table = &assembly->tables [MONO_TABLE_METHOD];
4613                 table->rows += mono_array_length (moduleb->global_methods);
4614                 alloc_table (table, table->rows);
4615                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4616                         mono_image_get_method_info (
4617                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4618         }
4619         if (moduleb->global_fields) {
4620                 table = &assembly->tables [MONO_TABLE_FIELD];
4621                 table->rows += mono_array_length (moduleb->global_fields);
4622                 alloc_table (table, table->rows);
4623                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4624                         mono_image_get_field_info (
4625                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4626         }
4627
4628         table = &assembly->tables [MONO_TABLE_MODULE];
4629         alloc_table (table, 1);
4630         mono_image_fill_module_table (domain, moduleb, assembly);
4631
4632         /* Collect all types into a list sorted by their table_idx */
4633         mono_ptr_array_init (types, moduleb->num_types);
4634
4635         if (moduleb->types)
4636                 for (i = 0; i < moduleb->num_types; ++i) {
4637                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4638                         collect_types (&types, type);
4639                 }
4640
4641         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4642         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4643         table->rows += mono_ptr_array_size (types);
4644         alloc_table (table, table->rows);
4645
4646         /*
4647          * Emit type names + namespaces at one place inside the string heap,
4648          * so load_class_names () needs to touch fewer pages.
4649          */
4650         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4651                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4652                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4653         }
4654         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4655                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4656                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4657         }
4658
4659         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4660                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4661                 mono_image_get_type_info (domain, type, assembly);
4662         }
4663
4664         /* 
4665          * table->rows is already set above and in mono_image_fill_module_table.
4666          */
4667         /* add all the custom attributes at the end, once all the indexes are stable */
4668         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4669
4670         /* CAS assembly permissions */
4671         if (assemblyb->permissions_minimum)
4672                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4673         if (assemblyb->permissions_optional)
4674                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4675         if (assemblyb->permissions_refused)
4676                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4677
4678         module_add_cattrs (assembly, moduleb);
4679
4680         /* fixup tokens */
4681         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4682
4683         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4684          * the final tokens and don't need another fixup pass. */
4685
4686         if (moduleb->global_methods) {
4687                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4688                         MonoReflectionMethodBuilder *mb = mono_array_get (
4689                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4690                         mono_image_add_methodimpl (assembly, mb);
4691                 }
4692         }
4693
4694         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4695                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4696                 if (type->methods) {
4697                         for (j = 0; j < type->num_methods; ++j) {
4698                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4699                                         type->methods, MonoReflectionMethodBuilder*, j);
4700
4701                                 mono_image_add_methodimpl (assembly, mb);
4702                         }
4703                 }
4704         }
4705
4706         mono_ptr_array_destroy (types);
4707
4708         fixup_cattrs (assembly);
4709 }
4710
4711 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4712
4713 void
4714 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4715 {
4716         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4717 }
4718
4719 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4720
4721
4722 typedef struct {
4723         guint32 import_lookup_table;
4724         guint32 timestamp;
4725         guint32 forwarder;
4726         guint32 name_rva;
4727         guint32 import_address_table_rva;
4728 } MonoIDT;
4729
4730 typedef struct {
4731         guint32 name_rva;
4732         guint32 flags;
4733 } MonoILT;
4734
4735 #ifndef DISABLE_REFLECTION_EMIT
4736
4737 /*
4738  * mono_image_insert_string:
4739  * @module: module builder object
4740  * @str: a string
4741  *
4742  * Insert @str into the user string stream of @module.
4743  */
4744 guint32
4745 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4746 {
4747         MonoDynamicImage *assembly;
4748         guint32 idx;
4749         char buf [16];
4750         char *b = buf;
4751         
4752         MONO_ARCH_SAVE_REGS;
4753
4754         if (!module->dynamic_image)
4755                 mono_image_module_basic_init (module);
4756
4757         assembly = module->dynamic_image;
4758         
4759         if (assembly->save) {
4760                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4761                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4762 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4763         {
4764                 char *swapped = g_malloc (2 * mono_string_length (str));
4765                 const char *p = (const char*)mono_string_chars (str);
4766
4767                 swap_with_size (swapped, p, 2, mono_string_length (str));
4768                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4769                 g_free (swapped);
4770         }
4771 #else
4772                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4773 #endif
4774                 mono_image_add_stream_data (&assembly->us, "", 1);
4775         } else {
4776                 idx = assembly->us.index ++;
4777         }
4778
4779         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4780
4781         return MONO_TOKEN_STRING | idx;
4782 }
4783
4784 guint32
4785 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4786 {
4787         MonoClass *klass;
4788         guint32 token = 0;
4789         MonoMethodSignature *sig;
4790
4791         klass = obj->vtable->klass;
4792         if (strcmp (klass->name, "MonoMethod") == 0) {
4793                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4794                 MonoMethodSignature *old;
4795                 guint32 sig_token, parent;
4796                 int nargs, i;
4797
4798                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4799
4800                 nargs = mono_array_length (opt_param_types);
4801                 old = mono_method_signature (method);
4802                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4803
4804                 sig->hasthis = old->hasthis;
4805                 sig->explicit_this = old->explicit_this;
4806                 sig->call_convention = old->call_convention;
4807                 sig->generic_param_count = old->generic_param_count;
4808                 sig->param_count = old->param_count + nargs;
4809                 sig->sentinelpos = old->param_count;
4810                 sig->ret = old->ret;
4811
4812                 for (i = 0; i < old->param_count; i++)
4813                         sig->params [i] = old->params [i];
4814
4815                 for (i = 0; i < nargs; i++) {
4816                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4817                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4818                 }
4819
4820                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4821                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4822                 parent >>= MONO_TYPEDEFORREF_BITS;
4823
4824                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4825                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4826
4827                 sig_token = method_encode_signature (assembly, sig);
4828                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4829         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4830                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4831                 ReflectionMethodBuilder rmb;
4832                 guint32 parent, sig_token;
4833                 int nopt_args, nparams, ngparams, i;
4834                 char *name;
4835
4836                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4837                 rmb.opt_types = opt_param_types;
4838                 nopt_args = mono_array_length (opt_param_types);
4839
4840                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4841                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4842                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4843
4844                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4845                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4846                 sig->call_convention = rmb.call_conv;
4847                 sig->generic_param_count = ngparams;
4848                 sig->param_count = nparams + nopt_args;
4849                 sig->sentinelpos = nparams;
4850                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4851
4852                 for (i = 0; i < nparams; i++) {
4853                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4854                         sig->params [i] = mono_reflection_type_get_handle (rt);
4855                 }
4856
4857                 for (i = 0; i < nopt_args; i++) {
4858                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4859                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4860                 }
4861
4862                 sig_token = method_builder_encode_signature (assembly, &rmb);
4863
4864                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4865                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4866
4867                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4868                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4869
4870                 name = mono_string_to_utf8 (rmb.name);
4871                 token = mono_image_get_varargs_method_token (
4872                         assembly, parent, name, sig_token);
4873                 g_free (name);
4874         } else {
4875                 g_error ("requested method token for %s\n", klass->name);
4876         }
4877
4878         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4879         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4880         return token;
4881 }
4882
4883 /*
4884  * mono_image_create_token:
4885  * @assembly: a dynamic assembly
4886  * @obj:
4887  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4888  *
4889  * Get a token to insert in the IL code stream for the given MemberInfo.
4890  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4891  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4892  * entry.
4893  */
4894 guint32
4895 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4896                                                  gboolean create_open_instance, gboolean register_token)
4897 {
4898         MonoClass *klass;
4899         guint32 token = 0;
4900
4901         klass = obj->vtable->klass;
4902
4903         /* Check for user defined reflection objects */
4904         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4905         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4906                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4907
4908         if (strcmp (klass->name, "MethodBuilder") == 0) {
4909                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4910                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4911
4912                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4913                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4914                 else
4915                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4916                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4917         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4918                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4919                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4920
4921                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4922                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4923                 else
4924                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4925                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4926         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4927                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4928                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4929                 if (tb->generic_params) {
4930                         token = mono_image_get_generic_field_token (assembly, fb);
4931                 } else {
4932                         if ((tb->module->dynamic_image == assembly)) {
4933                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4934                         } else {
4935                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4936                         }
4937                 }
4938         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4939                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4940                 if (create_open_instance && tb->generic_params) {
4941                         MonoType *type;
4942                         init_type_builder_generics (obj);
4943                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4944                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4945                         token = mono_metadata_token_from_dor (token);
4946                 } else if (tb->module->dynamic_image == assembly) {
4947                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4948                 } else {
4949                         MonoType *type;
4950                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4951                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4952                 }
4953         } else if (strcmp (klass->name, "MonoType") == 0) {
4954                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4955                 MonoClass *mc = mono_class_from_mono_type (type);
4956                 token = mono_metadata_token_from_dor (
4957                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4958         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4959                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4960                 token = mono_metadata_token_from_dor (
4961                         mono_image_typedef_or_ref (assembly, type));
4962         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4963                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4964                 token = mono_metadata_token_from_dor (
4965                         mono_image_typedef_or_ref (assembly, type));
4966         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4967                    strcmp (klass->name, "MonoMethod") == 0 ||
4968                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4969                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4970                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4971                 if (m->method->is_inflated) {
4972                         if (create_open_instance)
4973                                 token = mono_image_get_methodspec_token (assembly, m->method);
4974                         else
4975                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4976                 } else if ((m->method->klass->image == &assembly->image) &&
4977                          !m->method->klass->generic_class) {
4978                         static guint32 method_table_idx = 0xffffff;
4979                         if (m->method->klass->wastypebuilder) {
4980                                 /* we use the same token as the one that was assigned
4981                                  * to the Methodbuilder.
4982                                  * FIXME: do the equivalent for Fields.
4983                                  */
4984                                 token = m->method->token;
4985                         } else {
4986                                 /*
4987                                  * Each token should have a unique index, but the indexes are
4988                                  * assigned by managed code, so we don't know about them. An
4989                                  * easy solution is to count backwards...
4990                                  */
4991                                 method_table_idx --;
4992                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4993                         }
4994                 } else {
4995                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4996                 }
4997                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4998         } else if (strcmp (klass->name, "MonoField") == 0) {
4999                 MonoReflectionField *f = (MonoReflectionField *)obj;
5000                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5001                         static guint32 field_table_idx = 0xffffff;
5002                         field_table_idx --;
5003                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5004                 } else {
5005                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5006                 }
5007                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5008         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5009                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5010                 token = mono_image_get_array_token (assembly, m);
5011         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5012                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5013                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5014         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5015                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5016                 token = mono_metadata_token_from_dor (
5017                         mono_image_typedef_or_ref (assembly, type));
5018         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5019                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5020                 token = mono_image_get_field_on_inst_token (assembly, f);
5021         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5022                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5023                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5024         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5025                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5026                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5027         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5028                 MonoReflectionType *type = (MonoReflectionType *)obj;
5029                 token = mono_metadata_token_from_dor (
5030                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5031         } else {
5032                 g_error ("requested token for %s\n", klass->name);
5033         }
5034
5035         if (register_token)
5036                 mono_image_register_token (assembly, token, obj);
5037
5038         return token;
5039 }
5040
5041 /*
5042  * mono_image_register_token:
5043  *
5044  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5045  * the Module.ResolveXXXToken () methods to work.
5046  */
5047 void
5048 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5049 {
5050         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5051         if (prev) {
5052                 /* There could be multiple MethodInfo objects with the same token */
5053                 //g_assert (prev == obj);
5054         } else {
5055                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5056         }
5057 }
5058
5059 static MonoDynamicImage*
5060 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5061 {
5062         static const guchar entrycode [16] = {0xff, 0x25, 0};
5063         MonoDynamicImage *image;
5064         int i;
5065
5066         const char *version;
5067
5068         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5069                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5070         else
5071                 version = mono_get_runtime_info ()->runtime_version;
5072
5073 #if HAVE_BOEHM_GC
5074         /* The MonoGHashTable's need GC tracking */
5075         image = GC_MALLOC (sizeof (MonoDynamicImage));
5076 #else
5077         image = g_new0 (MonoDynamicImage, 1);
5078 #endif
5079         
5080         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5081         
5082         /*g_print ("created image %p\n", image);*/
5083         /* keep in sync with image.c */
5084         image->image.name = assembly_name;
5085         image->image.assembly_name = image->image.name; /* they may be different */
5086         image->image.module_name = module_name;
5087         image->image.version = g_strdup (version);
5088         image->image.md_version_major = 1;
5089         image->image.md_version_minor = 1;
5090         image->image.dynamic = TRUE;
5091
5092         image->image.references = g_new0 (MonoAssembly*, 1);
5093         image->image.references [0] = NULL;
5094
5095         mono_image_init (&image->image);
5096
5097         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5098         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5099         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5100         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5101         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5102         image->handleref = g_hash_table_new (NULL, NULL);
5103         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5104         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5105         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5106         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5107         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5108         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5109         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5110         image->gen_params = g_ptr_array_new ();
5111
5112         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5113         string_heap_init (&image->sheap);
5114         mono_image_add_stream_data (&image->us, "", 1);
5115         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5116         /* import tables... */
5117         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5118         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5119         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5120         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5121         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5122         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5123         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5124         stream_data_align (&image->code);
5125
5126         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5127
5128         for (i=0; i < MONO_TABLE_NUM; ++i) {
5129                 image->tables [i].next_idx = 1;
5130                 image->tables [i].columns = table_sizes [i];
5131         }
5132
5133         image->image.assembly = (MonoAssembly*)assembly;
5134         image->run = assembly->run;
5135         image->save = assembly->save;
5136         image->pe_kind = 0x1; /* ILOnly */
5137         image->machine = 0x14c; /* I386 */
5138         
5139         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5140
5141         return image;
5142 }
5143 #endif
5144
5145 static void
5146 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5147 {
5148         g_free (key);
5149 }
5150
5151 void
5152 mono_dynamic_image_free (MonoDynamicImage *image)
5153 {
5154         MonoDynamicImage *di = image;
5155         GList *list;
5156         int i;
5157
5158         if (di->methodspec)
5159                 mono_g_hash_table_destroy (di->methodspec);
5160         if (di->typespec)
5161                 g_hash_table_destroy (di->typespec);
5162         if (di->typeref)
5163                 g_hash_table_destroy (di->typeref);
5164         if (di->handleref)
5165                 g_hash_table_destroy (di->handleref);
5166         if (di->handleref_managed)
5167                 mono_g_hash_table_destroy (di->handleref_managed);
5168         if (di->tokens)
5169                 mono_g_hash_table_destroy (di->tokens);
5170         if (di->generic_def_objects)
5171                 mono_g_hash_table_destroy (di->generic_def_objects);
5172         if (di->blob_cache) {
5173                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5174                 g_hash_table_destroy (di->blob_cache);
5175         }
5176         if (di->standalonesig_cache)
5177                 g_hash_table_destroy (di->standalonesig_cache);
5178         for (list = di->array_methods; list; list = list->next) {
5179                 ArrayMethod *am = (ArrayMethod *)list->data;
5180                 g_free (am->sig);
5181                 g_free (am->name);
5182                 g_free (am);
5183         }
5184         g_list_free (di->array_methods);
5185         if (di->gen_params) {
5186                 for (i = 0; i < di->gen_params->len; i++) {
5187                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5188                         mono_gc_deregister_root ((char*) &entry->gparam);
5189                         g_free (entry);
5190                 }
5191                 g_ptr_array_free (di->gen_params, TRUE);
5192         }
5193         if (di->token_fixups)
5194                 mono_g_hash_table_destroy (di->token_fixups);
5195         if (di->method_to_table_idx)
5196                 g_hash_table_destroy (di->method_to_table_idx);
5197         if (di->field_to_table_idx)
5198                 g_hash_table_destroy (di->field_to_table_idx);
5199         if (di->method_aux_hash)
5200                 g_hash_table_destroy (di->method_aux_hash);
5201         if (di->vararg_aux_hash)
5202                 g_hash_table_destroy (di->vararg_aux_hash);
5203         g_free (di->strong_name);
5204         g_free (di->win32_res);
5205         if (di->public_key)
5206                 g_free (di->public_key);
5207
5208         /*g_print ("string heap destroy for image %p\n", di);*/
5209         mono_dynamic_stream_reset (&di->sheap);
5210         mono_dynamic_stream_reset (&di->code);
5211         mono_dynamic_stream_reset (&di->resources);
5212         mono_dynamic_stream_reset (&di->us);
5213         mono_dynamic_stream_reset (&di->blob);
5214         mono_dynamic_stream_reset (&di->tstream);
5215         mono_dynamic_stream_reset (&di->guid);
5216         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5217                 g_free (di->tables [i].values);
5218         }
5219 }       
5220
5221 #ifndef DISABLE_REFLECTION_EMIT
5222
5223 /*
5224  * mono_image_basic_init:
5225  * @assembly: an assembly builder object
5226  *
5227  * Create the MonoImage that represents the assembly builder and setup some
5228  * of the helper hash table and the basic metadata streams.
5229  */
5230 void
5231 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5232 {
5233         MonoDynamicAssembly *assembly;
5234         MonoDynamicImage *image;
5235         MonoDomain *domain = mono_object_domain (assemblyb);
5236         
5237         MONO_ARCH_SAVE_REGS;
5238
5239         if (assemblyb->dynamic_assembly)
5240                 return;
5241
5242 #if HAVE_BOEHM_GC
5243         /* assembly->assembly.image might be GC allocated */
5244         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5245 #else
5246         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5247 #endif
5248
5249         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5250         
5251         assembly->assembly.ref_count = 1;
5252         assembly->assembly.dynamic = TRUE;
5253         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5254         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5255         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5256         if (assemblyb->culture)
5257                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5258         else
5259                 assembly->assembly.aname.culture = g_strdup ("");
5260
5261         if (assemblyb->version) {
5262                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5263                         char **version = g_strsplit (vstr, ".", 4);
5264                         char **parts = version;
5265                         assembly->assembly.aname.major = atoi (*parts++);
5266                         assembly->assembly.aname.minor = atoi (*parts++);
5267                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5268                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5269
5270                         g_strfreev (version);
5271                         g_free (vstr);
5272         } else {
5273                         assembly->assembly.aname.major = 0;
5274                         assembly->assembly.aname.minor = 0;
5275                         assembly->assembly.aname.build = 0;
5276                         assembly->assembly.aname.revision = 0;
5277         }
5278
5279         assembly->run = assemblyb->access != 2;
5280         assembly->save = assemblyb->access != 1;
5281         assembly->domain = domain;
5282
5283         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5284         image->initial_image = TRUE;
5285         assembly->assembly.aname.name = image->image.name;
5286         assembly->assembly.image = &image->image;
5287         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5288                 /* -1 to correct for the trailing NULL byte */
5289                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5290                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5291                 }
5292                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5293         }
5294
5295         mono_domain_assemblies_lock (domain);
5296         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5297         mono_domain_assemblies_unlock (domain);
5298
5299         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5300         
5301         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5302         
5303         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5304 }
5305
5306 #endif /* !DISABLE_REFLECTION_EMIT */
5307
5308 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5309
5310 static int
5311 calc_section_size (MonoDynamicImage *assembly)
5312 {
5313         int nsections = 0;
5314
5315         /* alignment constraints */
5316         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5317         g_assert ((assembly->code.index % 4) == 0);
5318         assembly->meta_size += 3;
5319         assembly->meta_size &= ~3;
5320         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5321         g_assert ((assembly->resources.index % 4) == 0);
5322
5323         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5324         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5325         nsections++;
5326
5327         if (assembly->win32_res) {
5328                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5329
5330                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5331                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5332                 nsections++;
5333         }
5334
5335         assembly->sections [MONO_SECTION_RELOC].size = 12;
5336         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5337         nsections++;
5338
5339         return nsections;
5340 }
5341
5342 typedef struct {
5343         guint32 id;
5344         guint32 offset;
5345         GSList *children;
5346         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5347 } ResTreeNode;
5348
5349 static int
5350 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5351 {
5352         ResTreeNode *t1 = (ResTreeNode*)a;
5353         ResTreeNode *t2 = (ResTreeNode*)b;
5354
5355         return t1->id - t2->id;
5356 }
5357
5358 /*
5359  * resource_tree_create:
5360  *
5361  *  Organize the resources into a resource tree.
5362  */
5363 static ResTreeNode *
5364 resource_tree_create (MonoArray *win32_resources)
5365 {
5366         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5367         GSList *l;
5368         int i;
5369
5370         tree = g_new0 (ResTreeNode, 1);
5371         
5372         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5373                 MonoReflectionWin32Resource *win32_res =
5374                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5375
5376                 /* Create node */
5377
5378                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5379                 lang_node = g_new0 (ResTreeNode, 1);
5380                 lang_node->id = win32_res->lang_id;
5381                 lang_node->win32_res = win32_res;
5382
5383                 /* Create type node if neccesary */
5384                 type_node = NULL;
5385                 for (l = tree->children; l; l = l->next)
5386                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5387                                 type_node = (ResTreeNode*)l->data;
5388                                 break;
5389                         }
5390
5391                 if (!type_node) {
5392                         type_node = g_new0 (ResTreeNode, 1);
5393                         type_node->id = win32_res->res_type;
5394
5395                         /* 
5396                          * The resource types have to be sorted otherwise
5397                          * Windows Explorer can't display the version information.
5398                          */
5399                         tree->children = g_slist_insert_sorted (tree->children, 
5400                                 type_node, resource_tree_compare_by_id);
5401                 }
5402
5403                 /* Create res node if neccesary */
5404                 res_node = NULL;
5405                 for (l = type_node->children; l; l = l->next)
5406                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5407                                 res_node = (ResTreeNode*)l->data;
5408                                 break;
5409                         }
5410
5411                 if (!res_node) {
5412                         res_node = g_new0 (ResTreeNode, 1);
5413                         res_node->id = win32_res->res_id;
5414                         type_node->children = g_slist_append (type_node->children, res_node);
5415                 }
5416
5417                 res_node->children = g_slist_append (res_node->children, lang_node);
5418         }
5419
5420         return tree;
5421 }
5422
5423 /*
5424  * resource_tree_encode:
5425  * 
5426  *   Encode the resource tree into the format used in the PE file.
5427  */
5428 static void
5429 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5430 {
5431         char *entries;
5432         MonoPEResourceDir dir;
5433         MonoPEResourceDirEntry dir_entry;
5434         MonoPEResourceDataEntry data_entry;
5435         GSList *l;
5436         guint32 res_id_entries;
5437
5438         /*
5439          * For the format of the resource directory, see the article
5440          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5441          * Matt Pietrek
5442          */
5443
5444         memset (&dir, 0, sizeof (dir));
5445         memset (&dir_entry, 0, sizeof (dir_entry));
5446         memset (&data_entry, 0, sizeof (data_entry));
5447
5448         g_assert (sizeof (dir) == 16);
5449         g_assert (sizeof (dir_entry) == 8);
5450         g_assert (sizeof (data_entry) == 16);
5451
5452         node->offset = p - begin;
5453
5454         /* IMAGE_RESOURCE_DIRECTORY */
5455         res_id_entries = g_slist_length (node->children);
5456         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5457
5458         memcpy (p, &dir, sizeof (dir));
5459         p += sizeof (dir);
5460
5461         /* Reserve space for entries */
5462         entries = p;
5463         p += sizeof (dir_entry) * res_id_entries;
5464
5465         /* Write children */
5466         for (l = node->children; l; l = l->next) {
5467                 ResTreeNode *child = (ResTreeNode*)l->data;
5468
5469                 if (child->win32_res) {
5470                         guint32 size;
5471
5472                         child->offset = p - begin;
5473
5474                         /* IMAGE_RESOURCE_DATA_ENTRY */
5475                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5476                         size = mono_array_length (child->win32_res->res_data);
5477                         data_entry.rde_size = GUINT32_TO_LE (size);
5478
5479                         memcpy (p, &data_entry, sizeof (data_entry));
5480                         p += sizeof (data_entry);
5481
5482                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5483                         p += size;
5484                 } else {
5485                         resource_tree_encode (child, begin, p, &p);
5486                 }
5487         }
5488
5489         /* IMAGE_RESOURCE_ENTRY */
5490         for (l = node->children; l; l = l->next) {
5491                 ResTreeNode *child = (ResTreeNode*)l->data;
5492
5493                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5494                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5495
5496                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5497                 entries += sizeof (dir_entry);
5498         }
5499
5500         *endbuf = p;
5501 }
5502
5503 static void
5504 resource_tree_free (ResTreeNode * node)
5505 {
5506         GSList * list;
5507         for (list = node->children; list; list = list->next)
5508                 resource_tree_free ((ResTreeNode*)list->data);
5509         g_slist_free(node->children);
5510         g_free (node);
5511 }
5512
5513 static void
5514 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5515 {
5516         char *buf;
5517         char *p;
5518         guint32 size, i;
5519         MonoReflectionWin32Resource *win32_res;
5520         ResTreeNode *tree;
5521
5522         if (!assemblyb->win32_resources)
5523                 return;
5524
5525         /*
5526          * Resources are stored in a three level tree inside the PE file.
5527          * - level one contains a node for each type of resource
5528          * - level two contains a node for each resource
5529          * - level three contains a node for each instance of a resource for a
5530          *   specific language.
5531          */
5532
5533         tree = resource_tree_create (assemblyb->win32_resources);
5534
5535         /* Estimate the size of the encoded tree */
5536         size = 0;
5537         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5538                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5539                 size += mono_array_length (win32_res->res_data);
5540         }
5541         /* Directory structure */
5542         size += mono_array_length (assemblyb->win32_resources) * 256;
5543         p = buf = g_malloc (size);
5544
5545         resource_tree_encode (tree, p, p, &p);
5546
5547         g_assert (p - buf <= size);
5548
5549         assembly->win32_res = g_malloc (p - buf);
5550         assembly->win32_res_size = p - buf;
5551         memcpy (assembly->win32_res, buf, p - buf);
5552
5553         g_free (buf);
5554         resource_tree_free (tree);
5555 }
5556
5557 static void
5558 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5559 {
5560         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5561         int i;
5562
5563         p += sizeof (MonoPEResourceDir);
5564         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5565                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5566                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5567                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5568                         fixup_resource_directory (res_section, child, rva);
5569                 } else {
5570                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5571                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5572                 }
5573
5574                 p += sizeof (MonoPEResourceDirEntry);
5575         }
5576 }
5577
5578 static void
5579 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5580 {
5581         guint32 dummy;
5582         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5583                 g_error ("WriteFile returned %d\n", GetLastError ());
5584 }
5585
5586 /*
5587  * mono_image_create_pefile:
5588  * @mb: a module builder object
5589  * 
5590  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5591  * assembly->pefile where it can be easily retrieved later in chunks.
5592  */
5593 void
5594 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5595 {
5596         MonoMSDOSHeader *msdos;
5597         MonoDotNetHeader *header;
5598         MonoSectionTable *section;
5599         MonoCLIHeader *cli_header;
5600         guint32 size, image_size, virtual_base, text_offset;
5601         guint32 header_start, section_start, file_offset, virtual_offset;
5602         MonoDynamicImage *assembly;
5603         MonoReflectionAssemblyBuilder *assemblyb;
5604         MonoDynamicStream pefile_stream = {0};
5605         MonoDynamicStream *pefile = &pefile_stream;
5606         int i, nsections;
5607         guint32 *rva, value;
5608         guchar *p;
5609         static const unsigned char msheader[] = {
5610                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5611                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5612                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5613                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5614                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5615                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5616                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5617                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5618         };
5619
5620         assemblyb = mb->assemblyb;
5621
5622         mono_image_basic_init (assemblyb);
5623         assembly = mb->dynamic_image;
5624
5625         assembly->pe_kind = assemblyb->pe_kind;
5626         assembly->machine = assemblyb->machine;
5627         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5628         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5629         
5630         mono_image_build_metadata (mb);
5631
5632         if (mb->is_main && assemblyb->resources) {
5633                 int len = mono_array_length (assemblyb->resources);
5634                 for (i = 0; i < len; ++i)
5635                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5636         }
5637
5638         if (mb->resources) {
5639                 int len = mono_array_length (mb->resources);
5640                 for (i = 0; i < len; ++i)
5641                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5642         }
5643
5644         build_compressed_metadata (assembly);
5645
5646         if (mb->is_main)
5647                 assembly_add_win32_resources (assembly, assemblyb);
5648
5649         nsections = calc_section_size (assembly);
5650         
5651         /* The DOS header and stub */
5652         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5653         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5654
5655         /* the dotnet header */
5656         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5657
5658         /* the section tables */
5659         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5660
5661         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5662         virtual_offset = VIRT_ALIGN;
5663         image_size = 0;
5664
5665         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5666                 if (!assembly->sections [i].size)
5667                         continue;
5668                 /* align offsets */
5669                 file_offset += FILE_ALIGN - 1;
5670                 file_offset &= ~(FILE_ALIGN - 1);
5671                 virtual_offset += VIRT_ALIGN - 1;
5672                 virtual_offset &= ~(VIRT_ALIGN - 1);
5673
5674                 assembly->sections [i].offset = file_offset;
5675                 assembly->sections [i].rva = virtual_offset;
5676
5677                 file_offset += assembly->sections [i].size;
5678                 virtual_offset += assembly->sections [i].size;
5679                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5680         }
5681
5682         file_offset += FILE_ALIGN - 1;
5683         file_offset &= ~(FILE_ALIGN - 1);
5684
5685         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5686
5687         /* back-patch info */
5688         msdos = (MonoMSDOSHeader*)pefile->data;
5689         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5690
5691         header = (MonoDotNetHeader*)(pefile->data + header_start);
5692         header->pesig [0] = 'P';
5693         header->pesig [1] = 'E';
5694         
5695         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5696         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5697         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5698         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5699         if (assemblyb->pekind == 1) {
5700                 /* it's a dll */
5701                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5702         } else {
5703                 /* it's an exe */
5704                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5705         }
5706
5707         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5708
5709         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5710         header->pe.pe_major = 6;
5711         header->pe.pe_minor = 0;
5712         size = assembly->sections [MONO_SECTION_TEXT].size;
5713         size += FILE_ALIGN - 1;
5714         size &= ~(FILE_ALIGN - 1);
5715         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5716         size = assembly->sections [MONO_SECTION_RSRC].size;
5717         size += FILE_ALIGN - 1;
5718         size &= ~(FILE_ALIGN - 1);
5719         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5720         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5721         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5722         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5723         /* pe_rva_entry_point always at the beginning of the text section */
5724         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5725
5726         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5727         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5728         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5729         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5730         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5731         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5732         size = section_start;
5733         size += FILE_ALIGN - 1;
5734         size &= ~(FILE_ALIGN - 1);
5735         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5736         size = image_size;
5737         size += VIRT_ALIGN - 1;
5738         size &= ~(VIRT_ALIGN - 1);
5739         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5740
5741         /*
5742         // Translate the PEFileKind value to the value expected by the Windows loader
5743         */
5744         {
5745                 short kind;
5746
5747                 /*
5748                 // PEFileKinds.Dll == 1
5749                 // PEFileKinds.ConsoleApplication == 2
5750                 // PEFileKinds.WindowApplication == 3
5751                 //
5752                 // need to get:
5753                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5754                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5755                 */
5756                 if (assemblyb->pekind == 3)
5757                         kind = 2;
5758                 else
5759                         kind = 3;
5760                 
5761                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5762         }    
5763         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5764         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5765         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5766         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5767         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5768         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5769
5770         /* fill data directory entries */
5771
5772         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5773         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5774
5775         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5776         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5777
5778         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5779         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5780         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5781         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5782         /* patch entrypoint name */
5783         if (assemblyb->pekind == 1)
5784                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5785         else
5786                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5787         /* patch imported function RVA name */
5788         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5789         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5790
5791         /* the import table */
5792         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5793         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5794         /* patch imported dll RVA name and other entries in the dir */
5795         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5796         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5797         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5798         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5799         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5800         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5801
5802         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5803         value = (assembly->text_rva + assembly->imp_names_offset);
5804         *p++ = (value) & 0xff;
5805         *p++ = (value >> 8) & (0xff);
5806         *p++ = (value >> 16) & (0xff);
5807         *p++ = (value >> 24) & (0xff);
5808
5809         /* the CLI header info */
5810         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5811         cli_header->ch_size = GUINT32_FROM_LE (72);
5812         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5813         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5814         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5815         if (assemblyb->entry_point) {
5816                 guint32 table_idx = 0;
5817                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5818                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5819                         table_idx = methodb->table_idx;
5820                 } else {
5821                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5822                 }
5823                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5824         } else {
5825                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5826         }
5827         /* The embedded managed resources */
5828         text_offset = assembly->text_rva + assembly->code.index;
5829         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5830         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5831         text_offset += assembly->resources.index;
5832         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5833         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5834         text_offset += assembly->meta_size;
5835         if (assembly->strong_name_size) {
5836                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5837                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5838                 text_offset += assembly->strong_name_size;
5839         }
5840
5841         /* write the section tables and section content */
5842         section = (MonoSectionTable*)(pefile->data + section_start);
5843         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5844                 static const char section_names [][7] = {
5845                         ".text", ".rsrc", ".reloc"
5846                 };
5847                 if (!assembly->sections [i].size)
5848                         continue;
5849                 strcpy (section->st_name, section_names [i]);
5850                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5851                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5852                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5853                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5854                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5855                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5856                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5857                 section ++;
5858         }
5859         
5860         checked_write_file (file, pefile->data, pefile->index);
5861         
5862         mono_dynamic_stream_reset (pefile);
5863         
5864         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5865                 if (!assembly->sections [i].size)
5866                         continue;
5867                 
5868                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5869                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5870                 
5871                 switch (i) {
5872                 case MONO_SECTION_TEXT:
5873                         /* patch entry point */
5874                         p = (guchar*)(assembly->code.data + 2);
5875                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5876                         *p++ = (value) & 0xff;
5877                         *p++ = (value >> 8) & 0xff;
5878                         *p++ = (value >> 16) & 0xff;
5879                         *p++ = (value >> 24) & 0xff;
5880                 
5881                         checked_write_file (file, assembly->code.data, assembly->code.index);
5882                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5883                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5884                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5885                                 
5886
5887                         g_free (assembly->image.raw_metadata);
5888                         break;
5889                 case MONO_SECTION_RELOC: {
5890                         struct {
5891                                 guint32 page_rva;
5892                                 guint32 block_size;
5893                                 guint16 type_and_offset;
5894                                 guint16 term;
5895                         } reloc;
5896                         
5897                         g_assert (sizeof (reloc) == 12);
5898                         
5899                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5900                         reloc.block_size = GUINT32_FROM_LE (12);
5901                         
5902                         /* 
5903                          * the entrypoint is always at the start of the text section 
5904                          * 3 is IMAGE_REL_BASED_HIGHLOW
5905                          * 2 is patch_size_rva - text_rva
5906                          */
5907                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5908                         reloc.term = 0;
5909                         
5910                         checked_write_file (file, &reloc, sizeof (reloc));
5911                         
5912                         break;
5913                 }
5914                 case MONO_SECTION_RSRC:
5915                         if (assembly->win32_res) {
5916
5917                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5918                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5919                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5920                         }
5921                         break;
5922                 default:
5923                         g_assert_not_reached ();
5924                 }
5925         }
5926         
5927         /* check that the file is properly padded */
5928         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5929                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5930         if (! SetEndOfFile (file))
5931                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5932         
5933         mono_dynamic_stream_reset (&assembly->code);
5934         mono_dynamic_stream_reset (&assembly->us);
5935         mono_dynamic_stream_reset (&assembly->blob);
5936         mono_dynamic_stream_reset (&assembly->guid);
5937         mono_dynamic_stream_reset (&assembly->sheap);
5938
5939         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5940         g_hash_table_destroy (assembly->blob_cache);
5941         assembly->blob_cache = NULL;
5942 }
5943
5944 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5945
5946 void
5947 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5948 {
5949         g_assert_not_reached ();
5950 }
5951
5952 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5953
5954 #ifndef DISABLE_REFLECTION_EMIT
5955
5956 MonoReflectionModule *
5957 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5958 {
5959         char *name;
5960         MonoImage *image;
5961         MonoImageOpenStatus status;
5962         MonoDynamicAssembly *assembly;
5963         guint32 module_count;
5964         MonoImage **new_modules;
5965         gboolean *new_modules_loaded;
5966         
5967         name = mono_string_to_utf8 (fileName);
5968
5969         image = mono_image_open (name, &status);
5970         if (!image) {
5971                 MonoException *exc;
5972                 if (status == MONO_IMAGE_ERROR_ERRNO)
5973                         exc = mono_get_exception_file_not_found (fileName);
5974                 else
5975                         exc = mono_get_exception_bad_image_format (name);
5976                 g_free (name);
5977                 mono_raise_exception (exc);
5978         }
5979
5980         g_free (name);
5981
5982         assembly = ab->dynamic_assembly;
5983         image->assembly = (MonoAssembly*)assembly;
5984
5985         module_count = image->assembly->image->module_count;
5986         new_modules = g_new0 (MonoImage *, module_count + 1);
5987         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5988
5989         if (image->assembly->image->modules)
5990                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5991         if (image->assembly->image->modules_loaded)
5992                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5993         new_modules [module_count] = image;
5994         new_modules_loaded [module_count] = TRUE;
5995         mono_image_addref (image);
5996
5997         g_free (image->assembly->image->modules);
5998         image->assembly->image->modules = new_modules;
5999         image->assembly->image->modules_loaded = new_modules_loaded;
6000         image->assembly->image->module_count ++;
6001
6002         mono_assembly_load_references (image, &status);
6003         if (status) {
6004                 mono_image_close (image);
6005                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6006         }
6007
6008         return mono_module_get_object (mono_domain_get (), image);
6009 }
6010
6011 #endif /* DISABLE_REFLECTION_EMIT */
6012
6013 /*
6014  * We need to return always the same object for MethodInfo, FieldInfo etc..
6015  * but we need to consider the reflected type.
6016  * type uses a different hash, since it uses custom hash/equal functions.
6017  */
6018
6019 typedef struct {
6020         gpointer item;
6021         MonoClass *refclass;
6022 } ReflectedEntry;
6023
6024 static gboolean
6025 reflected_equal (gconstpointer a, gconstpointer b) {
6026         const ReflectedEntry *ea = a;
6027         const ReflectedEntry *eb = b;
6028
6029         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6030 }
6031
6032 static guint
6033 reflected_hash (gconstpointer a) {
6034         const ReflectedEntry *ea = a;
6035         return mono_aligned_addr_hash (ea->item);
6036 }
6037
6038 #define CHECK_OBJECT(t,p,k)     \
6039         do {    \
6040                 t _obj; \
6041                 ReflectedEntry e;       \
6042                 e.item = (p);   \
6043                 e.refclass = (k);       \
6044                 mono_domain_lock (domain);      \
6045                 if (!domain->refobject_hash)    \
6046                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6047                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6048                         mono_domain_unlock (domain);    \
6049                         return _obj;    \
6050                 }       \
6051         mono_domain_unlock (domain); \
6052         } while (0)
6053
6054 #ifdef HAVE_BOEHM_GC
6055 /* ReflectedEntry doesn't need to be GC tracked */
6056 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6057 #define FREE_REFENTRY(entry) g_free ((entry))
6058 #define REFENTRY_REQUIRES_CLEANUP
6059 #else
6060 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6061 /* FIXME: */
6062 #define FREE_REFENTRY(entry)
6063 #endif
6064
6065 #define CACHE_OBJECT(t,p,o,k)   \
6066         do {    \
6067                 t _obj; \
6068         ReflectedEntry pe; \
6069         pe.item = (p); \
6070         pe.refclass = (k); \
6071         mono_domain_lock (domain); \
6072                 if (!domain->refobject_hash)    \
6073                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6074         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6075         if (!_obj) { \
6076                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6077                     e->item = (p);      \
6078                     e->refclass = (k);  \
6079                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6080             _obj = o; \
6081         } \
6082                 mono_domain_unlock (domain);    \
6083         return _obj; \
6084         } while (0)
6085
6086 static void
6087 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6088 {
6089         mono_domain_lock (domain);
6090         if (domain->refobject_hash) {
6091         ReflectedEntry pe;
6092                 gpointer orig_pe, orig_value;
6093
6094                 pe.item = o;
6095                 pe.refclass = klass;
6096                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6097                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6098                         FREE_REFENTRY (orig_pe);
6099                 }
6100         }
6101         mono_domain_unlock (domain);
6102 }
6103
6104 #ifdef REFENTRY_REQUIRES_CLEANUP
6105 static void
6106 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6107 {
6108         FREE_REFENTRY (key);
6109 }
6110 #endif
6111
6112 void
6113 mono_reflection_cleanup_domain (MonoDomain *domain)
6114 {
6115         if (domain->refobject_hash) {
6116 /*let's avoid scanning the whole hashtable if not needed*/
6117 #ifdef REFENTRY_REQUIRES_CLEANUP
6118                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6119 #endif
6120                 mono_g_hash_table_destroy (domain->refobject_hash);
6121                 domain->refobject_hash = NULL;
6122         }
6123 }
6124
6125 #ifndef DISABLE_REFLECTION_EMIT
6126 static gpointer
6127 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6128 {
6129         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6130 }
6131
6132 static gpointer
6133 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6134 {
6135         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6136 }
6137
6138 void
6139 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6140 {
6141         MonoDynamicImage *image = moduleb->dynamic_image;
6142         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6143         if (!image) {
6144                 MonoError error;
6145                 int module_count;
6146                 MonoImage **new_modules;
6147                 MonoImage *ass;
6148                 char *name, *fqname;
6149                 /*
6150                  * FIXME: we already created an image in mono_image_basic_init (), but
6151                  * we don't know which module it belongs to, since that is only 
6152                  * determined at assembly save time.
6153                  */
6154                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6155                 name = mono_string_to_utf8 (ab->name);
6156                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6157                 if (!mono_error_ok (&error)) {
6158                         g_free (name);
6159                         mono_error_raise_exception (&error);
6160                 }
6161                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6162
6163                 moduleb->module.image = &image->image;
6164                 moduleb->dynamic_image = image;
6165                 register_module (mono_object_domain (moduleb), moduleb, image);
6166
6167                 /* register the module with the assembly */
6168                 ass = ab->dynamic_assembly->assembly.image;
6169                 module_count = ass->module_count;
6170                 new_modules = g_new0 (MonoImage *, module_count + 1);
6171
6172                 if (ass->modules)
6173                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6174                 new_modules [module_count] = &image->image;
6175                 mono_image_addref (&image->image);
6176
6177                 g_free (ass->modules);
6178                 ass->modules = new_modules;
6179                 ass->module_count ++;
6180         }
6181 }
6182
6183 void
6184 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6185 {
6186         MonoDynamicImage *image = moduleb->dynamic_image;
6187
6188         g_assert (type->type);
6189         image->wrappers_type = mono_class_from_mono_type (type->type);
6190 }
6191
6192 #endif
6193
6194 /*
6195  * mono_assembly_get_object:
6196  * @domain: an app domain
6197  * @assembly: an assembly
6198  *
6199  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6200  */
6201 MonoReflectionAssembly*
6202 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6203 {
6204         static MonoClass *assembly_type;
6205         MonoReflectionAssembly *res;
6206         
6207         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6208         if (!assembly_type) {
6209                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6210                 if (class == NULL)
6211                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6212                 g_assert (class);
6213                 assembly_type = class;
6214         }
6215         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6216         res->assembly = assembly;
6217
6218         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6219 }
6220
6221
6222
6223 MonoReflectionModule*   
6224 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6225 {
6226         static MonoClass *module_type;
6227         MonoReflectionModule *res;
6228         char* basename;
6229         
6230         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6231         if (!module_type) {
6232                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6233                 if (class == NULL)
6234                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6235                 g_assert (class);
6236                 module_type = class;
6237         }
6238         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6239
6240         res->image = image;
6241         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6242
6243         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6244         basename = g_path_get_basename (image->name);
6245         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6246         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6247         
6248         g_free (basename);
6249
6250         if (image->assembly->image == image) {
6251                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6252         } else {
6253                 int i;
6254                 res->token = 0;
6255                 if (image->assembly->image->modules) {
6256                         for (i = 0; i < image->assembly->image->module_count; i++) {
6257                                 if (image->assembly->image->modules [i] == image)
6258                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6259                         }
6260                         g_assert (res->token);
6261                 }
6262         }
6263
6264         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6265 }
6266
6267 MonoReflectionModule*   
6268 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6269 {
6270         static MonoClass *module_type;
6271         MonoReflectionModule *res;
6272         MonoTableInfo *table;
6273         guint32 cols [MONO_FILE_SIZE];
6274         const char *name;
6275         guint32 i, name_idx;
6276         const char *val;
6277         
6278         if (!module_type) {
6279                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6280                 if (class == NULL)
6281                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6282                 g_assert (class);
6283                 module_type = class;
6284         }
6285         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6286
6287         table = &image->tables [MONO_TABLE_FILE];
6288         g_assert (table_index < table->rows);
6289         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6290
6291         res->image = NULL;
6292         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6293         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6294
6295         /* Check whenever the row has a corresponding row in the moduleref table */
6296         table = &image->tables [MONO_TABLE_MODULEREF];
6297         for (i = 0; i < table->rows; ++i) {
6298                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6299                 val = mono_metadata_string_heap (image, name_idx);
6300                 if (strcmp (val, name) == 0)
6301                         res->image = image->modules [i];
6302         }
6303
6304         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6305         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6306         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6307         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6308         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6309
6310         return res;
6311 }
6312
6313 static gboolean
6314 verify_safe_for_managed_space (MonoType *type)
6315 {
6316         switch (type->type) {
6317 #ifdef DEBUG_HARDER
6318         case MONO_TYPE_ARRAY:
6319                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6320         case MONO_TYPE_PTR:
6321                 return verify_safe_for_managed_space (type->data.type);
6322         case MONO_TYPE_SZARRAY:
6323                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6324         case MONO_TYPE_GENERICINST: {
6325                 MonoGenericInst *inst = type->data.generic_class->inst;
6326                 int i;
6327                 if (!inst->is_open)
6328                         break;
6329                 for (i = 0; i < inst->type_argc; ++i)
6330                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6331                                 return FALSE;
6332                 break;
6333         }
6334 #endif
6335         case MONO_TYPE_VAR:
6336         case MONO_TYPE_MVAR:
6337                 return TRUE;
6338         }
6339         return TRUE;
6340 }
6341
6342 static MonoType*
6343 mono_type_normalize (MonoType *type)
6344 {
6345         int i;
6346         MonoGenericClass *gclass;
6347         MonoGenericInst *ginst;
6348         MonoClass *gtd;
6349         MonoGenericContainer *gcontainer;
6350         MonoType **argv = NULL;
6351         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6352
6353         if (type->type != MONO_TYPE_GENERICINST)
6354                 return type;
6355
6356         gclass = type->data.generic_class;
6357         ginst = gclass->context.class_inst;
6358         if (!ginst->is_open)
6359                 return type;
6360
6361         gtd = gclass->container_class;
6362         gcontainer = gtd->generic_container;
6363         argv = g_newa (MonoType*, ginst->type_argc);
6364
6365         for (i = 0; i < ginst->type_argc; ++i) {
6366                 MonoType *t = ginst->type_argv [i], *norm;
6367                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6368                         is_denorm_gtd = FALSE;
6369                 norm = mono_type_normalize (t);
6370                 argv [i] = norm;
6371                 if (norm != t)
6372                         requires_rebind = TRUE;
6373         }
6374
6375         if (is_denorm_gtd)
6376                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6377
6378         if (requires_rebind) {
6379                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6380                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6381         }
6382
6383         return type;
6384 }
6385 /*
6386  * mono_type_get_object:
6387  * @domain: an app domain
6388  * @type: a type
6389  *
6390  * Return an System.MonoType object representing the type @type.
6391  */
6392 MonoReflectionType*
6393 mono_type_get_object (MonoDomain *domain, MonoType *type)
6394 {
6395         MonoType *norm_type;
6396         MonoReflectionType *res;
6397         MonoClass *klass = mono_class_from_mono_type (type);
6398
6399         /*we must avoid using @type as it might have come
6400          * from a mono_metadata_type_dup and the caller
6401          * expects that is can be freed.
6402          * Using the right type from 
6403          */
6404         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6405
6406         /* void is very common */
6407         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6408                 return (MonoReflectionType*)domain->typeof_void;
6409
6410         /*
6411          * If the vtable of the given class was already created, we can use
6412          * the MonoType from there and avoid all locking and hash table lookups.
6413          * 
6414          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6415          * that the resulting object is different.   
6416          */
6417         if (type == &klass->byval_arg && !klass->image->dynamic) {
6418                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6419                 if (vtable && vtable->type)
6420                         return vtable->type;
6421         }
6422
6423         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6424         mono_domain_lock (domain);
6425         if (!domain->type_hash)
6426                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6427                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6428         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6429                 mono_domain_unlock (domain);
6430                 mono_loader_unlock ();
6431                 return res;
6432         }
6433
6434         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6435          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6436          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6437          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6438          * artifact of how generics are encoded and should be transparent to managed code so we
6439          * need to weed out this diference when retrieving managed System.Type objects.
6440          */
6441         norm_type = mono_type_normalize (type);
6442         if (norm_type != type) {
6443                 res = mono_type_get_object (domain, norm_type);
6444                 mono_g_hash_table_insert (domain->type_hash, type, res);
6445                 mono_domain_unlock (domain);
6446                 mono_loader_unlock ();
6447                 return res;
6448         }
6449
6450         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6451         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6452                 g_assert (0);
6453
6454         if (!verify_safe_for_managed_space (type)) {
6455                 mono_domain_unlock (domain);
6456                 mono_loader_unlock ();
6457                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6458         }
6459
6460         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6461                 gboolean is_type_done = TRUE;
6462                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6463                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6464                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6465                 */
6466                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6467                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6468
6469                         if (gparam->owner && gparam->owner->is_method) {
6470                                 MonoMethod *method = gparam->owner->owner.method;
6471                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6472                                         is_type_done = FALSE;
6473                         } else if (gparam->owner && !gparam->owner->is_method) {
6474                                 MonoClass *klass = gparam->owner->owner.klass;
6475                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6476                                         is_type_done = FALSE;
6477                         }
6478                 } 
6479
6480                 /* g_assert_not_reached (); */
6481                 /* should this be considered an error condition? */
6482                 if (is_type_done && !type->byref) {
6483                         mono_domain_unlock (domain);
6484                         mono_loader_unlock ();
6485                         return mono_class_get_ref_info (klass);
6486                 }
6487         }
6488         /* This is stored in vtables/JITted code so it has to be pinned */
6489         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6490         res->type = type;
6491         mono_g_hash_table_insert (domain->type_hash, type, res);
6492
6493         if (type->type == MONO_TYPE_VOID)
6494                 domain->typeof_void = (MonoObject*)res;
6495
6496         mono_domain_unlock (domain);
6497         mono_loader_unlock ();
6498         return res;
6499 }
6500
6501 /*
6502  * mono_method_get_object:
6503  * @domain: an app domain
6504  * @method: a method
6505  * @refclass: the reflected type (can be NULL)
6506  *
6507  * Return an System.Reflection.MonoMethod object representing the method @method.
6508  */
6509 MonoReflectionMethod*
6510 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6511 {
6512         /*
6513          * We use the same C representation for methods and constructors, but the type 
6514          * name in C# is different.
6515          */
6516         static MonoClass *System_Reflection_MonoMethod = NULL;
6517         static MonoClass *System_Reflection_MonoCMethod = NULL;
6518         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6519         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6520         MonoClass *klass;
6521         MonoReflectionMethod *ret;
6522
6523         if (method->is_inflated) {
6524                 MonoReflectionGenericMethod *gret;
6525
6526                 refclass = method->klass;
6527                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6528                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6529                         if (!System_Reflection_MonoGenericCMethod)
6530                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6531                         klass = System_Reflection_MonoGenericCMethod;
6532                 } else {
6533                         if (!System_Reflection_MonoGenericMethod)
6534                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6535                         klass = System_Reflection_MonoGenericMethod;
6536                 }
6537                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6538                 gret->method.method = method;
6539                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6540                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6541                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6542         }
6543
6544         if (!refclass)
6545                 refclass = method->klass;
6546
6547         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6548         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6549                 if (!System_Reflection_MonoCMethod)
6550                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6551                 klass = System_Reflection_MonoCMethod;
6552         }
6553         else {
6554                 if (!System_Reflection_MonoMethod)
6555                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6556                 klass = System_Reflection_MonoMethod;
6557         }
6558         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6559         ret->method = method;
6560         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6561         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6562 }
6563
6564 /*
6565  * mono_method_clear_object:
6566  *
6567  *   Clear the cached reflection objects for the dynamic method METHOD.
6568  */
6569 void
6570 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6571 {
6572         MonoClass *klass;
6573         g_assert (method->dynamic);
6574
6575         klass = method->klass;
6576         while (klass) {
6577                 clear_cached_object (domain, method, klass);
6578                 klass = klass->parent;
6579         }
6580         /* Added by mono_param_get_objects () */
6581         clear_cached_object (domain, &(method->signature), NULL);
6582         klass = method->klass;
6583         while (klass) {
6584                 clear_cached_object (domain, &(method->signature), klass);
6585                 klass = klass->parent;
6586         }
6587 }
6588
6589 /*
6590  * mono_field_get_object:
6591  * @domain: an app domain
6592  * @klass: a type
6593  * @field: a field
6594  *
6595  * Return an System.Reflection.MonoField object representing the field @field
6596  * in class @klass.
6597  */
6598 MonoReflectionField*
6599 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6600 {
6601         MonoReflectionField *res;
6602         static MonoClass *monofield_klass;
6603
6604         CHECK_OBJECT (MonoReflectionField *, field, klass);
6605         if (!monofield_klass)
6606                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6607         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6608         res->klass = klass;
6609         res->field = field;
6610         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6611
6612         if (is_field_on_inst (field)) {
6613                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6614                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6615         } else {
6616                 if (field->type)
6617                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6618                 res->attrs = mono_field_get_flags (field);
6619         }
6620         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6621 }
6622
6623 /*
6624  * mono_property_get_object:
6625  * @domain: an app domain
6626  * @klass: a type
6627  * @property: a property
6628  *
6629  * Return an System.Reflection.MonoProperty object representing the property @property
6630  * in class @klass.
6631  */
6632 MonoReflectionProperty*
6633 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6634 {
6635         MonoReflectionProperty *res;
6636         static MonoClass *monoproperty_klass;
6637
6638         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6639         if (!monoproperty_klass)
6640                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6641         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6642         res->klass = klass;
6643         res->property = property;
6644         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6645 }
6646
6647 /*
6648  * mono_event_get_object:
6649  * @domain: an app domain
6650  * @klass: a type
6651  * @event: a event
6652  *
6653  * Return an System.Reflection.MonoEvent object representing the event @event
6654  * in class @klass.
6655  */
6656 MonoReflectionEvent*
6657 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6658 {
6659         MonoReflectionEvent *res;
6660         MonoReflectionMonoEvent *mono_event;
6661         static MonoClass *monoevent_klass;
6662
6663         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6664         if (!monoevent_klass)
6665                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6666         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6667         mono_event->klass = klass;
6668         mono_event->event = event;
6669         res = (MonoReflectionEvent*)mono_event;
6670         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6671 }
6672
6673 /**
6674  * mono_get_reflection_missing_object:
6675  * @domain: Domain where the object lives
6676  *
6677  * Returns the System.Reflection.Missing.Value singleton object
6678  * (of type System.Reflection.Missing).
6679  *
6680  * Used as the value for ParameterInfo.DefaultValue when Optional
6681  * is present
6682  */
6683 static MonoObject *
6684 mono_get_reflection_missing_object (MonoDomain *domain)
6685 {
6686         MonoObject *obj;
6687         static MonoClassField *missing_value_field = NULL;
6688         
6689         if (!missing_value_field) {
6690                 MonoClass *missing_klass;
6691                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6692                 mono_class_init (missing_klass);
6693                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6694                 g_assert (missing_value_field);
6695         }
6696         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6697         g_assert (obj);
6698         return obj;
6699 }
6700
6701 static MonoObject*
6702 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6703 {
6704         if (!*dbnull)
6705                 *dbnull = mono_get_dbnull_object (domain);
6706         return *dbnull;
6707 }
6708
6709 static MonoObject*
6710 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6711 {
6712         if (!*reflection_missing)
6713                 *reflection_missing = mono_get_reflection_missing_object (domain);
6714         return *reflection_missing;
6715 }
6716
6717 /*
6718  * mono_param_get_objects:
6719  * @domain: an app domain
6720  * @method: a method
6721  *
6722  * Return an System.Reflection.ParameterInfo array object representing the parameters
6723  * in the method @method.
6724  */
6725 MonoArray*
6726 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6727 {
6728         static MonoClass *System_Reflection_ParameterInfo;
6729         static MonoClass *System_Reflection_ParameterInfo_array;
6730         MonoError error;
6731         MonoArray *res = NULL;
6732         MonoReflectionMethod *member = NULL;
6733         MonoReflectionParameter *param = NULL;
6734         char **names, **blobs = NULL;
6735         guint32 *types = NULL;
6736         MonoType *type = NULL;
6737         MonoObject *dbnull = NULL;
6738         MonoObject *missing = NULL;
6739         MonoMarshalSpec **mspecs;
6740         MonoMethodSignature *sig;
6741         MonoVTable *pinfo_vtable;
6742         int i;
6743
6744         if (!System_Reflection_ParameterInfo_array) {
6745                 MonoClass *klass;
6746
6747                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6748                 mono_memory_barrier ();
6749                 System_Reflection_ParameterInfo = klass; 
6750         
6751                 klass = mono_array_class_get (klass, 1);
6752                 mono_memory_barrier ();
6753                 System_Reflection_ParameterInfo_array = klass;
6754         }
6755
6756         sig = mono_method_signature_checked (method, &error);
6757         if (!mono_error_ok (&error))
6758                 mono_error_raise_exception (&error);
6759
6760         if (!sig->param_count)
6761                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6762
6763         /* Note: the cache is based on the address of the signature into the method
6764          * since we already cache MethodInfos with the method as keys.
6765          */
6766         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6767
6768         member = mono_method_get_object (domain, method, refclass);
6769         names = g_new (char *, sig->param_count);
6770         mono_method_get_param_names (method, (const char **) names);
6771
6772         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6773         mono_method_get_marshal_info (method, mspecs);
6774
6775         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6776         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6777         for (i = 0; i < sig->param_count; ++i) {
6778                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6779                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6780                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6781                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6782                 param->PositionImpl = i;
6783                 param->AttrsImpl = sig->params [i]->attrs;
6784
6785                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6786                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6787                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6788                         else
6789                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6790                 } else {
6791
6792                         if (!blobs) {
6793                                 blobs = g_new0 (char *, sig->param_count);
6794                                 types = g_new0 (guint32, sig->param_count);
6795                                 get_default_param_value_blobs (method, blobs, types); 
6796                         }
6797
6798                         /* Build MonoType for the type from the Constant Table */
6799                         if (!type)
6800                                 type = g_new0 (MonoType, 1);
6801                         type->type = types [i];
6802                         type->data.klass = NULL;
6803                         if (types [i] == MONO_TYPE_CLASS)
6804                                 type->data.klass = mono_defaults.object_class;
6805                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6806                                 /* For enums, types [i] contains the base type */
6807
6808                                         type->type = MONO_TYPE_VALUETYPE;
6809                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6810                         } else
6811                                 type->data.klass = mono_class_from_mono_type (type);
6812
6813                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6814
6815                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6816                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6817                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6818                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6819                                 else
6820                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6821                         }
6822                         
6823                 }
6824
6825                 if (mspecs [i + 1])
6826                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6827                 
6828                 mono_array_setref (res, i, param);
6829         }
6830         g_free (names);
6831         g_free (blobs);
6832         g_free (types);
6833         g_free (type);
6834
6835         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6836                 if (mspecs [i])
6837                         mono_metadata_free_marshal_spec (mspecs [i]);
6838         g_free (mspecs);
6839         
6840         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6841 }
6842
6843 MonoArray*
6844 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6845 {
6846         return mono_param_get_objects_internal (domain, method, NULL);
6847 }
6848
6849 /*
6850  * mono_method_body_get_object:
6851  * @domain: an app domain
6852  * @method: a method
6853  *
6854  * Return an System.Reflection.MethodBody object representing the method @method.
6855  */
6856 MonoReflectionMethodBody*
6857 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6858 {
6859         static MonoClass *System_Reflection_MethodBody = NULL;
6860         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6861         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6862         MonoReflectionMethodBody *ret;
6863         MonoMethodHeader *header;
6864         MonoImage *image;
6865         guint32 method_rva, local_var_sig_token;
6866     char *ptr;
6867         unsigned char format, flags;
6868         int i;
6869
6870         /* for compatibility with .net */
6871     if (method->dynamic)
6872         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6873
6874         if (!System_Reflection_MethodBody)
6875                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6876         if (!System_Reflection_LocalVariableInfo)
6877                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6878         if (!System_Reflection_ExceptionHandlingClause)
6879                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6880
6881         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6882
6883         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6884                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6885             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6886             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6887                 return NULL;
6888
6889         image = method->klass->image;
6890         header = mono_method_get_header (method);
6891
6892         if (!image->dynamic) {
6893                 /* Obtain local vars signature token */
6894                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6895                 ptr = mono_image_rva_map (image, method_rva);
6896                 flags = *(const unsigned char *) ptr;
6897                 format = flags & METHOD_HEADER_FORMAT_MASK;
6898                 switch (format){
6899                 case METHOD_HEADER_TINY_FORMAT:
6900                         local_var_sig_token = 0;
6901                         break;
6902                 case METHOD_HEADER_FAT_FORMAT:
6903                         ptr += 2;
6904                         ptr += 2;
6905                         ptr += 4;
6906                         local_var_sig_token = read32 (ptr);
6907                         break;
6908                 default:
6909                         g_assert_not_reached ();
6910                 }
6911         } else
6912                 local_var_sig_token = 0; //FIXME
6913
6914         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6915
6916         ret->init_locals = header->init_locals;
6917         ret->max_stack = header->max_stack;
6918         ret->local_var_sig_token = local_var_sig_token;
6919         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6920         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6921
6922         /* Locals */
6923         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6924         for (i = 0; i < header->num_locals; ++i) {
6925                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6926                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6927                 info->is_pinned = header->locals [i]->pinned;
6928                 info->local_index = i;
6929                 mono_array_setref (ret->locals, i, info);
6930         }
6931
6932         /* Exceptions */
6933         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6934         for (i = 0; i < header->num_clauses; ++i) {
6935                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6936                 MonoExceptionClause *clause = &header->clauses [i];
6937
6938                 info->flags = clause->flags;
6939                 info->try_offset = clause->try_offset;
6940                 info->try_length = clause->try_len;
6941                 info->handler_offset = clause->handler_offset;
6942                 info->handler_length = clause->handler_len;
6943                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6944                         info->filter_offset = clause->data.filter_offset;
6945                 else if (clause->data.catch_class)
6946                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6947
6948                 mono_array_setref (ret->clauses, i, info);
6949         }
6950
6951         mono_metadata_free_mh (header);
6952         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6953         return ret;
6954 }
6955
6956 /**
6957  * mono_get_dbnull_object:
6958  * @domain: Domain where the object lives
6959  *
6960  * Returns the System.DBNull.Value singleton object
6961  *
6962  * Used as the value for ParameterInfo.DefaultValue 
6963  */
6964 MonoObject *
6965 mono_get_dbnull_object (MonoDomain *domain)
6966 {
6967         MonoObject *obj;
6968         static MonoClassField *dbnull_value_field = NULL;
6969         
6970         if (!dbnull_value_field) {
6971                 MonoClass *dbnull_klass;
6972                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6973                 mono_class_init (dbnull_klass);
6974                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6975                 g_assert (dbnull_value_field);
6976         }
6977         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6978         g_assert (obj);
6979         return obj;
6980 }
6981
6982 static void
6983 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6984 {
6985         guint32 param_index, i, lastp, crow = 0;
6986         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6987         gint32 idx;
6988
6989         MonoClass *klass = method->klass;
6990         MonoImage *image = klass->image;
6991         MonoMethodSignature *methodsig = mono_method_signature (method);
6992
6993         MonoTableInfo *constt;
6994         MonoTableInfo *methodt;
6995         MonoTableInfo *paramt;
6996
6997         if (!methodsig->param_count)
6998                 return;
6999
7000         mono_class_init (klass);
7001
7002         if (klass->image->dynamic) {
7003                 MonoReflectionMethodAux *aux;
7004                 if (method->is_inflated)
7005                         method = ((MonoMethodInflated*)method)->declaring;
7006                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7007                 if (aux && aux->param_defaults) {
7008                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7009                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7010                 }
7011                 return;
7012         }
7013
7014         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7015         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7016         constt = &image->tables [MONO_TABLE_CONSTANT];
7017
7018         idx = mono_method_get_index (method) - 1;
7019         g_assert (idx != -1);
7020
7021         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7022         if (idx + 1 < methodt->rows)
7023                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7024         else
7025                 lastp = paramt->rows + 1;
7026
7027         for (i = param_index; i < lastp; ++i) {
7028                 guint32 paramseq;
7029
7030                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7031                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7032
7033                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7034                         continue;
7035
7036                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7037                 if (!crow) {
7038                         continue;
7039                 }
7040         
7041                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7042                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7043                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7044         }
7045
7046         return;
7047 }
7048
7049 MonoObject *
7050 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7051 {
7052         void *retval;
7053         MonoClass *klass;
7054         MonoObject *object;
7055         MonoType *basetype = type;
7056
7057         if (!blob)
7058                 return NULL;
7059         
7060         klass = mono_class_from_mono_type (type);
7061         if (klass->valuetype) {
7062                 object = mono_object_new (domain, klass);
7063                 retval = ((gchar *) object + sizeof (MonoObject));
7064                 if (klass->enumtype)
7065                         basetype = mono_class_enum_basetype (klass);
7066         } else {
7067                 retval = &object;
7068         }
7069                         
7070         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7071                 return object;
7072         else
7073                 return NULL;
7074 }
7075
7076 static int
7077 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7078         int found_sep;
7079         char *s;
7080         gboolean quoted = FALSE;
7081
7082         memset (assembly, 0, sizeof (MonoAssemblyName));
7083         assembly->culture = "";
7084         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7085
7086         if (*p == '"') {
7087                 quoted = TRUE;
7088                 p++;
7089         }
7090         assembly->name = p;
7091         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7092                 p++;
7093         if (quoted) {
7094                 if (*p != '"')
7095                         return 1;
7096                 *p = 0;
7097                 p++;
7098         }
7099         if (*p != ',')
7100                 return 1;
7101         *p = 0;
7102         /* Remove trailing whitespace */
7103         s = p - 1;
7104         while (*s && g_ascii_isspace (*s))
7105                 *s-- = 0;
7106         p ++;
7107         while (g_ascii_isspace (*p))
7108                 p++;
7109         while (*p) {
7110                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7111                         p += 8;
7112                         assembly->major = strtoul (p, &s, 10);
7113                         if (s == p || *s != '.')
7114                                 return 1;
7115                         p = ++s;
7116                         assembly->minor = strtoul (p, &s, 10);
7117                         if (s == p || *s != '.')
7118                                 return 1;
7119                         p = ++s;
7120                         assembly->build = strtoul (p, &s, 10);
7121                         if (s == p || *s != '.')
7122                                 return 1;
7123                         p = ++s;
7124                         assembly->revision = strtoul (p, &s, 10);
7125                         if (s == p)
7126                                 return 1;
7127                         p = s;
7128                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7129                         p += 8;
7130                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7131                                 assembly->culture = "";
7132                                 p += 7;
7133                         } else {
7134                                 assembly->culture = p;
7135                                 while (*p && *p != ',') {
7136                                         p++;
7137                                 }
7138                         }
7139                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7140                         p += 15;
7141                         if (strncmp (p, "null", 4) == 0) {
7142                                 p += 4;
7143                         } else {
7144                                 int len;
7145                                 gchar *start = p;
7146                                 while (*p && *p != ',') {
7147                                         p++;
7148                                 }
7149                                 len = (p - start + 1);
7150                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7151                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7152                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7153                         }
7154                 } else {
7155                         while (*p && *p != ',')
7156                                 p++;
7157                 }
7158                 found_sep = 0;
7159                 while (g_ascii_isspace (*p) || *p == ',') {
7160                         *p++ = 0;
7161                         found_sep = 1;
7162                         continue;
7163                 }
7164                 /* failed */
7165                 if (!found_sep)
7166                         return 1;
7167         }
7168
7169         return 0;
7170 }
7171
7172 /*
7173  * mono_reflection_parse_type:
7174  * @name: type name
7175  *
7176  * Parse a type name as accepted by the GetType () method and output the info
7177  * extracted in the info structure.
7178  * the name param will be mangled, so, make a copy before passing it to this function.
7179  * The fields in info will be valid until the memory pointed to by name is valid.
7180  *
7181  * See also mono_type_get_name () below.
7182  *
7183  * Returns: 0 on parse error.
7184  */
7185 static int
7186 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7187                              MonoTypeNameParse *info)
7188 {
7189         char *start, *p, *w, *temp, *last_point, *startn;
7190         int in_modifiers = 0;
7191         int isbyref = 0, rank, arity = 0, i;
7192
7193         start = p = w = name;
7194
7195         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7196         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7197         info->name = info->name_space = NULL;
7198         info->nested = NULL;
7199         info->modifiers = NULL;
7200         info->type_arguments = NULL;
7201
7202         /* last_point separates the namespace from the name */
7203         last_point = NULL;
7204         /* Skips spaces */
7205         while (*p == ' ') p++, start++, w++, name++;
7206
7207         while (*p) {
7208                 switch (*p) {
7209                 case '+':
7210                         *p = 0; /* NULL terminate the name */
7211                         startn = p + 1;
7212                         info->nested = g_list_append (info->nested, startn);
7213                         /* we have parsed the nesting namespace + name */
7214                         if (info->name)
7215                                 break;
7216                         if (last_point) {
7217                                 info->name_space = start;
7218                                 *last_point = 0;
7219                                 info->name = last_point + 1;
7220                         } else {
7221                                 info->name_space = (char *)"";
7222                                 info->name = start;
7223                         }
7224                         break;
7225                 case '.':
7226                         last_point = p;
7227                         break;
7228                 case '\\':
7229                         ++p;
7230                         break;
7231                 case '&':
7232                 case '*':
7233                 case '[':
7234                 case ',':
7235                 case ']':
7236                         in_modifiers = 1;
7237                         break;
7238                 case '`':
7239                         ++p;
7240                         i = strtol (p, &temp, 10);
7241                         arity += i;
7242                         if (p == temp)
7243                                 return 0;
7244                         p = temp-1;
7245                         break;
7246                 default:
7247                         break;
7248                 }
7249                 if (in_modifiers)
7250                         break;
7251                 // *w++ = *p++;
7252                 p++;
7253         }
7254         
7255         if (!info->name) {
7256                 if (last_point) {
7257                         info->name_space = start;
7258                         *last_point = 0;
7259                         info->name = last_point + 1;
7260                 } else {
7261                         info->name_space = (char *)"";
7262                         info->name = start;
7263                 }
7264         }
7265         while (*p) {
7266                 switch (*p) {
7267                 case '&':
7268                         if (isbyref) /* only one level allowed by the spec */
7269                                 return 0;
7270                         isbyref = 1;
7271                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7272                         *p++ = 0;
7273                         break;
7274                 case '*':
7275                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7276                         *p++ = 0;
7277                         break;
7278                 case '[':
7279                         if (arity != 0) {
7280                                 *p++ = 0;
7281                                 info->type_arguments = g_ptr_array_new ();
7282                                 for (i = 0; i < arity; i++) {
7283                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7284                                         gboolean fqname = FALSE;
7285
7286                                         g_ptr_array_add (info->type_arguments, subinfo);
7287
7288                                         if (*p == '[') {
7289                                                 p++;
7290                                                 fqname = TRUE;
7291                                         }
7292
7293                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7294                                                 return 0;
7295
7296                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7297                                         if (fqname && (*p != ']')) {
7298                                                 char *aname;
7299
7300                                                 if (*p != ',')
7301                                                         return 0;
7302                                                 *p++ = 0;
7303
7304                                                 aname = p;
7305                                                 while (*p && (*p != ']'))
7306                                                         p++;
7307
7308                                                 if (*p != ']')
7309                                                         return 0;
7310
7311                                                 *p++ = 0;
7312                                                 while (*aname) {
7313                                                         if (g_ascii_isspace (*aname)) {
7314                                                                 ++aname;
7315                                                                 continue;
7316                                                         }
7317                                                         break;
7318                                                 }
7319                                                 if (!*aname ||
7320                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7321                                                         return 0;
7322                                         } else if (fqname && (*p == ']')) {
7323                                                 *p++ = 0;
7324                                         }
7325
7326                                         if (i + 1 < arity) {
7327                                                 if (*p != ',')
7328                                                         return 0;
7329                                         } else {
7330                                                 if (*p != ']')
7331                                                         return 0;
7332                                         }
7333                                         *p++ = 0;
7334                                 }
7335
7336                                 arity = 0;
7337                                 break;
7338                         }
7339                         rank = 1;
7340                         *p++ = 0;
7341                         while (*p) {
7342                                 if (*p == ']')
7343                                         break;
7344                                 if (*p == ',')
7345                                         rank++;
7346                                 else if (*p == '*') /* '*' means unknown lower bound */
7347                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7348                                 else
7349                                         return 0;
7350                                 ++p;
7351                         }
7352                         if (*p++ != ']')
7353                                 return 0;
7354                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7355                         break;
7356                 case ']':
7357                         if (is_recursed)
7358                                 goto end;
7359                         return 0;
7360                 case ',':
7361                         if (is_recursed)
7362                                 goto end;
7363                         *p++ = 0;
7364                         while (*p) {
7365                                 if (g_ascii_isspace (*p)) {
7366                                         ++p;
7367                                         continue;
7368                                 }
7369                                 break;
7370                         }
7371                         if (!*p)
7372                                 return 0; /* missing assembly name */
7373                         if (!assembly_name_to_aname (&info->assembly, p))
7374                                 return 0;
7375                         break;
7376                 default:
7377                         return 0;
7378                 }
7379                 if (info->assembly.name)
7380                         break;
7381         }
7382         // *w = 0; /* terminate class name */
7383  end:
7384         if (!info->name || !*info->name)
7385                 return 0;
7386         if (endptr)
7387                 *endptr = p;
7388         /* add other consistency checks */
7389         return 1;
7390 }
7391
7392 int
7393 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7394 {
7395         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7396 }
7397
7398 static MonoType*
7399 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7400 {
7401         gboolean type_resolve = FALSE;
7402         MonoType *type;
7403         MonoImage *rootimage = image;
7404
7405         if (info->assembly.name) {
7406                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7407                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7408                         /* 
7409                          * This could happen in the AOT compiler case when the search hook is not
7410                          * installed.
7411                          */
7412                         assembly = image->assembly;
7413                 if (!assembly) {
7414                         /* then we must load the assembly ourselve - see #60439 */
7415                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7416                         if (!assembly)
7417                                 return NULL;
7418                 }
7419                 image = assembly->image;
7420         } else if (!image) {
7421                 image = mono_defaults.corlib;
7422         }
7423
7424         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7425         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7426                 image = mono_defaults.corlib;
7427                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7428         }
7429
7430         return type;
7431 }
7432
7433 static MonoType*
7434 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7435 {
7436         MonoClass *klass;
7437         GList *mod;
7438         int modval;
7439         gboolean bounded = FALSE;
7440         
7441         if (!image)
7442                 image = mono_defaults.corlib;
7443
7444         if (ignorecase)
7445                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7446         else
7447                 klass = mono_class_from_name (image, info->name_space, info->name);
7448         if (!klass)
7449                 return NULL;
7450         for (mod = info->nested; mod; mod = mod->next) {
7451                 gpointer iter = NULL;
7452                 MonoClass *parent;
7453
7454                 parent = klass;
7455                 mono_class_init (parent);
7456
7457                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7458                         if (ignorecase) {
7459                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7460                                         break;
7461                         } else {
7462                                 if (strcmp (klass->name, mod->data) == 0)
7463                                         break;
7464                         }
7465                 }
7466                 if (!klass)
7467                         break;
7468         }
7469         if (!klass)
7470                 return NULL;
7471
7472         if (info->type_arguments) {
7473                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7474                 MonoReflectionType *the_type;
7475                 MonoType *instance;
7476                 int i;
7477
7478                 for (i = 0; i < info->type_arguments->len; i++) {
7479                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7480
7481                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7482                         if (!type_args [i]) {
7483                                 g_free (type_args);
7484                                 return NULL;
7485                         }
7486                 }
7487
7488                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7489
7490                 instance = mono_reflection_bind_generic_parameters (
7491                         the_type, info->type_arguments->len, type_args);
7492
7493                 g_free (type_args);
7494                 if (!instance)
7495                         return NULL;
7496
7497                 klass = mono_class_from_mono_type (instance);
7498         }
7499
7500         for (mod = info->modifiers; mod; mod = mod->next) {
7501                 modval = GPOINTER_TO_UINT (mod->data);
7502                 if (!modval) { /* byref: must be last modifier */
7503                         return &klass->this_arg;
7504                 } else if (modval == -1) {
7505                         klass = mono_ptr_class_get (&klass->byval_arg);
7506                 } else if (modval == -2) {
7507                         bounded = TRUE;
7508                 } else { /* array rank */
7509                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7510                 }
7511         }
7512
7513         return &klass->byval_arg;
7514 }
7515
7516 /*
7517  * mono_reflection_get_type:
7518  * @image: a metadata context
7519  * @info: type description structure
7520  * @ignorecase: flag for case-insensitive string compares
7521  * @type_resolve: whenever type resolve was already tried
7522  *
7523  * Build a MonoType from the type description in @info.
7524  * 
7525  */
7526
7527 MonoType*
7528 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7529         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7530 }
7531
7532 static MonoType*
7533 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7534 {
7535         MonoReflectionAssemblyBuilder *abuilder;
7536         MonoType *type;
7537         int i;
7538
7539         g_assert (assembly->dynamic);
7540         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7541
7542         /* Enumerate all modules */
7543
7544         type = NULL;
7545         if (abuilder->modules) {
7546                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7547                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7548                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7549                         if (type)
7550                                 break;
7551                 }
7552         }
7553
7554         if (!type && abuilder->loaded_modules) {
7555                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7556                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7557                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7558                         if (type)
7559                                 break;
7560                 }
7561         }
7562
7563         return type;
7564 }
7565         
7566 MonoType*
7567 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7568 {
7569         MonoType *type;
7570         MonoReflectionAssembly *assembly;
7571         GString *fullName;
7572         GList *mod;
7573
7574         if (image && image->dynamic)
7575                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7576         else
7577                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7578         if (type)
7579                 return type;
7580         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7581                 return NULL;
7582
7583         if (type_resolve) {
7584                 if (*type_resolve) 
7585                         return NULL;
7586                 else
7587                         *type_resolve = TRUE;
7588         }
7589         
7590         /* Reconstruct the type name */
7591         fullName = g_string_new ("");
7592         if (info->name_space && (info->name_space [0] != '\0'))
7593                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7594         else
7595                 g_string_printf (fullName, "%s", info->name);
7596         for (mod = info->nested; mod; mod = mod->next)
7597                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7598
7599         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7600         if (assembly) {
7601                 if (assembly->assembly->dynamic)
7602                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7603                 else
7604                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7605                                                                                                           info, ignorecase);
7606         }
7607         g_string_free (fullName, TRUE);
7608         return type;
7609 }
7610
7611 void
7612 mono_reflection_free_type_info (MonoTypeNameParse *info)
7613 {
7614         g_list_free (info->modifiers);
7615         g_list_free (info->nested);
7616
7617         if (info->type_arguments) {
7618                 int i;
7619
7620                 for (i = 0; i < info->type_arguments->len; i++) {
7621                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7622
7623                         mono_reflection_free_type_info (subinfo);
7624                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7625                         g_free (subinfo);
7626                 }
7627
7628                 g_ptr_array_free (info->type_arguments, TRUE);
7629         }
7630 }
7631
7632 /*
7633  * mono_reflection_type_from_name:
7634  * @name: type name.
7635  * @image: a metadata context (can be NULL).
7636  *
7637  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7638  * it defaults to get the type from @image or, if @image is NULL or loading
7639  * from it fails, uses corlib.
7640  * 
7641  */
7642 MonoType*
7643 mono_reflection_type_from_name (char *name, MonoImage *image)
7644 {
7645         MonoType *type = NULL;
7646         MonoTypeNameParse info;
7647         char *tmp;
7648
7649         /* Make a copy since parse_type modifies its argument */
7650         tmp = g_strdup (name);
7651         
7652         /*g_print ("requested type %s\n", str);*/
7653         if (mono_reflection_parse_type (tmp, &info)) {
7654                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7655         }
7656
7657         g_free (tmp);
7658         mono_reflection_free_type_info (&info);
7659         return type;
7660 }
7661
7662 /*
7663  * mono_reflection_get_token:
7664  *
7665  *   Return the metadata token of OBJ which should be an object
7666  * representing a metadata element.
7667  */
7668 guint32
7669 mono_reflection_get_token (MonoObject *obj)
7670 {
7671         MonoClass *klass;
7672         guint32 token = 0;
7673
7674         klass = obj->vtable->klass;
7675
7676         if (strcmp (klass->name, "MethodBuilder") == 0) {
7677                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7678
7679                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7680         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7681                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7682
7683                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7684         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7685                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7686
7687                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7688         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7689                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7690                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7691         } else if (strcmp (klass->name, "MonoType") == 0) {
7692                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7693                 MonoClass *mc = mono_class_from_mono_type (type);
7694                 if (!mono_class_init (mc))
7695                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7696
7697                 token = mc->type_token;
7698         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7699                    strcmp (klass->name, "MonoMethod") == 0 ||
7700                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7701                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7702                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7703                 if (m->method->is_inflated) {
7704                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7705                         return inflated->declaring->token;
7706                 } else {
7707                         token = m->method->token;
7708                 }
7709         } else if (strcmp (klass->name, "MonoField") == 0) {
7710                 MonoReflectionField *f = (MonoReflectionField*)obj;
7711
7712                 if (is_field_on_inst (f->field)) {
7713                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7714                         int field_index = f->field - dgclass->fields;
7715                         MonoObject *obj;
7716
7717                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7718                         obj = dgclass->field_objects [field_index];
7719                         return mono_reflection_get_token (obj);
7720                 }
7721                 token = mono_class_get_field_token (f->field);
7722         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7723                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7724
7725                 token = mono_class_get_property_token (p->property);
7726         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7727                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7728
7729                 token = mono_class_get_event_token (p->event);
7730         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7731                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7732                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7733                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7734
7735                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7736         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7737                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7738
7739                 token = m->token;
7740         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7741                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7742         } else {
7743                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7744                 MonoException *ex = mono_get_exception_not_implemented (msg);
7745                 g_free (msg);
7746                 mono_raise_exception (ex);
7747         }
7748
7749         return token;
7750 }
7751
7752 static void*
7753 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7754 {
7755         int slen, type = t->type;
7756         MonoClass *tklass = t->data.klass;
7757
7758 handle_enum:
7759         switch (type) {
7760         case MONO_TYPE_U1:
7761         case MONO_TYPE_I1:
7762         case MONO_TYPE_BOOLEAN: {
7763                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7764                 *bval = *p;
7765                 *end = p + 1;
7766                 return bval;
7767         }
7768         case MONO_TYPE_CHAR:
7769         case MONO_TYPE_U2:
7770         case MONO_TYPE_I2: {
7771                 guint16 *val = g_malloc (sizeof (guint16));
7772                 *val = read16 (p);
7773                 *end = p + 2;
7774                 return val;
7775         }
7776 #if SIZEOF_VOID_P == 4
7777         case MONO_TYPE_U:
7778         case MONO_TYPE_I:
7779 #endif
7780         case MONO_TYPE_R4:
7781         case MONO_TYPE_U4:
7782         case MONO_TYPE_I4: {
7783                 guint32 *val = g_malloc (sizeof (guint32));
7784                 *val = read32 (p);
7785                 *end = p + 4;
7786                 return val;
7787         }
7788 #if SIZEOF_VOID_P == 8
7789         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7790         case MONO_TYPE_I:
7791 #endif
7792         case MONO_TYPE_U8:
7793         case MONO_TYPE_I8: {
7794                 guint64 *val = g_malloc (sizeof (guint64));
7795                 *val = read64 (p);
7796                 *end = p + 8;
7797                 return val;
7798         }
7799         case MONO_TYPE_R8: {
7800                 double *val = g_malloc (sizeof (double));
7801                 readr8 (p, val);
7802                 *end = p + 8;
7803                 return val;
7804         }
7805         case MONO_TYPE_VALUETYPE:
7806                 if (t->data.klass->enumtype) {
7807                         type = mono_class_enum_basetype (t->data.klass)->type;
7808                         goto handle_enum;
7809                 } else {
7810                         MonoClass *k =  t->data.klass;
7811                         
7812                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7813                                 guint64 *val = g_malloc (sizeof (guint64));
7814                                 *val = read64 (p);
7815                                 *end = p + 8;
7816                                 return val;
7817                         }
7818                 }
7819                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7820                 break;
7821                 
7822         case MONO_TYPE_STRING:
7823                 if (*p == (char)0xFF) {
7824                         *end = p + 1;
7825                         return NULL;
7826                 }
7827                 slen = mono_metadata_decode_value (p, &p);
7828                 *end = p + slen;
7829                 return mono_string_new_len (mono_domain_get (), p, slen);
7830         case MONO_TYPE_CLASS: {
7831                 char *n;
7832                 MonoType *t;
7833                 if (*p == (char)0xFF) {
7834                         *end = p + 1;
7835                         return NULL;
7836                 }
7837 handle_type:
7838                 slen = mono_metadata_decode_value (p, &p);
7839                 n = g_memdup (p, slen + 1);
7840                 n [slen] = 0;
7841                 t = mono_reflection_type_from_name (n, image);
7842                 if (!t)
7843                         g_warning ("Cannot load type '%s'", n);
7844                 g_free (n);
7845                 *end = p + slen;
7846                 if (t)
7847                         return mono_type_get_object (mono_domain_get (), t);
7848                 else
7849                         return NULL;
7850         }
7851         case MONO_TYPE_OBJECT: {
7852                 char subt = *p++;
7853                 MonoObject *obj;
7854                 MonoClass *subc = NULL;
7855                 void *val;
7856
7857                 if (subt == 0x50) {
7858                         goto handle_type;
7859                 } else if (subt == 0x0E) {
7860                         type = MONO_TYPE_STRING;
7861                         goto handle_enum;
7862                 } else if (subt == 0x1D) {
7863                         MonoType simple_type = {{0}};
7864                         int etype = *p;
7865                         p ++;
7866
7867                         if (etype == 0x51)
7868                                 /* See Partition II, Appendix B3 */
7869                                 etype = MONO_TYPE_OBJECT;
7870                         type = MONO_TYPE_SZARRAY;
7871                         simple_type.type = etype;
7872                         tklass = mono_class_from_mono_type (&simple_type);
7873                         goto handle_enum;
7874                 } else if (subt == 0x55) {
7875                         char *n;
7876                         MonoType *t;
7877                         slen = mono_metadata_decode_value (p, &p);
7878                         n = g_memdup (p, slen + 1);
7879                         n [slen] = 0;
7880                         t = mono_reflection_type_from_name (n, image);
7881                         if (!t)
7882                                 g_error ("Cannot load type '%s'", n);
7883                         g_free (n);
7884                         p += slen;
7885                         subc = mono_class_from_mono_type (t);
7886                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7887                         MonoType simple_type = {{0}};
7888                         simple_type.type = subt;
7889                         subc = mono_class_from_mono_type (&simple_type);
7890                 } else {
7891                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7892                 }
7893                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7894                 obj = mono_object_new (mono_domain_get (), subc);
7895                 g_assert (!subc->has_references);
7896                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7897                 g_free (val);
7898                 return obj;
7899         }
7900         case MONO_TYPE_SZARRAY: {
7901                 MonoArray *arr;
7902                 guint32 i, alen, basetype;
7903                 alen = read32 (p);
7904                 p += 4;
7905                 if (alen == 0xffffffff) {
7906                         *end = p;
7907                         return NULL;
7908                 }
7909                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7910                 basetype = tklass->byval_arg.type;
7911                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7912                         basetype = mono_class_enum_basetype (tklass)->type;
7913                 switch (basetype)
7914                 {
7915                         case MONO_TYPE_U1:
7916                         case MONO_TYPE_I1:
7917                         case MONO_TYPE_BOOLEAN:
7918                                 for (i = 0; i < alen; i++) {
7919                                         MonoBoolean val = *p++;
7920                                         mono_array_set (arr, MonoBoolean, i, val);
7921                                 }
7922                                 break;
7923                         case MONO_TYPE_CHAR:
7924                         case MONO_TYPE_U2:
7925                         case MONO_TYPE_I2:
7926                                 for (i = 0; i < alen; i++) {
7927                                         guint16 val = read16 (p);
7928                                         mono_array_set (arr, guint16, i, val);
7929                                         p += 2;
7930                                 }
7931                                 break;
7932                         case MONO_TYPE_R4:
7933                         case MONO_TYPE_U4:
7934                         case MONO_TYPE_I4:
7935                                 for (i = 0; i < alen; i++) {
7936                                         guint32 val = read32 (p);
7937                                         mono_array_set (arr, guint32, i, val);
7938                                         p += 4;
7939                                 }
7940                                 break;
7941                         case MONO_TYPE_R8:
7942                                 for (i = 0; i < alen; i++) {
7943                                         double val;
7944                                         readr8 (p, &val);
7945                                         mono_array_set (arr, double, i, val);
7946                                         p += 8;
7947                                 }
7948                                 break;
7949                         case MONO_TYPE_U8:
7950                         case MONO_TYPE_I8:
7951                                 for (i = 0; i < alen; i++) {
7952                                         guint64 val = read64 (p);
7953                                         mono_array_set (arr, guint64, i, val);
7954                                         p += 8;
7955                                 }
7956                                 break;
7957                         case MONO_TYPE_CLASS:
7958                         case MONO_TYPE_OBJECT:
7959                         case MONO_TYPE_STRING:
7960                                 for (i = 0; i < alen; i++) {
7961                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7962                                         mono_array_setref (arr, i, item);
7963                                 }
7964                                 break;
7965                         default:
7966                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7967                 }
7968                 *end=p;
7969                 return arr;
7970         }
7971         default:
7972                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7973         }
7974         return NULL;
7975 }
7976
7977 static MonoObject*
7978 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7979 {
7980         static MonoClass *klass;
7981         static MonoMethod *ctor;
7982         MonoObject *retval;
7983         void *params [2], *unboxed;
7984
7985         if (!klass)
7986                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7987         if (!ctor)
7988                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7989         
7990         params [0] = mono_type_get_object (mono_domain_get (), t);
7991         params [1] = val;
7992         retval = mono_object_new (mono_domain_get (), klass);
7993         unboxed = mono_object_unbox (retval);
7994         mono_runtime_invoke (ctor, unboxed, params, NULL);
7995
7996         return retval;
7997 }
7998
7999 static MonoObject*
8000 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8001 {
8002         static MonoClass *klass;
8003         static MonoMethod *ctor;
8004         MonoObject *retval;
8005         void *unboxed, *params [2];
8006
8007         if (!klass)
8008                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8009         if (!ctor)
8010                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8011
8012         params [0] = minfo;
8013         params [1] = typedarg;
8014         retval = mono_object_new (mono_domain_get (), klass);
8015         unboxed = mono_object_unbox (retval);
8016         mono_runtime_invoke (ctor, unboxed, params, NULL);
8017
8018         return retval;
8019 }
8020
8021 static gboolean
8022 type_is_reference (MonoType *type)
8023 {
8024         switch (type->type) {
8025         case MONO_TYPE_BOOLEAN:
8026         case MONO_TYPE_CHAR:
8027         case MONO_TYPE_U:
8028         case MONO_TYPE_I:
8029         case MONO_TYPE_U1:
8030         case MONO_TYPE_I1:
8031         case MONO_TYPE_U2:
8032         case MONO_TYPE_I2:
8033         case MONO_TYPE_U4:
8034         case MONO_TYPE_I4:
8035         case MONO_TYPE_U8:
8036         case MONO_TYPE_I8:
8037         case MONO_TYPE_R8:
8038         case MONO_TYPE_R4:
8039         case MONO_TYPE_VALUETYPE:
8040                 return FALSE;
8041         default:
8042                 return TRUE;
8043         }
8044 }
8045
8046 static void
8047 free_param_data (MonoMethodSignature *sig, void **params) {
8048         int i;
8049         for (i = 0; i < sig->param_count; ++i) {
8050                 if (!type_is_reference (sig->params [i]))
8051                         g_free (params [i]);
8052         }
8053 }
8054
8055 /*
8056  * Find the field index in the metadata FieldDef table.
8057  */
8058 static guint32
8059 find_field_index (MonoClass *klass, MonoClassField *field) {
8060         int i;
8061
8062         for (i = 0; i < klass->field.count; ++i) {
8063                 if (field == &klass->fields [i])
8064                         return klass->field.first + 1 + i;
8065         }
8066         return 0;
8067 }
8068
8069 /*
8070  * Find the property index in the metadata Property table.
8071  */
8072 static guint32
8073 find_property_index (MonoClass *klass, MonoProperty *property) {
8074         int i;
8075
8076         for (i = 0; i < klass->ext->property.count; ++i) {
8077                 if (property == &klass->ext->properties [i])
8078                         return klass->ext->property.first + 1 + i;
8079         }
8080         return 0;
8081 }
8082
8083 /*
8084  * Find the event index in the metadata Event table.
8085  */
8086 static guint32
8087 find_event_index (MonoClass *klass, MonoEvent *event) {
8088         int i;
8089
8090         for (i = 0; i < klass->ext->event.count; ++i) {
8091                 if (event == &klass->ext->events [i])
8092                         return klass->ext->event.first + 1 + i;
8093         }
8094         return 0;
8095 }
8096
8097 static MonoObject*
8098 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8099 {
8100         const char *p = (const char*)data;
8101         const char *named;
8102         guint32 i, j, num_named;
8103         MonoObject *attr;
8104         void *params_buf [32];
8105         void **params;
8106         MonoMethodSignature *sig;
8107
8108         mono_error_init (error);
8109
8110         mono_class_init (method->klass);
8111
8112         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8113                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8114                 return NULL;
8115         }
8116
8117         if (len == 0) {
8118                 attr = mono_object_new (mono_domain_get (), method->klass);
8119                 mono_runtime_invoke (method, attr, NULL, NULL);
8120                 return attr;
8121         }
8122
8123         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8124                 return NULL;
8125
8126         /*g_print ("got attr %s\n", method->klass->name);*/
8127
8128         sig = mono_method_signature (method);
8129         if (sig->param_count < 32)
8130                 params = params_buf;
8131         else
8132                 /* Allocate using GC so it gets GC tracking */
8133                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8134
8135         /* skip prolog */
8136         p += 2;
8137         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8138                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8139         }
8140
8141         named = p;
8142         attr = mono_object_new (mono_domain_get (), method->klass);
8143         mono_runtime_invoke (method, attr, params, NULL);
8144         free_param_data (method->signature, params);
8145         num_named = read16 (named);
8146         named += 2;
8147         for (j = 0; j < num_named; j++) {
8148                 gint name_len;
8149                 char *name, named_type, data_type;
8150                 named_type = *named++;
8151                 data_type = *named++; /* type of data */
8152                 if (data_type == MONO_TYPE_SZARRAY)
8153                         data_type = *named++;
8154                 if (data_type == MONO_TYPE_ENUM) {
8155                         gint type_len;
8156                         char *type_name;
8157                         type_len = mono_metadata_decode_blob_size (named, &named);
8158                         type_name = g_malloc (type_len + 1);
8159                         memcpy (type_name, named, type_len);
8160                         type_name [type_len] = 0;
8161                         named += type_len;
8162                         /* FIXME: lookup the type and check type consistency */
8163                         g_free (type_name);
8164                 }
8165                 name_len = mono_metadata_decode_blob_size (named, &named);
8166                 name = g_malloc (name_len + 1);
8167                 memcpy (name, named, name_len);
8168                 name [name_len] = 0;
8169                 named += name_len;
8170                 if (named_type == 0x53) {
8171                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8172                         void *val = load_cattr_value (image, field->type, named, &named);
8173                         mono_field_set_value (attr, field, val);
8174                         if (!type_is_reference (field->type))
8175                                 g_free (val);
8176                 } else if (named_type == 0x54) {
8177                         MonoProperty *prop;
8178                         void *pparams [1];
8179                         MonoType *prop_type;
8180
8181                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8182                         /* can we have more that 1 arg in a custom attr named property? */
8183                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8184                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8185                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8186                         mono_property_set_value (prop, attr, pparams, NULL);
8187                         if (!type_is_reference (prop_type))
8188                                 g_free (pparams [0]);
8189                 }
8190                 g_free (name);
8191         }
8192
8193         if (params != params_buf)
8194                 mono_gc_free_fixed (params);
8195
8196         return attr;
8197 }
8198         
8199 /*
8200  * mono_reflection_create_custom_attr_data_args:
8201  *
8202  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8203  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8204  * NAMED_ARG_INFO will contain information about the named arguments.
8205  */
8206 void
8207 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)
8208 {
8209         MonoArray *typedargs, *namedargs;
8210         MonoClass *attrklass;
8211         MonoDomain *domain;
8212         const char *p = (const char*)data;
8213         const char *named;
8214         guint32 i, j, num_named;
8215         CattrNamedArg *arginfo = NULL;
8216
8217         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8218                 return;
8219
8220         mono_class_init (method->klass);
8221
8222         *typed_args = NULL;
8223         *named_args = NULL;
8224         *named_arg_info = NULL;
8225         
8226         domain = mono_domain_get ();
8227
8228         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8229                 return;
8230
8231         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8232         
8233         /* skip prolog */
8234         p += 2;
8235         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8236                 MonoObject *obj;
8237                 void *val;
8238
8239                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8240                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8241                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8242                 mono_array_setref (typedargs, i, obj);
8243
8244                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8245                         g_free (val);
8246         }
8247
8248         named = p;
8249         num_named = read16 (named);
8250         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8251         named += 2;
8252         attrklass = method->klass;
8253
8254         arginfo = g_new0 (CattrNamedArg, num_named);
8255         *named_arg_info = arginfo;
8256
8257         for (j = 0; j < num_named; j++) {
8258                 gint name_len;
8259                 char *name, named_type, data_type;
8260                 named_type = *named++;
8261                 data_type = *named++; /* type of data */
8262                 if (data_type == MONO_TYPE_SZARRAY)
8263                         data_type = *named++;
8264                 if (data_type == MONO_TYPE_ENUM) {
8265                         gint type_len;
8266                         char *type_name;
8267                         type_len = mono_metadata_decode_blob_size (named, &named);
8268                         type_name = g_malloc (type_len + 1);
8269                         memcpy (type_name, named, type_len);
8270                         type_name [type_len] = 0;
8271                         named += type_len;
8272                         /* FIXME: lookup the type and check type consistency */
8273                         g_free (type_name);
8274                 }
8275                 name_len = mono_metadata_decode_blob_size (named, &named);
8276                 name = g_malloc (name_len + 1);
8277                 memcpy (name, named, name_len);
8278                 name [name_len] = 0;
8279                 named += name_len;
8280                 if (named_type == 0x53) {
8281                         MonoObject *obj;
8282                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8283                         void *val;
8284
8285                         arginfo [j].type = field->type;
8286                         arginfo [j].field = field;
8287
8288                         val = load_cattr_value (image, field->type, named, &named);
8289                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8290                         mono_array_setref (namedargs, j, obj);
8291                         if (!type_is_reference (field->type))
8292                                 g_free (val);
8293                 } else if (named_type == 0x54) {
8294                         MonoObject *obj;
8295                         MonoType *prop_type;
8296                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8297                         void *val;
8298
8299                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8300                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8301
8302                         arginfo [j].type = prop_type;
8303                         arginfo [j].prop = prop;
8304
8305                         val = load_cattr_value (image, prop_type, named, &named);
8306                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8307                         mono_array_setref (namedargs, j, obj);
8308                         if (!type_is_reference (prop_type))
8309                                 g_free (val);
8310                 }
8311                 g_free (name);
8312         }
8313
8314         *typed_args = typedargs;
8315         *named_args = namedargs;
8316 }
8317
8318 void
8319 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8320 {
8321         MonoDomain *domain;
8322         MonoArray *typedargs, *namedargs;
8323         MonoImage *image;
8324         MonoMethod *method;
8325         CattrNamedArg *arginfo;
8326         int i;
8327
8328         *ctor_args = NULL;
8329         *named_args = NULL;
8330
8331         if (len == 0)
8332                 return;
8333
8334         image = assembly->assembly->image;
8335         method = ref_method->method;
8336         domain = mono_object_domain (ref_method);
8337
8338         if (!mono_class_init (method->klass))
8339                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8340
8341         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8342         if (mono_loader_get_last_error ())
8343                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8344
8345         if (!typedargs || !namedargs)
8346                 return;
8347
8348         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8349                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8350                 MonoObject *typedarg;
8351
8352                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8353                 mono_array_setref (typedargs, i, typedarg);
8354         }
8355
8356         for (i = 0; i < mono_array_length (namedargs); ++i) {
8357                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8358                 MonoObject *typedarg, *namedarg, *minfo;
8359
8360                 if (arginfo [i].prop)
8361                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8362                 else
8363                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8364
8365                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8366                 namedarg = create_cattr_named_arg (minfo, typedarg);
8367
8368                 mono_array_setref (namedargs, i, namedarg);
8369         }
8370
8371         *ctor_args = typedargs;
8372         *named_args = namedargs;
8373 }
8374
8375 static MonoObject*
8376 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8377 {
8378         static MonoMethod *ctor;
8379         MonoDomain *domain;
8380         MonoObject *attr;
8381         void *params [4];
8382
8383         g_assert (image->assembly);
8384
8385         if (!ctor)
8386                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8387
8388         domain = mono_domain_get ();
8389         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8390         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8391         params [1] = mono_assembly_get_object (domain, image->assembly);
8392         params [2] = (gpointer)&cattr->data;
8393         params [3] = &cattr->data_size;
8394         mono_runtime_invoke (ctor, attr, params, NULL);
8395         return attr;
8396 }
8397
8398 static MonoArray*
8399 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8400 {
8401         MonoArray *result;
8402         MonoObject *attr;
8403         int i, n;
8404
8405         mono_error_init (error);
8406
8407         n = 0;
8408         for (i = 0; i < cinfo->num_attrs; ++i) {
8409                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8410                         n ++;
8411         }
8412
8413         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8414         n = 0;
8415         for (i = 0; i < cinfo->num_attrs; ++i) {
8416                 if (!cinfo->attrs [i].ctor)
8417                         /* The cattr type is not finished yet */
8418                         /* We should include the type name but cinfo doesn't contain it */
8419                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8420                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8421                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8422                         if (!mono_error_ok (error))
8423                                 return result;
8424                         mono_array_setref (result, n, attr);
8425                         n ++;
8426                 }
8427         }
8428         return result;
8429 }
8430
8431 MonoArray*
8432 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8433 {
8434         MonoError error;
8435
8436         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8437 }
8438
8439 static MonoArray*
8440 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8441 {
8442         MonoArray *result;
8443         MonoObject *attr;
8444         int i;
8445         
8446         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8447         for (i = 0; i < cinfo->num_attrs; ++i) {
8448                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8449                 mono_array_setref (result, i, attr);
8450         }
8451         return result;
8452 }
8453
8454 /**
8455  * mono_custom_attrs_from_index:
8456  *
8457  * Returns: NULL if no attributes are found or if a loading error occurs.
8458  */
8459 MonoCustomAttrInfo*
8460 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8461 {
8462         guint32 mtoken, i, len;
8463         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8464         MonoTableInfo *ca;
8465         MonoCustomAttrInfo *ainfo;
8466         GList *tmp, *list = NULL;
8467         const char *data;
8468
8469         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8470
8471         i = mono_metadata_custom_attrs_from_index (image, idx);
8472         if (!i)
8473                 return NULL;
8474         i --;
8475         while (i < ca->rows) {
8476                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8477                         break;
8478                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8479                 ++i;
8480         }
8481         len = g_list_length (list);
8482         if (!len)
8483                 return NULL;
8484         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8485         ainfo->num_attrs = len;
8486         ainfo->image = image;
8487         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8488                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8489                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8490                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8491                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8492                         mtoken |= MONO_TOKEN_METHOD_DEF;
8493                         break;
8494                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8495                         mtoken |= MONO_TOKEN_MEMBER_REF;
8496                         break;
8497                 default:
8498                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8499                         break;
8500                 }
8501                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8502                 if (!ainfo->attrs [i].ctor) {
8503                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8504                         g_list_free (list);
8505                         g_free (ainfo);
8506                         return NULL;
8507                 }
8508
8509                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8510                         /*FIXME raising an exception here doesn't make any sense*/
8511                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8512                         g_list_free (list);
8513                         g_free (ainfo);
8514                         return NULL;
8515                 }
8516                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8517                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8518                 ainfo->attrs [i].data = (guchar*)data;
8519         }
8520         g_list_free (list);
8521
8522         return ainfo;
8523 }
8524
8525 MonoCustomAttrInfo*
8526 mono_custom_attrs_from_method (MonoMethod *method)
8527 {
8528         guint32 idx;
8529
8530         /*
8531          * An instantiated method has the same cattrs as the generic method definition.
8532          *
8533          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8534          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8535          */
8536         if (method->is_inflated)
8537                 method = ((MonoMethodInflated *) method)->declaring;
8538         
8539         if (method->dynamic || method->klass->image->dynamic)
8540                 return lookup_custom_attr (method->klass->image, method);
8541
8542         if (!method->token)
8543                 /* Synthetic methods */
8544                 return NULL;
8545
8546         idx = mono_method_get_index (method);
8547         idx <<= MONO_CUSTOM_ATTR_BITS;
8548         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8549         return mono_custom_attrs_from_index (method->klass->image, idx);
8550 }
8551
8552 MonoCustomAttrInfo*
8553 mono_custom_attrs_from_class (MonoClass *klass)
8554 {
8555         guint32 idx;
8556
8557         if (klass->generic_class)
8558                 klass = klass->generic_class->container_class;
8559
8560         if (klass->image->dynamic)
8561                 return lookup_custom_attr (klass->image, klass);
8562
8563         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8564                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8565                 idx <<= MONO_CUSTOM_ATTR_BITS;
8566                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8567         } else {
8568                 idx = mono_metadata_token_index (klass->type_token);
8569                 idx <<= MONO_CUSTOM_ATTR_BITS;
8570                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8571         }
8572         return mono_custom_attrs_from_index (klass->image, idx);
8573 }
8574
8575 MonoCustomAttrInfo*
8576 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8577 {
8578         guint32 idx;
8579         
8580         if (assembly->image->dynamic)
8581                 return lookup_custom_attr (assembly->image, assembly);
8582         idx = 1; /* there is only one assembly */
8583         idx <<= MONO_CUSTOM_ATTR_BITS;
8584         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8585         return mono_custom_attrs_from_index (assembly->image, idx);
8586 }
8587
8588 static MonoCustomAttrInfo*
8589 mono_custom_attrs_from_module (MonoImage *image)
8590 {
8591         guint32 idx;
8592         
8593         if (image->dynamic)
8594                 return lookup_custom_attr (image, image);
8595         idx = 1; /* there is only one module */
8596         idx <<= MONO_CUSTOM_ATTR_BITS;
8597         idx |= MONO_CUSTOM_ATTR_MODULE;
8598         return mono_custom_attrs_from_index (image, idx);
8599 }
8600
8601 MonoCustomAttrInfo*
8602 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8603 {
8604         guint32 idx;
8605         
8606         if (klass->image->dynamic) {
8607                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8608                 return lookup_custom_attr (klass->image, property);
8609         }
8610         idx = find_property_index (klass, property);
8611         idx <<= MONO_CUSTOM_ATTR_BITS;
8612         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8613         return mono_custom_attrs_from_index (klass->image, idx);
8614 }
8615
8616 MonoCustomAttrInfo*
8617 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8618 {
8619         guint32 idx;
8620         
8621         if (klass->image->dynamic) {
8622                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8623                 return lookup_custom_attr (klass->image, event);
8624         }
8625         idx = find_event_index (klass, event);
8626         idx <<= MONO_CUSTOM_ATTR_BITS;
8627         idx |= MONO_CUSTOM_ATTR_EVENT;
8628         return mono_custom_attrs_from_index (klass->image, idx);
8629 }
8630
8631 MonoCustomAttrInfo*
8632 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8633 {
8634         guint32 idx;
8635         if (klass->image->dynamic) {
8636                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8637                 return lookup_custom_attr (klass->image, field);
8638         }
8639         idx = find_field_index (klass, field);
8640         idx <<= MONO_CUSTOM_ATTR_BITS;
8641         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8642         return mono_custom_attrs_from_index (klass->image, idx);
8643 }
8644
8645 MonoCustomAttrInfo*
8646 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8647 {
8648         MonoTableInfo *ca;
8649         guint32 i, idx, method_index;
8650         guint32 param_list, param_last, param_pos, found;
8651         MonoImage *image;
8652         MonoReflectionMethodAux *aux;
8653
8654         /*
8655          * An instantiated method has the same cattrs as the generic method definition.
8656          *
8657          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8658          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8659          */
8660         if (method->is_inflated)
8661                 method = ((MonoMethodInflated *) method)->declaring;
8662
8663         if (method->klass->image->dynamic) {
8664                 MonoCustomAttrInfo *res, *ainfo;
8665                 int size;
8666
8667                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8668                 if (!aux || !aux->param_cattr)
8669                         return NULL;
8670
8671                 /* Need to copy since it will be freed later */
8672                 ainfo = aux->param_cattr [param];
8673                 if (!ainfo)
8674                         return NULL;
8675                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8676                 res = g_malloc0 (size);
8677                 memcpy (res, ainfo, size);
8678                 return res;
8679         }
8680
8681         image = method->klass->image;
8682         method_index = mono_method_get_index (method);
8683         if (!method_index)
8684                 return NULL;
8685         ca = &image->tables [MONO_TABLE_METHOD];
8686
8687         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8688         if (method_index == ca->rows) {
8689                 ca = &image->tables [MONO_TABLE_PARAM];
8690                 param_last = ca->rows + 1;
8691         } else {
8692                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8693                 ca = &image->tables [MONO_TABLE_PARAM];
8694         }
8695         found = FALSE;
8696         for (i = param_list; i < param_last; ++i) {
8697                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8698                 if (param_pos == param) {
8699                         found = TRUE;
8700                         break;
8701                 }
8702         }
8703         if (!found)
8704                 return NULL;
8705         idx = i;
8706         idx <<= MONO_CUSTOM_ATTR_BITS;
8707         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8708         return mono_custom_attrs_from_index (image, idx);
8709 }
8710
8711 gboolean
8712 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8713 {
8714         int i;
8715         MonoClass *klass;
8716         for (i = 0; i < ainfo->num_attrs; ++i) {
8717                 klass = ainfo->attrs [i].ctor->klass;
8718                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8719                         return TRUE;
8720         }
8721         return FALSE;
8722 }
8723
8724 MonoObject*
8725 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8726 {
8727         int i, attr_index;
8728         MonoClass *klass;
8729         MonoArray *attrs;
8730
8731         attr_index = -1;
8732         for (i = 0; i < ainfo->num_attrs; ++i) {
8733                 klass = ainfo->attrs [i].ctor->klass;
8734                 if (mono_class_has_parent (klass, attr_klass)) {
8735                         attr_index = i;
8736                         break;
8737                 }
8738         }
8739         if (attr_index == -1)
8740                 return NULL;
8741
8742         attrs = mono_custom_attrs_construct (ainfo);
8743         if (attrs)
8744                 return mono_array_get (attrs, MonoObject*, attr_index);
8745         else
8746                 return NULL;
8747 }
8748
8749 /*
8750  * mono_reflection_get_custom_attrs_info:
8751  * @obj: a reflection object handle
8752  *
8753  * Return the custom attribute info for attributes defined for the
8754  * reflection handle @obj. The objects.
8755  *
8756  * FIXME this function leaks like a sieve for SRE objects.
8757  */
8758 MonoCustomAttrInfo*
8759 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8760 {
8761         MonoClass *klass;
8762         MonoCustomAttrInfo *cinfo = NULL;
8763         
8764         klass = obj->vtable->klass;
8765         if (klass == mono_defaults.monotype_class) {
8766                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8767                 klass = mono_class_from_mono_type (type);
8768                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8769                 cinfo = mono_custom_attrs_from_class (klass);
8770         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8771                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8772                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8773         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8774                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8775                 cinfo = mono_custom_attrs_from_module (module->image);
8776         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8777                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8778                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8779         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8780                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8781                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8782         } else if (strcmp ("MonoField", klass->name) == 0) {
8783                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8784                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8785         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8786                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8787                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8788         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8789                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8790                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8791         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8792                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8793                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8794                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8795                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8796                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8797                 } else if (is_sr_mono_property (member_class)) {
8798                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8799                         MonoMethod *method;
8800                         if (!(method = prop->property->get))
8801                                 method = prop->property->set;
8802                         g_assert (method);
8803
8804                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8805                 } 
8806 #ifndef DISABLE_REFLECTION_EMIT
8807                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8808                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8809                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8810                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8811                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8812                         MonoMethod *method = NULL;
8813                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8814                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8815                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8816                                 method = ((MonoReflectionMethod *)c->cb)->method;
8817                         else
8818                                 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));
8819
8820                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8821                 } 
8822 #endif
8823                 else {
8824                         char *type_name = mono_type_get_full_name (member_class);
8825                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8826                         MonoException *ex = mono_get_exception_not_supported  (msg);
8827                         g_free (type_name);
8828                         g_free (msg);
8829                         mono_raise_exception (ex);
8830                 }
8831         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8832                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8833                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8834         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8835                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8836                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8837         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8838                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8839                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8840         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8841                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8842                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8843         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8844                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8845                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8846         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8847                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8848                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8849         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8850                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8851                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8852         } else { /* handle other types here... */
8853                 g_error ("get custom attrs not yet supported for %s", klass->name);
8854         }
8855
8856         return cinfo;
8857 }
8858
8859 /*
8860  * mono_reflection_get_custom_attrs_by_type:
8861  * @obj: a reflection object handle
8862  *
8863  * Return an array with all the custom attributes defined of the
8864  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8865  * of that type are returned. The objects are fully build. Return NULL if a loading error
8866  * occurs.
8867  */
8868 MonoArray*
8869 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8870 {
8871         MonoArray *result;
8872         MonoCustomAttrInfo *cinfo;
8873
8874         mono_error_init (error);
8875
8876         cinfo = mono_reflection_get_custom_attrs_info (obj);
8877         if (cinfo) {
8878                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8879                 if (!cinfo->cached)
8880                         mono_custom_attrs_free (cinfo);
8881         } else {
8882                 if (mono_loader_get_last_error ())
8883                         return NULL;
8884                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8885         }
8886
8887         return result;
8888 }
8889
8890 /*
8891  * mono_reflection_get_custom_attrs:
8892  * @obj: a reflection object handle
8893  *
8894  * Return an array with all the custom attributes defined of the
8895  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8896  * occurs.
8897  */
8898 MonoArray*
8899 mono_reflection_get_custom_attrs (MonoObject *obj)
8900 {
8901         MonoError error;
8902
8903         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8904 }
8905
8906 /*
8907  * mono_reflection_get_custom_attrs_data:
8908  * @obj: a reflection obj handle
8909  *
8910  * Returns an array of System.Reflection.CustomAttributeData,
8911  * which include information about attributes reflected on
8912  * types loaded using the Reflection Only methods
8913  */
8914 MonoArray*
8915 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8916 {
8917         MonoArray *result;
8918         MonoCustomAttrInfo *cinfo;
8919
8920         cinfo = mono_reflection_get_custom_attrs_info (obj);
8921         if (cinfo) {
8922                 result = mono_custom_attrs_data_construct (cinfo);
8923                 if (!cinfo->cached)
8924                         mono_custom_attrs_free (cinfo);
8925         } else
8926                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8927
8928         return result;
8929 }
8930
8931 static MonoReflectionType*
8932 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8933 {
8934         static MonoMethod *method_get_underlying_system_type = NULL;
8935         MonoMethod *usertype_method;
8936
8937         if (!method_get_underlying_system_type)
8938                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8939         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8940         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8941 }
8942
8943
8944 static gboolean
8945 is_corlib_type (MonoClass *class)
8946 {
8947         return class->image == mono_defaults.corlib;
8948 }
8949
8950 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8951         static MonoClass *cached_class; \
8952         if (cached_class) \
8953                 return cached_class == _class; \
8954         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8955                 cached_class = _class; \
8956                 return TRUE; \
8957         } \
8958         return FALSE; \
8959 } while (0) \
8960
8961
8962 #ifndef DISABLE_REFLECTION_EMIT
8963 static gboolean
8964 is_sre_array (MonoClass *class)
8965 {
8966         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8967 }
8968
8969 static gboolean
8970 is_sre_byref (MonoClass *class)
8971 {
8972         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8973 }
8974
8975 static gboolean
8976 is_sre_pointer (MonoClass *class)
8977 {
8978         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8979 }
8980
8981 static gboolean
8982 is_sre_generic_instance (MonoClass *class)
8983 {
8984         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8985 }
8986
8987 static gboolean
8988 is_sre_type_builder (MonoClass *class)
8989 {
8990         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8991 }
8992
8993 static gboolean
8994 is_sre_method_builder (MonoClass *class)
8995 {
8996         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8997 }
8998
8999 static gboolean
9000 is_sre_ctor_builder (MonoClass *class)
9001 {
9002         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9003 }
9004
9005 static gboolean
9006 is_sre_field_builder (MonoClass *class)
9007 {
9008         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9009 }
9010
9011 static gboolean
9012 is_sre_method_on_tb_inst (MonoClass *class)
9013 {
9014         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9015 }
9016
9017 static gboolean
9018 is_sre_ctor_on_tb_inst (MonoClass *class)
9019 {
9020         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9021 }
9022
9023 MonoType*
9024 mono_reflection_type_get_handle (MonoReflectionType* ref)
9025 {
9026         MonoClass *class;
9027         if (!ref)
9028                 return NULL;
9029         if (ref->type)
9030                 return ref->type;
9031
9032         if (is_usertype (ref)) {
9033                 ref = mono_reflection_type_get_underlying_system_type (ref);
9034                 if (ref == NULL || is_usertype (ref))
9035                         return NULL;
9036                 if (ref->type)
9037                         return ref->type;
9038         }
9039
9040         class = mono_object_class (ref);
9041
9042         if (is_sre_array (class)) {
9043                 MonoType *res;
9044                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9045                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9046                 g_assert (base);
9047                 if (sre_array->rank == 0) //single dimentional array
9048                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9049                 else
9050                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9051                 sre_array->type.type = res;
9052                 return res;
9053         } else if (is_sre_byref (class)) {
9054                 MonoType *res;
9055                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9056                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9057                 g_assert (base);
9058                 res = &mono_class_from_mono_type (base)->this_arg;
9059                 sre_byref->type.type = res;
9060                 return res;
9061         } else if (is_sre_pointer (class)) {
9062                 MonoType *res;
9063                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9064                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9065                 g_assert (base);
9066                 res = &mono_ptr_class_get (base)->byval_arg;
9067                 sre_pointer->type.type = res;
9068                 return res;
9069         } else if (is_sre_generic_instance (class)) {
9070                 MonoType *res, **types;
9071                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9072                 int i, count;
9073
9074                 count = mono_array_length (gclass->type_arguments);
9075                 types = g_new0 (MonoType*, count);
9076                 for (i = 0; i < count; ++i) {
9077                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9078                         types [i] = mono_reflection_type_get_handle (t);
9079                         if (!types[i]) {
9080                                 g_free (types);
9081                                 return NULL;
9082                         }
9083                 }
9084
9085                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9086                 g_free (types);
9087                 g_assert (res);
9088                 gclass->type.type = res;
9089                 return res;
9090         }
9091
9092         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9093         return NULL;
9094 }
9095
9096
9097
9098 void
9099 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9100 {
9101         mono_reflection_type_get_handle (type);
9102 }
9103
9104 void
9105 mono_reflection_register_with_runtime (MonoReflectionType *type)
9106 {
9107         MonoType *res = mono_reflection_type_get_handle (type);
9108         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9109         MonoClass *class;
9110
9111         if (!res)
9112                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9113
9114         class = mono_class_from_mono_type (res);
9115
9116         mono_loader_lock (); /*same locking as mono_type_get_object*/
9117         mono_domain_lock (domain);
9118
9119         if (!class->image->dynamic) {
9120                 mono_class_setup_supertypes (class);
9121         } else {
9122                 if (!domain->type_hash)
9123                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9124                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9125                 mono_g_hash_table_insert (domain->type_hash, res, type);
9126         }
9127         mono_domain_unlock (domain);
9128         mono_loader_unlock ();
9129 }
9130
9131 /**
9132  * LOCKING: Assumes the loader lock is held.
9133  */
9134 static MonoMethodSignature*
9135 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9136         MonoMethodSignature *sig;
9137         int count, i;
9138
9139         count = parameters? mono_array_length (parameters): 0;
9140
9141         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9142         sig->param_count = count;
9143         sig->sentinelpos = -1; /* FIXME */
9144         for (i = 0; i < count; ++i)
9145                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9146         return sig;
9147 }
9148
9149 /**
9150  * LOCKING: Assumes the loader lock is held.
9151  */
9152 static MonoMethodSignature*
9153 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9154         MonoMethodSignature *sig;
9155
9156         sig = parameters_to_signature (image, ctor->parameters);
9157         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9158         sig->ret = &mono_defaults.void_class->byval_arg;
9159         return sig;
9160 }
9161
9162 /**
9163  * LOCKING: Assumes the loader lock is held.
9164  */
9165 static MonoMethodSignature*
9166 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9167         MonoMethodSignature *sig;
9168
9169         sig = parameters_to_signature (image, method->parameters);
9170         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9171         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9172         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9173         return sig;
9174 }
9175
9176 static MonoMethodSignature*
9177 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9178         MonoMethodSignature *sig;
9179
9180         sig = parameters_to_signature (NULL, method->parameters);
9181         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9182         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9183         sig->generic_param_count = 0;
9184         return sig;
9185 }
9186
9187 static void
9188 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9189 {
9190         MonoClass *klass = mono_object_class (prop);
9191         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9192                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9193                 *name = mono_string_to_utf8 (pb->name);
9194                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9195         } else {
9196                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9197                 *name = g_strdup (p->property->name);
9198                 if (p->property->get)
9199                         *type = mono_method_signature (p->property->get)->ret;
9200                 else
9201                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9202         }
9203 }
9204
9205 static void
9206 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9207 {
9208         MonoClass *klass = mono_object_class (field);
9209         if (strcmp (klass->name, "FieldBuilder") == 0) {
9210                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9211                 *name = mono_string_to_utf8 (fb->name);
9212                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9213         } else {
9214                 MonoReflectionField *f = (MonoReflectionField *)field;
9215                 *name = g_strdup (mono_field_get_name (f->field));
9216                 *type = f->field->type;
9217         }
9218 }
9219
9220 #else /* DISABLE_REFLECTION_EMIT */
9221
9222 void
9223 mono_reflection_register_with_runtime (MonoReflectionType *type)
9224 {
9225         /* This is empty */
9226 }
9227
9228 static gboolean
9229 is_sre_type_builder (MonoClass *class)
9230 {
9231         return FALSE;
9232 }
9233
9234 static gboolean
9235 is_sre_generic_instance (MonoClass *class)
9236 {
9237         return FALSE;
9238 }
9239
9240 static void
9241 init_type_builder_generics (MonoObject *type)
9242 {
9243 }
9244
9245 #endif /* !DISABLE_REFLECTION_EMIT */
9246
9247
9248 static gboolean
9249 is_sr_mono_field (MonoClass *class)
9250 {
9251         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9252 }
9253
9254 static gboolean
9255 is_sr_mono_property (MonoClass *class)
9256 {
9257         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9258 }
9259
9260 static gboolean
9261 is_sr_mono_method (MonoClass *class)
9262 {
9263         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9264 }
9265
9266 static gboolean
9267 is_sr_mono_cmethod (MonoClass *class)
9268 {
9269         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9270 }
9271
9272 static gboolean
9273 is_sr_mono_generic_method (MonoClass *class)
9274 {
9275         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9276 }
9277
9278 static gboolean
9279 is_sr_mono_generic_cmethod (MonoClass *class)
9280 {
9281         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9282 }
9283
9284 gboolean
9285 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9286 {
9287         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9288 }
9289
9290 static gboolean
9291 is_usertype (MonoReflectionType *ref)
9292 {
9293         MonoClass *class = mono_object_class (ref);
9294         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9295 }
9296
9297 static MonoReflectionType*
9298 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9299 {
9300         if (!type || type->type)
9301                 return type;
9302
9303         if (is_usertype (type)) {
9304                 type = mono_reflection_type_get_underlying_system_type (type);
9305                 if (is_usertype (type))
9306                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9307         }
9308
9309         return type;
9310 }
9311 /*
9312  * Encode a value in a custom attribute stream of bytes.
9313  * The value to encode is either supplied as an object in argument val
9314  * (valuetypes are boxed), or as a pointer to the data in the
9315  * argument argval.
9316  * @type represents the type of the value
9317  * @buffer is the start of the buffer
9318  * @p the current position in the buffer
9319  * @buflen contains the size of the buffer and is used to return the new buffer size
9320  * if this needs to be realloced.
9321  * @retbuffer and @retp return the start and the position of the buffer
9322  */
9323 static void
9324 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9325 {
9326         MonoTypeEnum simple_type;
9327         
9328         if ((p-buffer) + 10 >= *buflen) {
9329                 char *newbuf;
9330                 *buflen *= 2;
9331                 newbuf = g_realloc (buffer, *buflen);
9332                 p = newbuf + (p-buffer);
9333                 buffer = newbuf;
9334         }
9335         if (!argval)
9336                 argval = ((char*)arg + sizeof (MonoObject));
9337         simple_type = type->type;
9338 handle_enum:
9339         switch (simple_type) {
9340         case MONO_TYPE_BOOLEAN:
9341         case MONO_TYPE_U1:
9342         case MONO_TYPE_I1:
9343                 *p++ = *argval;
9344                 break;
9345         case MONO_TYPE_CHAR:
9346         case MONO_TYPE_U2:
9347         case MONO_TYPE_I2:
9348                 swap_with_size (p, argval, 2, 1);
9349                 p += 2;
9350                 break;
9351         case MONO_TYPE_U4:
9352         case MONO_TYPE_I4:
9353         case MONO_TYPE_R4:
9354                 swap_with_size (p, argval, 4, 1);
9355                 p += 4;
9356                 break;
9357         case MONO_TYPE_R8:
9358 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9359                 p [0] = argval [4];
9360                 p [1] = argval [5];
9361                 p [2] = argval [6];
9362                 p [3] = argval [7];
9363                 p [4] = argval [0];
9364                 p [5] = argval [1];
9365                 p [6] = argval [2];
9366                 p [7] = argval [3];
9367 #else
9368                 swap_with_size (p, argval, 8, 1);
9369 #endif
9370                 p += 8;
9371                 break;
9372         case MONO_TYPE_U8:
9373         case MONO_TYPE_I8:
9374                 swap_with_size (p, argval, 8, 1);
9375                 p += 8;
9376                 break;
9377         case MONO_TYPE_VALUETYPE:
9378                 if (type->data.klass->enumtype) {
9379                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9380                         goto handle_enum;
9381                 } else {
9382                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9383                 }
9384                 break;
9385         case MONO_TYPE_STRING: {
9386                 char *str;
9387                 guint32 slen;
9388                 if (!arg) {
9389                         *p++ = 0xFF;
9390                         break;
9391                 }
9392                 str = mono_string_to_utf8 ((MonoString*)arg);
9393                 slen = strlen (str);
9394                 if ((p-buffer) + 10 + slen >= *buflen) {
9395                         char *newbuf;
9396                         *buflen *= 2;
9397                         *buflen += slen;
9398                         newbuf = g_realloc (buffer, *buflen);
9399                         p = newbuf + (p-buffer);
9400                         buffer = newbuf;
9401                 }
9402                 mono_metadata_encode_value (slen, p, &p);
9403                 memcpy (p, str, slen);
9404                 p += slen;
9405                 g_free (str);
9406                 break;
9407         }
9408         case MONO_TYPE_CLASS: {
9409                 char *str;
9410                 guint32 slen;
9411                 if (!arg) {
9412                         *p++ = 0xFF;
9413                         break;
9414                 }
9415 handle_type:
9416                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9417                 slen = strlen (str);
9418                 if ((p-buffer) + 10 + slen >= *buflen) {
9419                         char *newbuf;
9420                         *buflen *= 2;
9421                         *buflen += slen;
9422                         newbuf = g_realloc (buffer, *buflen);
9423                         p = newbuf + (p-buffer);
9424                         buffer = newbuf;
9425                 }
9426                 mono_metadata_encode_value (slen, p, &p);
9427                 memcpy (p, str, slen);
9428                 p += slen;
9429                 g_free (str);
9430                 break;
9431         }
9432         case MONO_TYPE_SZARRAY: {
9433                 int len, i;
9434                 MonoClass *eclass, *arg_eclass;
9435
9436                 if (!arg) {
9437                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9438                         break;
9439                 }
9440                 len = mono_array_length ((MonoArray*)arg);
9441                 *p++ = len & 0xff;
9442                 *p++ = (len >> 8) & 0xff;
9443                 *p++ = (len >> 16) & 0xff;
9444                 *p++ = (len >> 24) & 0xff;
9445                 *retp = p;
9446                 *retbuffer = buffer;
9447                 eclass = type->data.klass;
9448                 arg_eclass = mono_object_class (arg)->element_class;
9449
9450                 if (!eclass) {
9451                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9452                         eclass = mono_defaults.object_class;
9453                 }
9454                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9455                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9456                         int elsize = mono_class_array_element_size (arg_eclass);
9457                         for (i = 0; i < len; ++i) {
9458                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9459                                 elptr += elsize;
9460                         }
9461                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9462                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9463                         int elsize = mono_class_array_element_size (eclass);
9464                         for (i = 0; i < len; ++i) {
9465                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9466                                 elptr += elsize;
9467                         }
9468                 } else {
9469                         for (i = 0; i < len; ++i) {
9470                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9471                         }
9472                 }
9473                 break;
9474         }
9475         case MONO_TYPE_OBJECT: {
9476                 MonoClass *klass;
9477                 char *str;
9478                 guint32 slen;
9479
9480                 /*
9481                  * The parameter type is 'object' but the type of the actual
9482                  * argument is not. So we have to add type information to the blob
9483                  * too. This is completely undocumented in the spec.
9484                  */
9485
9486                 if (arg == NULL) {
9487                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9488                         *p++ = 0xFF;
9489                         break;
9490                 }
9491                 
9492                 klass = mono_object_class (arg);
9493
9494                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9495                         *p++ = 0x50;
9496                         goto handle_type;
9497                 } else if (klass->enumtype) {
9498                         *p++ = 0x55;
9499                 } else if (klass == mono_defaults.string_class) {
9500                         simple_type = MONO_TYPE_STRING;
9501                         *p++ = 0x0E;
9502                         goto handle_enum;
9503                 } else if (klass->rank == 1) {
9504                         *p++ = 0x1D;
9505                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9506                                 /* See Partition II, Appendix B3 */
9507                                 *p++ = 0x51;
9508                         else
9509                                 *p++ = klass->element_class->byval_arg.type;
9510                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9511                         break;
9512                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9513                         *p++ = simple_type = klass->byval_arg.type;
9514                         goto handle_enum;
9515                 } else {
9516                         g_error ("unhandled type in custom attr");
9517                 }
9518                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9519                 slen = strlen (str);
9520                 if ((p-buffer) + 10 + slen >= *buflen) {
9521                         char *newbuf;
9522                         *buflen *= 2;
9523                         *buflen += slen;
9524                         newbuf = g_realloc (buffer, *buflen);
9525                         p = newbuf + (p-buffer);
9526                         buffer = newbuf;
9527                 }
9528                 mono_metadata_encode_value (slen, p, &p);
9529                 memcpy (p, str, slen);
9530                 p += slen;
9531                 g_free (str);
9532                 simple_type = mono_class_enum_basetype (klass)->type;
9533                 goto handle_enum;
9534         }
9535         default:
9536                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9537         }
9538         *retp = p;
9539         *retbuffer = buffer;
9540 }
9541
9542 static void
9543 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9544 {
9545         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9546                 char *str = type_get_qualified_name (type, NULL);
9547                 int slen = strlen (str);
9548
9549                 *p++ = 0x55;
9550                 /*
9551                  * This seems to be optional...
9552                  * *p++ = 0x80;
9553                  */
9554                 mono_metadata_encode_value (slen, p, &p);
9555                 memcpy (p, str, slen);
9556                 p += slen;
9557                 g_free (str);
9558         } else if (type->type == MONO_TYPE_OBJECT) {
9559                 *p++ = 0x51;
9560         } else if (type->type == MONO_TYPE_CLASS) {
9561                 /* it should be a type: encode_cattr_value () has the check */
9562                 *p++ = 0x50;
9563         } else {
9564                 mono_metadata_encode_value (type->type, p, &p);
9565                 if (type->type == MONO_TYPE_SZARRAY)
9566                         /* See the examples in Partition VI, Annex B */
9567                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9568         }
9569
9570         *retp = p;
9571 }
9572
9573 #ifndef DISABLE_REFLECTION_EMIT
9574 static void
9575 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9576 {
9577         int len;
9578         /* Preallocate a large enough buffer */
9579         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9580                 char *str = type_get_qualified_name (type, NULL);
9581                 len = strlen (str);
9582                 g_free (str);
9583         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9584                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9585                 len = strlen (str);
9586                 g_free (str);
9587         } else {
9588                 len = 0;
9589         }
9590         len += strlen (name);
9591
9592         if ((p-buffer) + 20 + len >= *buflen) {
9593                 char *newbuf;
9594                 *buflen *= 2;
9595                 *buflen += len;
9596                 newbuf = g_realloc (buffer, *buflen);
9597                 p = newbuf + (p-buffer);
9598                 buffer = newbuf;
9599         }
9600
9601         encode_field_or_prop_type (type, p, &p);
9602
9603         len = strlen (name);
9604         mono_metadata_encode_value (len, p, &p);
9605         memcpy (p, name, len);
9606         p += len;
9607         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9608         *retp = p;
9609         *retbuffer = buffer;
9610 }
9611
9612 /*
9613  * mono_reflection_get_custom_attrs_blob:
9614  * @ctor: custom attribute constructor
9615  * @ctorArgs: arguments o the constructor
9616  * @properties:
9617  * @propValues:
9618  * @fields:
9619  * @fieldValues:
9620  * 
9621  * Creates the blob of data that needs to be saved in the metadata and that represents
9622  * the custom attributed described by @ctor, @ctorArgs etc.
9623  * Returns: a Byte array representing the blob of data.
9624  */
9625 MonoArray*
9626 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9627 {
9628         MonoArray *result;
9629         MonoMethodSignature *sig;
9630         MonoObject *arg;
9631         char *buffer, *p;
9632         guint32 buflen, i;
9633
9634         MONO_ARCH_SAVE_REGS;
9635
9636         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9637                 /* sig is freed later so allocate it in the heap */
9638                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9639         } else {
9640                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9641         }
9642
9643         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9644         buflen = 256;
9645         p = buffer = g_malloc (buflen);
9646         /* write the prolog */
9647         *p++ = 1;
9648         *p++ = 0;
9649         for (i = 0; i < sig->param_count; ++i) {
9650                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9651                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9652         }
9653         i = 0;
9654         if (properties)
9655                 i += mono_array_length (properties);
9656         if (fields)
9657                 i += mono_array_length (fields);
9658         *p++ = i & 0xff;
9659         *p++ = (i >> 8) & 0xff;
9660         if (properties) {
9661                 MonoObject *prop;
9662                 for (i = 0; i < mono_array_length (properties); ++i) {
9663                         MonoType *ptype;
9664                         char *pname;
9665
9666                         prop = mono_array_get (properties, gpointer, i);
9667                         get_prop_name_and_type (prop, &pname, &ptype);
9668                         *p++ = 0x54; /* PROPERTY signature */
9669                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9670                         g_free (pname);
9671                 }
9672         }
9673
9674         if (fields) {
9675                 MonoObject *field;
9676                 for (i = 0; i < mono_array_length (fields); ++i) {
9677                         MonoType *ftype;
9678                         char *fname;
9679
9680                         field = mono_array_get (fields, gpointer, i);
9681                         get_field_name_and_type (field, &fname, &ftype);
9682                         *p++ = 0x53; /* FIELD signature */
9683                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9684                         g_free (fname);
9685                 }
9686         }
9687
9688         g_assert (p - buffer <= buflen);
9689         buflen = p - buffer;
9690         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9691         p = mono_array_addr (result, char, 0);
9692         memcpy (p, buffer, buflen);
9693         g_free (buffer);
9694         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9695                 g_free (sig);
9696         return result;
9697 }
9698
9699 /*
9700  * mono_reflection_setup_internal_class:
9701  * @tb: a TypeBuilder object
9702  *
9703  * Creates a MonoClass that represents the TypeBuilder.
9704  * This is a trick that lets us simplify a lot of reflection code
9705  * (and will allow us to support Build and Run assemblies easier).
9706  */
9707 void
9708 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9709 {
9710         MonoError error;
9711         MonoClass *klass, *parent;
9712
9713         MONO_ARCH_SAVE_REGS;
9714
9715         RESOLVE_TYPE (tb->parent);
9716
9717         mono_loader_lock ();
9718
9719         if (tb->parent) {
9720                 /* check so we can compile corlib correctly */
9721                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9722                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9723                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9724                 } else {
9725                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9726                 }
9727         } else {
9728                 parent = NULL;
9729         }
9730         
9731         /* the type has already being created: it means we just have to change the parent */
9732         if (tb->type.type) {
9733                 klass = mono_class_from_mono_type (tb->type.type);
9734                 klass->parent = NULL;
9735                 /* fool mono_class_setup_parent */
9736                 klass->supertypes = NULL;
9737                 mono_class_setup_parent (klass, parent);
9738                 mono_class_setup_mono_type (klass);
9739                 mono_loader_unlock ();
9740                 return;
9741         }
9742
9743         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9744
9745         klass->image = &tb->module->dynamic_image->image;
9746
9747         klass->inited = 1; /* we lie to the runtime */
9748         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9749         if (!mono_error_ok (&error))
9750                 goto failure;
9751         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9752         if (!mono_error_ok (&error))
9753                 goto failure;
9754         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9755         klass->flags = tb->attrs;
9756         
9757         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9758
9759         klass->element_class = klass;
9760
9761         if (mono_class_get_ref_info (klass) == NULL) {
9762
9763                 mono_class_set_ref_info (klass, tb);
9764
9765                 /* Put into cache so mono_class_get () will find it.
9766                 Skip nested types as those should not be available on the global scope. */
9767                 if (!tb->nesting_type) {
9768                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9769                 } else {
9770                         klass->image->reflection_info_unregister_classes =
9771                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9772                 }
9773         } else {
9774                 g_assert (mono_class_get_ref_info (klass) == tb);
9775         }
9776
9777         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9778                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9779
9780         if (parent != NULL) {
9781                 mono_class_setup_parent (klass, parent);
9782         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9783                 const char *old_n = klass->name;
9784                 /* trick to get relative numbering right when compiling corlib */
9785                 klass->name = "BuildingObject";
9786                 mono_class_setup_parent (klass, mono_defaults.object_class);
9787                 klass->name = old_n;
9788         }
9789
9790         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9791                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9792                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9793                 klass->instance_size = sizeof (MonoObject);
9794                 klass->size_inited = 1;
9795                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9796         }
9797
9798         mono_class_setup_mono_type (klass);
9799
9800         mono_class_setup_supertypes (klass);
9801
9802         /*
9803          * FIXME: handle interfaces.
9804          */
9805
9806         tb->type.type = &klass->byval_arg;
9807
9808         if (tb->nesting_type) {
9809                 g_assert (tb->nesting_type->type);
9810                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9811         }
9812
9813         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9814
9815         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9816         
9817         mono_loader_unlock ();
9818         return;
9819
9820 failure:
9821         mono_loader_unlock ();
9822         mono_error_raise_exception (&error);
9823 }
9824
9825 /*
9826  * mono_reflection_setup_generic_class:
9827  * @tb: a TypeBuilder object
9828  *
9829  * Setup the generic class before adding the first generic parameter.
9830  */
9831 void
9832 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9833 {
9834 }
9835
9836 /*
9837  * mono_reflection_create_generic_class:
9838  * @tb: a TypeBuilder object
9839  *
9840  * Creates the generic class after all generic parameters have been added.
9841  */
9842 void
9843 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9844 {
9845         MonoClass *klass;
9846         int count, i;
9847
9848         MONO_ARCH_SAVE_REGS;
9849
9850         klass = mono_class_from_mono_type (tb->type.type);
9851
9852         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9853
9854         if (klass->generic_container || (count == 0))
9855                 return;
9856
9857         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9858
9859         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9860
9861         klass->generic_container->owner.klass = klass;
9862         klass->generic_container->type_argc = count;
9863         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9864
9865         klass->is_generic = 1;
9866
9867         for (i = 0; i < count; i++) {
9868                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9869                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9870                 klass->generic_container->type_params [i] = *param;
9871                 /*Make sure we are a diferent type instance */
9872                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9873                 klass->generic_container->type_params [i].info.pklass = NULL;
9874                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9875
9876                 g_assert (klass->generic_container->type_params [i].param.owner);
9877         }
9878
9879         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9880 }
9881
9882 /*
9883  * mono_reflection_create_internal_class:
9884  * @tb: a TypeBuilder object
9885  *
9886  * Actually create the MonoClass that is associated with the TypeBuilder.
9887  */
9888 void
9889 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9890 {
9891         MonoClass *klass;
9892
9893         MONO_ARCH_SAVE_REGS;
9894
9895         klass = mono_class_from_mono_type (tb->type.type);
9896
9897         mono_loader_lock ();
9898         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9899                 MonoReflectionFieldBuilder *fb;
9900                 MonoClass *ec;
9901                 MonoType *enum_basetype;
9902
9903                 g_assert (tb->fields != NULL);
9904                 g_assert (mono_array_length (tb->fields) >= 1);
9905
9906                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9907
9908                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9909                         mono_loader_unlock ();
9910                         return;
9911                 }
9912
9913                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9914                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9915                 if (!klass->element_class)
9916                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9917
9918                 /*
9919                  * get the element_class from the current corlib.
9920                  */
9921                 ec = default_class_from_mono_type (enum_basetype);
9922                 klass->instance_size = ec->instance_size;
9923                 klass->size_inited = 1;
9924                 /* 
9925                  * this is almost safe to do with enums and it's needed to be able
9926                  * to create objects of the enum type (for use in SetConstant).
9927                  */
9928                 /* FIXME: Does this mean enums can't have method overrides ? */
9929                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9930         }
9931         mono_loader_unlock ();
9932 }
9933
9934 static MonoMarshalSpec*
9935 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9936                                                                 MonoReflectionMarshal *minfo)
9937 {
9938         MonoMarshalSpec *res;
9939
9940         res = image_g_new0 (image, MonoMarshalSpec, 1);
9941         res->native = minfo->type;
9942
9943         switch (minfo->type) {
9944         case MONO_NATIVE_LPARRAY:
9945                 res->data.array_data.elem_type = minfo->eltype;
9946                 if (minfo->has_size) {
9947                         res->data.array_data.param_num = minfo->param_num;
9948                         res->data.array_data.num_elem = minfo->count;
9949                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9950                 }
9951                 else {
9952                         res->data.array_data.param_num = -1;
9953                         res->data.array_data.num_elem = -1;
9954                         res->data.array_data.elem_mult = -1;
9955                 }
9956                 break;
9957
9958         case MONO_NATIVE_BYVALTSTR:
9959         case MONO_NATIVE_BYVALARRAY:
9960                 res->data.array_data.num_elem = minfo->count;
9961                 break;
9962
9963         case MONO_NATIVE_CUSTOM:
9964                 if (minfo->marshaltyperef)
9965                         res->data.custom_data.custom_name =
9966                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9967                 if (minfo->mcookie)
9968                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9969                 break;
9970
9971         default:
9972                 break;
9973         }
9974
9975         return res;
9976 }
9977 #endif /* !DISABLE_REFLECTION_EMIT */
9978
9979 MonoReflectionMarshal*
9980 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9981                                                                                    MonoMarshalSpec *spec)
9982 {
9983         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9984         MonoReflectionMarshal *minfo;
9985         MonoType *mtype;
9986
9987         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9988                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9989                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9990                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9991         }
9992
9993         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9994         minfo->type = spec->native;
9995
9996         switch (minfo->type) {
9997         case MONO_NATIVE_LPARRAY:
9998                 minfo->eltype = spec->data.array_data.elem_type;
9999                 minfo->count = spec->data.array_data.num_elem;
10000                 minfo->param_num = spec->data.array_data.param_num;
10001                 break;
10002
10003         case MONO_NATIVE_BYVALTSTR:
10004         case MONO_NATIVE_BYVALARRAY:
10005                 minfo->count = spec->data.array_data.num_elem;
10006                 break;
10007
10008         case MONO_NATIVE_CUSTOM:
10009                 if (spec->data.custom_data.custom_name) {
10010                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10011                         if (mtype)
10012                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10013
10014                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10015                 }
10016                 if (spec->data.custom_data.cookie)
10017                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10018                 break;
10019
10020         default:
10021                 break;
10022         }
10023
10024         return minfo;
10025 }
10026
10027 #ifndef DISABLE_REFLECTION_EMIT
10028 static MonoMethod*
10029 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10030                                          ReflectionMethodBuilder *rmb,
10031                                          MonoMethodSignature *sig)
10032 {
10033         MonoError error;
10034         MonoMethod *m;
10035         MonoMethodWrapper *wrapperm;
10036         MonoMarshalSpec **specs;
10037         MonoReflectionMethodAux *method_aux;
10038         MonoImage *image;
10039         gboolean dynamic;
10040         int i;
10041
10042         mono_error_init (&error);
10043         /*
10044          * Methods created using a MethodBuilder should have their memory allocated
10045          * inside the image mempool, while dynamic methods should have their memory
10046          * malloc'd.
10047          */
10048         dynamic = rmb->refs != NULL;
10049         image = dynamic ? NULL : klass->image;
10050
10051         if (!dynamic)
10052                 g_assert (!klass->generic_class);
10053
10054         mono_loader_lock ();
10055
10056         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10057                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10058                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10059         else
10060                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10061
10062         wrapperm = (MonoMethodWrapper*)m;
10063
10064         m->dynamic = dynamic;
10065         m->slot = -1;
10066         m->flags = rmb->attrs;
10067         m->iflags = rmb->iattrs;
10068         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10069         g_assert (mono_error_ok (&error));
10070         m->klass = klass;
10071         m->signature = sig;
10072         m->sre_method = TRUE;
10073         m->skip_visibility = rmb->skip_visibility;
10074         if (rmb->table_idx)
10075                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10076
10077         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10078                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10079                         m->string_ctor = 1;
10080
10081                 m->signature->pinvoke = 1;
10082         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10083                 m->signature->pinvoke = 1;
10084
10085                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10086
10087                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10088                 g_assert (mono_error_ok (&error));
10089                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10090                 g_assert (mono_error_ok (&error));
10091                 
10092                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10093
10094                 if (klass->image->dynamic)
10095                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10096
10097                 mono_loader_unlock ();
10098
10099                 return m;
10100         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10101                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10102                 MonoMethodHeader *header;
10103                 guint32 code_size;
10104                 gint32 max_stack, i;
10105                 gint32 num_locals = 0;
10106                 gint32 num_clauses = 0;
10107                 guint8 *code;
10108
10109                 if (rmb->ilgen) {
10110                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10111                         code_size = rmb->ilgen->code_len;
10112                         max_stack = rmb->ilgen->max_stack;
10113                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10114                         if (rmb->ilgen->ex_handlers)
10115                                 num_clauses = method_count_clauses (rmb->ilgen);
10116                 } else {
10117                         if (rmb->code) {
10118                                 code = mono_array_addr (rmb->code, guint8, 0);
10119                                 code_size = mono_array_length (rmb->code);
10120                                 /* we probably need to run a verifier on the code... */
10121                                 max_stack = 8; 
10122                         }
10123                         else {
10124                                 code = NULL;
10125                                 code_size = 0;
10126                                 max_stack = 8;
10127                         }
10128                 }
10129
10130                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10131                 header->code_size = code_size;
10132                 header->code = image_g_malloc (image, code_size);
10133                 memcpy ((char*)header->code, code, code_size);
10134                 header->max_stack = max_stack;
10135                 header->init_locals = rmb->init_locals;
10136                 header->num_locals = num_locals;
10137
10138                 for (i = 0; i < num_locals; ++i) {
10139                         MonoReflectionLocalBuilder *lb = 
10140                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10141
10142                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10143                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10144                 }
10145
10146                 header->num_clauses = num_clauses;
10147                 if (num_clauses) {
10148                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10149                                  rmb->ilgen, num_clauses);
10150                 }
10151
10152                 wrapperm->header = header;
10153         }
10154
10155         if (rmb->generic_params) {
10156                 int count = mono_array_length (rmb->generic_params);
10157                 MonoGenericContainer *container = rmb->generic_container;
10158
10159                 g_assert (container);
10160
10161                 container->type_argc = count;
10162                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10163                 container->owner.method = m;
10164
10165                 m->is_generic = TRUE;
10166                 mono_method_set_generic_container (m, container);
10167
10168                 for (i = 0; i < count; i++) {
10169                         MonoReflectionGenericParam *gp =
10170                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10171                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10172                         container->type_params [i] = *param;
10173                 }
10174
10175                 /*
10176                  * The method signature might have pointers to generic parameters that belong to other methods.
10177                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10178                  * generic parameters.
10179                  */
10180                 for (i = 0; i < m->signature->param_count; ++i) {
10181                         MonoType *t = m->signature->params [i];
10182                         if (t->type == MONO_TYPE_MVAR) {
10183                                 MonoGenericParam *gparam =  t->data.generic_param;
10184                                 if (gparam->num < count) {
10185                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10186                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10187                                 }
10188
10189                         }
10190                 }
10191
10192                 if (klass->generic_container) {
10193                         container->parent = klass->generic_container;
10194                         container->context.class_inst = klass->generic_container->context.class_inst;
10195                 }
10196                 container->context.method_inst = mono_get_shared_generic_inst (container);
10197         }
10198
10199         if (rmb->refs) {
10200                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10201                 int i;
10202                 void **data;
10203
10204                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10205
10206                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10207                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10208                 for (i = 0; i < rmb->nrefs; ++i)
10209                         data [i + 1] = rmb->refs [i];
10210         }
10211
10212         method_aux = NULL;
10213
10214         /* Parameter info */
10215         if (rmb->pinfo) {
10216                 if (!method_aux)
10217                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10218                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10219                 for (i = 0; i <= m->signature->param_count; ++i) {
10220                         MonoReflectionParamBuilder *pb;
10221                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10222                                 if ((i > 0) && (pb->attrs)) {
10223                                         /* Make a copy since it might point to a shared type structure */
10224                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10225                                         m->signature->params [i - 1]->attrs = pb->attrs;
10226                                 }
10227
10228                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10229                                         MonoDynamicImage *assembly;
10230                                         guint32 idx, def_type, len;
10231                                         char *p;
10232                                         const char *p2;
10233
10234                                         if (!method_aux->param_defaults) {
10235                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10236                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10237                                         }
10238                                         assembly = (MonoDynamicImage*)klass->image;
10239                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10240                                         /* Copy the data from the blob since it might get realloc-ed */
10241                                         p = assembly->blob.data + idx;
10242                                         len = mono_metadata_decode_blob_size (p, &p2);
10243                                         len += p2 - p;
10244                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10245                                         method_aux->param_default_types [i] = def_type;
10246                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10247                                 }
10248
10249                                 if (pb->name) {
10250                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10251                                         g_assert (mono_error_ok (&error));
10252                                 }
10253                                 if (pb->cattrs) {
10254                                         if (!method_aux->param_cattr)
10255                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10256                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10257                                 }
10258                         }
10259                 }
10260         }
10261
10262         /* Parameter marshalling */
10263         specs = NULL;
10264         if (rmb->pinfo)         
10265                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10266                         MonoReflectionParamBuilder *pb;
10267                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10268                                 if (pb->marshal_info) {
10269                                         if (specs == NULL)
10270                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10271                                         specs [pb->position] = 
10272                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10273                                 }
10274                         }
10275                 }
10276         if (specs != NULL) {
10277                 if (!method_aux)
10278                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10279                 method_aux->param_marshall = specs;
10280         }
10281
10282         if (klass->image->dynamic && method_aux)
10283                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10284
10285         mono_loader_unlock ();
10286
10287         return m;
10288 }       
10289
10290 static MonoMethod*
10291 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10292 {
10293         ReflectionMethodBuilder rmb;
10294         MonoMethodSignature *sig;
10295
10296         mono_loader_lock ();
10297         sig = ctor_builder_to_signature (klass->image, mb);
10298         mono_loader_unlock ();
10299
10300         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10301
10302         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10303         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10304
10305         /* If we are in a generic class, we might be called multiple times from inflate_method */
10306         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10307                 /* ilgen is no longer needed */
10308                 mb->ilgen = NULL;
10309         }
10310
10311         return mb->mhandle;
10312 }
10313
10314 static MonoMethod*
10315 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10316 {
10317         ReflectionMethodBuilder rmb;
10318         MonoMethodSignature *sig;
10319
10320         mono_loader_lock ();
10321         sig = method_builder_to_signature (klass->image, mb);
10322         mono_loader_unlock ();
10323
10324         reflection_methodbuilder_from_method_builder (&rmb, mb);
10325
10326         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10327         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10328
10329         /* If we are in a generic class, we might be called multiple times from inflate_method */
10330         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10331                 /* ilgen is no longer needed */
10332                 mb->ilgen = NULL;
10333         }
10334         return mb->mhandle;
10335 }
10336
10337 static MonoClassField*
10338 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10339 {
10340         MonoClassField *field;
10341         MonoType *custom;
10342         MonoError error;
10343
10344         field = g_new0 (MonoClassField, 1);
10345
10346         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10347         g_assert (mono_error_ok (&error));
10348         if (fb->attrs || fb->modreq || fb->modopt) {
10349                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10350                 field->type->attrs = fb->attrs;
10351
10352                 g_assert (klass->image->dynamic);
10353                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10354                 g_free (field->type);
10355                 field->type = mono_metadata_type_dup (klass->image, custom);
10356                 g_free (custom);
10357         } else {
10358                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10359         }
10360         if (fb->offset != -1)
10361                 field->offset = fb->offset;
10362         field->parent = klass;
10363         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10364
10365         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10366
10367         return field;
10368 }
10369 #endif
10370
10371 MonoType*
10372 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10373 {
10374         MonoClass *klass;
10375         MonoReflectionTypeBuilder *tb = NULL;
10376         gboolean is_dynamic = FALSE;
10377         MonoDomain *domain;
10378         MonoClass *geninst;
10379
10380         mono_loader_lock ();
10381
10382         domain = mono_object_domain (type);
10383
10384         if (is_sre_type_builder (mono_object_class (type))) {
10385                 tb = (MonoReflectionTypeBuilder *) type;
10386
10387                 is_dynamic = TRUE;
10388         } else if (is_sre_generic_instance (mono_object_class (type))) {
10389                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10390                 MonoReflectionType *gtd = rgi->generic_type;
10391
10392                 if (is_sre_type_builder (mono_object_class (gtd))) {
10393                         tb = (MonoReflectionTypeBuilder *)gtd;
10394                         is_dynamic = TRUE;
10395                 }
10396         }
10397
10398         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10399         if (tb && tb->generic_container)
10400                 mono_reflection_create_generic_class (tb);
10401
10402         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10403         if (!klass->generic_container) {
10404                 mono_loader_unlock ();
10405                 return NULL;
10406         }
10407
10408         if (klass->wastypebuilder) {
10409                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10410
10411                 is_dynamic = TRUE;
10412         }
10413
10414         mono_loader_unlock ();
10415
10416         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10417
10418         return &geninst->byval_arg;
10419 }
10420
10421 MonoClass*
10422 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10423 {
10424         MonoGenericClass *gclass;
10425         MonoGenericInst *inst;
10426
10427         g_assert (klass->generic_container);
10428
10429         inst = mono_metadata_get_generic_inst (type_argc, types);
10430         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10431
10432         return mono_generic_class_get_class (gclass);
10433 }
10434
10435 MonoReflectionMethod*
10436 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10437 {
10438         MonoClass *klass;
10439         MonoMethod *method, *inflated;
10440         MonoMethodInflated *imethod;
10441         MonoGenericContext tmp_context;
10442         MonoGenericInst *ginst;
10443         MonoType **type_argv;
10444         int count, i;
10445
10446         MONO_ARCH_SAVE_REGS;
10447
10448         /*FIXME but this no longer should happen*/
10449         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10450 #ifndef DISABLE_REFLECTION_EMIT
10451                 MonoReflectionMethodBuilder *mb = NULL;
10452                 MonoReflectionTypeBuilder *tb;
10453                 MonoClass *klass;
10454
10455                 mb = (MonoReflectionMethodBuilder *) rmethod;
10456                 tb = (MonoReflectionTypeBuilder *) mb->type;
10457                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10458
10459                 method = methodbuilder_to_mono_method (klass, mb);
10460 #else
10461                 g_assert_not_reached ();
10462                 method = NULL;
10463 #endif
10464         } else {
10465                 method = rmethod->method;
10466         }
10467
10468         klass = method->klass;
10469
10470         if (method->is_inflated)
10471                 method = ((MonoMethodInflated *) method)->declaring;
10472
10473         count = mono_method_signature (method)->generic_param_count;
10474         if (count != mono_array_length (types))
10475                 return NULL;
10476
10477         type_argv = g_new0 (MonoType *, count);
10478         for (i = 0; i < count; i++) {
10479                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10480                 type_argv [i] = mono_reflection_type_get_handle (garg);
10481         }
10482         ginst = mono_metadata_get_generic_inst (count, type_argv);
10483         g_free (type_argv);
10484
10485         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10486         tmp_context.method_inst = ginst;
10487
10488         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10489         imethod = (MonoMethodInflated *) inflated;
10490
10491         /*FIXME but I think this is no longer necessary*/
10492         if (method->klass->image->dynamic) {
10493                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10494                 /*
10495                  * This table maps metadata structures representing inflated methods/fields
10496                  * to the reflection objects representing their generic definitions.
10497                  */
10498                 mono_loader_lock ();
10499                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10500                 mono_loader_unlock ();
10501         }
10502
10503         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10504                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10505         
10506         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10507 }
10508
10509 #ifndef DISABLE_REFLECTION_EMIT
10510
10511 static MonoMethod *
10512 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10513 {
10514         MonoMethodInflated *imethod;
10515         MonoGenericContext *context;
10516         int i;
10517
10518         /*
10519          * With generic code sharing the klass might not be inflated.
10520          * This can happen because classes inflated with their own
10521          * type arguments are "normalized" to the uninflated class.
10522          */
10523         if (!klass->generic_class)
10524                 return method;
10525
10526         context = mono_class_get_context (klass);
10527
10528         if (klass->method.count && klass->methods) {
10529                 /* Find the already created inflated method */
10530                 for (i = 0; i < klass->method.count; ++i) {
10531                         g_assert (klass->methods [i]->is_inflated);
10532                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10533                                 break;
10534                 }
10535                 g_assert (i < klass->method.count);
10536                 imethod = (MonoMethodInflated*)klass->methods [i];
10537         } else {
10538                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10539         }
10540
10541         if (method->is_generic && method->klass->image->dynamic) {
10542                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10543
10544                 mono_loader_lock ();
10545                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10546                 mono_loader_unlock ();
10547         }
10548         return (MonoMethod *) imethod;
10549 }
10550
10551 static MonoMethod *
10552 inflate_method (MonoReflectionType *type, MonoObject *obj)
10553 {
10554         MonoMethod *method;
10555         MonoClass *gklass;
10556
10557         MonoClass *type_class = mono_object_class (type);
10558
10559         if (is_sre_generic_instance (type_class)) {
10560                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10561                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10562         } else if (is_sre_type_builder (type_class)) {
10563                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10564         } else if (type->type) {
10565                 gklass = mono_class_from_mono_type (type->type);
10566                 gklass = mono_class_get_generic_type_definition (gklass);
10567         } else {
10568                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10569         }
10570
10571         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10572                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10573                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10574                 else
10575                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10576         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10577                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10578         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10579                 method = ((MonoReflectionMethod *) obj)->method;
10580         else {
10581                 method = NULL; /* prevent compiler warning */
10582                 g_error ("can't handle type %s", obj->vtable->klass->name);
10583         }
10584
10585         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10586 }
10587
10588 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10589 void
10590 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10591                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10592                                           MonoArray *events)
10593 {
10594         MonoGenericClass *gclass;
10595         MonoDynamicGenericClass *dgclass;
10596         MonoClass *klass, *gklass;
10597         MonoType *gtype;
10598         int i;
10599
10600         MONO_ARCH_SAVE_REGS;
10601
10602         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10603         klass = mono_class_from_mono_type (gtype);
10604         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10605         gclass = gtype->data.generic_class;
10606
10607         if (!gclass->is_dynamic)
10608                 return;
10609
10610         dgclass = (MonoDynamicGenericClass *) gclass;
10611
10612         if (dgclass->initialized)
10613                 return;
10614
10615         gklass = gclass->container_class;
10616         mono_class_init (gklass);
10617
10618         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10619         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10620         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10621
10622         dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
10623         dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
10624         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10625         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10626         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10627
10628         for (i = 0; i < dgclass->count_methods; i++) {
10629                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10630
10631                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10632         }
10633
10634         for (i = 0; i < dgclass->count_ctors; i++) {
10635                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10636
10637                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10638         }
10639
10640         for (i = 0; i < dgclass->count_fields; i++) {
10641                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10642                 MonoClassField *field, *inflated_field = NULL;
10643
10644                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10645                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10646                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10647                         field = ((MonoReflectionField *) obj)->field;
10648                 else {
10649                         field = NULL; /* prevent compiler warning */
10650                         g_assert_not_reached ();
10651                 }
10652
10653                 dgclass->fields [i] = *field;
10654                 dgclass->fields [i].parent = klass;
10655                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10656                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10657                 dgclass->field_generic_types [i] = field->type;
10658                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10659                 dgclass->field_objects [i] = obj;
10660
10661                 if (inflated_field) {
10662                         g_free (inflated_field);
10663                 } else {
10664                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10665                 }
10666         }
10667
10668         dgclass->initialized = TRUE;
10669 }
10670
10671 void
10672 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10673 {
10674         MonoDynamicGenericClass *dgclass;
10675         int i;
10676
10677         g_assert (gclass->is_dynamic);
10678
10679         dgclass = (MonoDynamicGenericClass *)gclass;
10680
10681         for (i = 0; i < dgclass->count_fields; ++i) {
10682                 MonoClassField *field = dgclass->fields + i;
10683                 mono_metadata_free_type (field->type);
10684                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10685         }
10686 }
10687
10688 static void
10689 fix_partial_generic_class (MonoClass *klass)
10690 {
10691         MonoClass *gklass = klass->generic_class->container_class;
10692         MonoDynamicGenericClass *dgclass;
10693         int i;
10694
10695         if (klass->wastypebuilder)
10696                 return;
10697
10698         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10699         if (klass->parent != gklass->parent) {
10700                 MonoError error;
10701                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10702                 if (mono_error_ok (&error)) {
10703                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10704                         mono_metadata_free_type (parent_type);
10705                         if (parent != klass->parent) {
10706                                 /*fool mono_class_setup_parent*/
10707                                 klass->supertypes = NULL;
10708                                 mono_class_setup_parent (klass, parent);
10709                         }
10710                 } else {
10711                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10712                         mono_error_cleanup (&error);
10713                         if (gklass->wastypebuilder)
10714                                 klass->wastypebuilder = TRUE;
10715                         return;
10716                 }
10717         }
10718
10719         if (!dgclass->initialized)
10720                 return;
10721
10722         if (klass->method.count != gklass->method.count) {
10723                 klass->method.count = gklass->method.count;
10724                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10725
10726                 for (i = 0; i < klass->method.count; i++) {
10727                         klass->methods [i] = mono_class_inflate_generic_method_full (
10728                                 gklass->methods [i], klass, mono_class_get_context (klass));
10729                 }
10730         }
10731
10732         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10733                 klass->interface_count = gklass->interface_count;
10734                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10735                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10736
10737                 for (i = 0; i < gklass->interface_count; ++i) {
10738                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10739                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10740                         mono_metadata_free_type (iface_type);
10741
10742                         ensure_runtime_vtable (klass->interfaces [i]);
10743                 }
10744                 klass->interfaces_inited = 1;
10745         }
10746
10747         if (klass->field.count != gklass->field.count) {
10748                 klass->field.count = gklass->field.count;
10749                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10750
10751                 for (i = 0; i < klass->field.count; i++) {
10752                         klass->fields [i] = gklass->fields [i];
10753                         klass->fields [i].parent = klass;
10754                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10755                 }
10756         }
10757
10758         /*We can only finish with this klass once it's parent has as well*/
10759         if (gklass->wastypebuilder)
10760                 klass->wastypebuilder = TRUE;
10761         return;
10762 }
10763
10764 static void
10765 ensure_generic_class_runtime_vtable (MonoClass *klass)
10766 {
10767         MonoClass *gklass = klass->generic_class->container_class;
10768
10769         ensure_runtime_vtable (gklass); 
10770
10771         fix_partial_generic_class (klass);
10772 }
10773
10774 static void
10775 ensure_runtime_vtable (MonoClass *klass)
10776 {
10777         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10778         int i, num, j;
10779
10780         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10781                 return;
10782         if (klass->parent)
10783                 ensure_runtime_vtable (klass->parent);
10784
10785         if (tb) {
10786                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10787                 num += tb->num_methods;
10788                 klass->method.count = num;
10789                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10790                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10791                 for (i = 0; i < num; ++i)
10792                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10793                 num = tb->num_methods;
10794                 j = i;
10795                 for (i = 0; i < num; ++i)
10796                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10797         
10798                 if (tb->interfaces) {
10799                         klass->interface_count = mono_array_length (tb->interfaces);
10800                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10801                         for (i = 0; i < klass->interface_count; ++i) {
10802                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10803                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10804                                 ensure_runtime_vtable (klass->interfaces [i]);
10805                         }
10806                         klass->interfaces_inited = 1;
10807                 }
10808         } else if (klass->generic_class){
10809                 ensure_generic_class_runtime_vtable (klass);
10810         }
10811
10812         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10813                 int slot_num = 0;
10814                 for (i = 0; i < klass->method.count; ++i) {
10815                         MonoMethod *im = klass->methods [i];
10816                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10817                                 im->slot = slot_num++;
10818                 }
10819                 
10820                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10821                 mono_class_setup_interface_offsets (klass);
10822                 mono_class_setup_interface_id (klass);
10823         }
10824
10825         /*
10826          * The generic vtable is needed even if image->run is not set since some
10827          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10828          * method->slot being defined.
10829          */
10830
10831         /* 
10832          * tb->methods could not be freed since it is used for determining 
10833          * overrides during dynamic vtable construction.
10834          */
10835 }
10836
10837 static MonoMethod*
10838 mono_reflection_method_get_handle (MonoObject *method)
10839 {
10840         MonoClass *class = mono_object_class (method);
10841         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10842                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10843                 return sr_method->method;
10844         }
10845         if (is_sre_method_builder (class)) {
10846                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10847                 return mb->mhandle;
10848         }
10849         if (is_sre_method_on_tb_inst (class)) {
10850                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10851                 MonoMethod *result;
10852                 /*FIXME move this to a proper method and unify with resolve_object*/
10853                 if (m->method_args) {
10854                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10855                 } else {
10856                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10857                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10858                         MonoMethod *mono_method;
10859
10860                         if (is_sre_method_builder (mono_object_class (m->mb)))
10861                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10862                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10863                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10864                         else
10865                                 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)));
10866
10867                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10868                 }
10869                 return result;
10870         }
10871
10872         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10873         return NULL;
10874 }
10875
10876 void
10877 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10878 {
10879         MonoReflectionTypeBuilder *tb;
10880         int i, onum;
10881
10882         *overrides = NULL;
10883         *num_overrides = 0;
10884
10885         g_assert (klass->image->dynamic);
10886
10887         if (!mono_class_get_ref_info (klass))
10888                 return;
10889
10890         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10891
10892         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10893
10894         onum = 0;
10895         if (tb->methods) {
10896                 for (i = 0; i < tb->num_methods; ++i) {
10897                         MonoReflectionMethodBuilder *mb = 
10898                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10899                         if (mb->override_method)
10900                                 onum ++;
10901                 }
10902         }
10903
10904         if (onum) {
10905                 *overrides = g_new0 (MonoMethod*, onum * 2);
10906
10907                 onum = 0;
10908                 for (i = 0; i < tb->num_methods; ++i) {
10909                         MonoReflectionMethodBuilder *mb = 
10910                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10911                         if (mb->override_method) {
10912                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10913                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10914
10915                                 g_assert (mb->mhandle);
10916
10917                                 onum ++;
10918                         }
10919                 }
10920         }
10921
10922         *num_overrides = onum;
10923 }
10924
10925 static void
10926 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10927 {
10928         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10929         MonoReflectionFieldBuilder *fb;
10930         MonoClassField *field;
10931         MonoImage *image = klass->image;
10932         const char *p, *p2;
10933         int i;
10934         guint32 len, idx, real_size = 0;
10935
10936         klass->field.count = tb->num_fields;
10937         klass->field.first = 0;
10938
10939         mono_error_init (error);
10940
10941         if (tb->class_size) {
10942                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10943                 klass->packing_size = tb->packing_size;
10944                 real_size = klass->instance_size + tb->class_size;
10945         }
10946
10947         if (!klass->field.count) {
10948                 klass->instance_size = MAX (klass->instance_size, real_size);
10949                 return;
10950         }
10951         
10952         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10953         mono_class_alloc_ext (klass);
10954         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10955         /*
10956         This is, guess what, a hack.
10957         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10958         On the static path no field class is resolved, only types are built. This is the right thing to do
10959         but we suck.
10960         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10961         */
10962         klass->size_inited = 1;
10963
10964         for (i = 0; i < klass->field.count; ++i) {
10965                 fb = mono_array_get (tb->fields, gpointer, i);
10966                 field = &klass->fields [i];
10967                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10968                 if (!mono_error_ok (error))
10969                         return;
10970                 if (fb->attrs) {
10971                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10972                         field->type->attrs = fb->attrs;
10973                 } else {
10974                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10975                 }
10976                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10977                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10978                 if (fb->offset != -1)
10979                         field->offset = fb->offset;
10980                 field->parent = klass;
10981                 fb->handle = field;
10982                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10983
10984                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10985                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10986                 }
10987                 if (fb->def_value) {
10988                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10989                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10990                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10991                         /* Copy the data from the blob since it might get realloc-ed */
10992                         p = assembly->blob.data + idx;
10993                         len = mono_metadata_decode_blob_size (p, &p2);
10994                         len += p2 - p;
10995                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10996                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10997                 }
10998         }
10999
11000         klass->instance_size = MAX (klass->instance_size, real_size);
11001         mono_class_layout_fields (klass);
11002 }
11003
11004 static void
11005 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11006 {
11007         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11008         MonoReflectionPropertyBuilder *pb;
11009         MonoImage *image = klass->image;
11010         MonoProperty *properties;
11011         int i;
11012
11013         mono_error_init (error);
11014
11015         if (!klass->ext)
11016                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11017
11018         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11019         klass->ext->property.first = 0;
11020
11021         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11022         klass->ext->properties = properties;
11023         for (i = 0; i < klass->ext->property.count; ++i) {
11024                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11025                 properties [i].parent = klass;
11026                 properties [i].attrs = pb->attrs;
11027                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11028                 if (!mono_error_ok (error))
11029                         return;
11030                 if (pb->get_method)
11031                         properties [i].get = pb->get_method->mhandle;
11032                 if (pb->set_method)
11033                         properties [i].set = pb->set_method->mhandle;
11034
11035                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11036                 if (pb->def_value) {
11037                         guint32 len, idx;
11038                         const char *p, *p2;
11039                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11040                         if (!klass->ext->prop_def_values)
11041                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11042                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11043                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11044                         /* Copy the data from the blob since it might get realloc-ed */
11045                         p = assembly->blob.data + idx;
11046                         len = mono_metadata_decode_blob_size (p, &p2);
11047                         len += p2 - p;
11048                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11049                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11050                 }
11051         }
11052 }
11053
11054 MonoReflectionEvent *
11055 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11056 {
11057         MonoEvent *event = g_new0 (MonoEvent, 1);
11058         MonoClass *klass;
11059
11060         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11061
11062         event->parent = klass;
11063         event->attrs = eb->attrs;
11064         event->name = mono_string_to_utf8 (eb->name);
11065         if (eb->add_method)
11066                 event->add = eb->add_method->mhandle;
11067         if (eb->remove_method)
11068                 event->remove = eb->remove_method->mhandle;
11069         if (eb->raise_method)
11070                 event->raise = eb->raise_method->mhandle;
11071
11072 #ifndef MONO_SMALL_CONFIG
11073         if (eb->other_methods) {
11074                 int j;
11075                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11076                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11077                         MonoReflectionMethodBuilder *mb = 
11078                                 mono_array_get (eb->other_methods,
11079                                                 MonoReflectionMethodBuilder*, j);
11080                         event->other [j] = mb->mhandle;
11081                 }
11082         }
11083 #endif
11084
11085         return mono_event_get_object (mono_object_domain (tb), klass, event);
11086 }
11087
11088 static void
11089 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11090 {
11091         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11092         MonoReflectionEventBuilder *eb;
11093         MonoImage *image = klass->image;
11094         MonoEvent *events;
11095         int i;
11096
11097         mono_error_init (error);
11098
11099         if (!klass->ext)
11100                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11101
11102         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11103         klass->ext->event.first = 0;
11104
11105         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11106         klass->ext->events = events;
11107         for (i = 0; i < klass->ext->event.count; ++i) {
11108                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11109                 events [i].parent = klass;
11110                 events [i].attrs = eb->attrs;
11111                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11112                 if (!mono_error_ok (error))
11113                         return;
11114                 if (eb->add_method)
11115                         events [i].add = eb->add_method->mhandle;
11116                 if (eb->remove_method)
11117                         events [i].remove = eb->remove_method->mhandle;
11118                 if (eb->raise_method)
11119                         events [i].raise = eb->raise_method->mhandle;
11120
11121 #ifndef MONO_SMALL_CONFIG
11122                 if (eb->other_methods) {
11123                         int j;
11124                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11125                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11126                                 MonoReflectionMethodBuilder *mb = 
11127                                         mono_array_get (eb->other_methods,
11128                                                                         MonoReflectionMethodBuilder*, j);
11129                                 events [i].other [j] = mb->mhandle;
11130                         }
11131                 }
11132 #endif
11133                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11134         }
11135 }
11136
11137 static gboolean
11138 remove_instantiations_of_and_ensure_contents (gpointer key,
11139                                                   gpointer value,
11140                                                   gpointer user_data)
11141 {
11142         MonoType *type = (MonoType*)key;
11143         MonoClass *klass = (MonoClass*)user_data;
11144
11145         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11146                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11147                 return TRUE;
11148         } else
11149                 return FALSE;
11150 }
11151
11152 static void
11153 check_array_for_usertypes (MonoArray *arr)
11154 {
11155         int i;
11156
11157         if (!arr)
11158                 return;
11159
11160         for (i = 0; i < mono_array_length (arr); ++i)
11161                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11162 }
11163
11164 MonoReflectionType*
11165 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11166 {
11167         MonoError error;
11168         MonoClass *klass;
11169         MonoDomain* domain;
11170         MonoReflectionType* res;
11171         int i, j;
11172
11173         MONO_ARCH_SAVE_REGS;
11174
11175         domain = mono_object_domain (tb);
11176         klass = mono_class_from_mono_type (tb->type.type);
11177
11178         /*
11179          * Check for user defined Type subclasses.
11180          */
11181         RESOLVE_TYPE (tb->parent);
11182         check_array_for_usertypes (tb->interfaces);
11183         if (tb->fields) {
11184                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11185                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11186                         if (fb) {
11187                                 RESOLVE_TYPE (fb->type);
11188                                 check_array_for_usertypes (fb->modreq);
11189                                 check_array_for_usertypes (fb->modopt);
11190                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11191                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11192                         }
11193                 }
11194         }
11195         if (tb->methods) {
11196                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11197                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11198                         if (mb) {
11199                                 RESOLVE_TYPE (mb->rtype);
11200                                 check_array_for_usertypes (mb->return_modreq);
11201                                 check_array_for_usertypes (mb->return_modopt);
11202                                 check_array_for_usertypes (mb->parameters);
11203                                 if (mb->param_modreq)
11204                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11205                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11206                                 if (mb->param_modopt)
11207                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11208                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11209                         }
11210                 }
11211         }
11212         if (tb->ctors) {
11213                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11214                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11215                         if (mb) {
11216                                 check_array_for_usertypes (mb->parameters);
11217                                 if (mb->param_modreq)
11218                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11219                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11220                                 if (mb->param_modopt)
11221                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11222                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11223                         }
11224                 }
11225         }
11226
11227         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11228
11229         /* 
11230          * we need to lock the domain because the lock will be taken inside
11231          * So, we need to keep the locking order correct.
11232          */
11233         mono_loader_lock ();
11234         mono_domain_lock (domain);
11235         if (klass->wastypebuilder) {
11236                 mono_domain_unlock (domain);
11237                 mono_loader_unlock ();
11238                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11239         }
11240         /*
11241          * Fields to set in klass:
11242          * the various flags: delegate/unicode/contextbound etc.
11243          */
11244         klass->flags = tb->attrs;
11245         klass->has_cctor = 1;
11246         klass->has_finalize = 1;
11247         klass->has_finalize_inited = 1;
11248
11249         /* fool mono_class_setup_parent */
11250         klass->supertypes = NULL;
11251         mono_class_setup_parent (klass, klass->parent);
11252         mono_class_setup_mono_type (klass);
11253
11254 #if 0
11255         if (!((MonoDynamicImage*)klass->image)->run) {
11256                 if (klass->generic_container) {
11257                         /* FIXME: The code below can't handle generic classes */
11258                         klass->wastypebuilder = TRUE;
11259                         mono_loader_unlock ();
11260                         mono_domain_unlock (domain);
11261                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11262                 }
11263         }
11264 #endif
11265
11266         /* enums are done right away */
11267         if (!klass->enumtype)
11268                 ensure_runtime_vtable (klass);
11269
11270         if (tb->subtypes) {
11271                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11272                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11273                         mono_class_alloc_ext (klass);
11274                         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)));
11275                 }
11276         }
11277
11278         klass->nested_classes_inited = TRUE;
11279
11280         /* fields and object layout */
11281         if (klass->parent) {
11282                 if (!klass->parent->size_inited)
11283                         mono_class_init (klass->parent);
11284                 klass->instance_size = klass->parent->instance_size;
11285                 klass->sizes.class_size = 0;
11286                 klass->min_align = klass->parent->min_align;
11287                 /* if the type has no fields we won't call the field_setup
11288                  * routine which sets up klass->has_references.
11289                  */
11290                 klass->has_references |= klass->parent->has_references;
11291         } else {
11292                 klass->instance_size = sizeof (MonoObject);
11293                 klass->min_align = 1;
11294         }
11295
11296         /* FIXME: handle packing_size and instance_size */
11297         typebuilder_setup_fields (klass, &error);
11298         if (!mono_error_ok (&error))
11299                 goto failure;
11300         typebuilder_setup_properties (klass, &error);
11301         if (!mono_error_ok (&error))
11302                 goto failure;
11303
11304         typebuilder_setup_events (klass, &error);
11305         if (!mono_error_ok (&error))
11306                 goto failure;
11307
11308         klass->wastypebuilder = TRUE;
11309
11310         /* 
11311          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11312          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11313          * we want to return normal System.MonoType objects, so clear these out from the cache.
11314          *
11315          * Together with this we must ensure the contents of all instances to match the created type.
11316          */
11317         if (domain->type_hash && klass->generic_container)
11318                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11319
11320         mono_domain_unlock (domain);
11321         mono_loader_unlock ();
11322
11323         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11324                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11325                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11326         }
11327
11328         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11329         g_assert (res != (MonoReflectionType*)tb);
11330
11331         return res;
11332
11333 failure:
11334         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11335         klass->wastypebuilder = TRUE;
11336         mono_domain_unlock (domain);
11337         mono_loader_unlock ();
11338         mono_error_raise_exception (&error);
11339         return NULL;
11340 }
11341
11342 void
11343 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11344 {
11345         MonoGenericParamFull *param;
11346         MonoImage *image;
11347         MonoClass *pklass;
11348         MonoError error;
11349
11350         MONO_ARCH_SAVE_REGS;
11351
11352         image = &gparam->tbuilder->module->dynamic_image->image;
11353
11354         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11355
11356         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11357         g_assert (mono_error_ok (&error));
11358         param->param.num = gparam->index;
11359
11360         if (gparam->mbuilder) {
11361                 if (!gparam->mbuilder->generic_container) {
11362                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11363                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11364                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11365                         gparam->mbuilder->generic_container->is_method = TRUE;
11366                         /* 
11367                          * Cannot set owner.method, since the MonoMethod is not created yet.
11368                          * Set the image field instead, so type_in_image () works.
11369                          */
11370                         gparam->mbuilder->generic_container->image = klass->image;
11371                 }
11372                 param->param.owner = gparam->mbuilder->generic_container;
11373         } else if (gparam->tbuilder) {
11374                 if (!gparam->tbuilder->generic_container) {
11375                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11376                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11377                         gparam->tbuilder->generic_container->owner.klass = klass;
11378                 }
11379                 param->param.owner = gparam->tbuilder->generic_container;
11380         }
11381
11382         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11383
11384         gparam->type.type = &pklass->byval_arg;
11385
11386         mono_class_set_ref_info (pklass, gparam);
11387         mono_image_lock (image);
11388         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11389         mono_image_unlock (image);
11390 }
11391
11392 MonoArray *
11393 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11394 {
11395         MonoReflectionModuleBuilder *module = sig->module;
11396         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11397         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11398         guint32 buflen, i;
11399         MonoArray *result;
11400         SigBuffer buf;
11401
11402         check_array_for_usertypes (sig->arguments);
11403
11404         sigbuffer_init (&buf, 32);
11405
11406         sigbuffer_add_value (&buf, 0x07);
11407         sigbuffer_add_value (&buf, na);
11408         if (assembly != NULL){
11409                 for (i = 0; i < na; ++i) {
11410                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11411                         encode_reflection_type (assembly, type, &buf);
11412                 }
11413         }
11414
11415         buflen = buf.p - buf.buf;
11416         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11417         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11418         sigbuffer_free (&buf);
11419
11420         return result;
11421 }
11422
11423 MonoArray *
11424 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11425 {
11426         MonoDynamicImage *assembly = sig->module->dynamic_image;
11427         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11428         guint32 buflen, i;
11429         MonoArray *result;
11430         SigBuffer buf;
11431
11432         check_array_for_usertypes (sig->arguments);
11433
11434         sigbuffer_init (&buf, 32);
11435
11436         sigbuffer_add_value (&buf, 0x06);
11437         for (i = 0; i < na; ++i) {
11438                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11439                 encode_reflection_type (assembly, type, &buf);
11440         }
11441
11442         buflen = buf.p - buf.buf;
11443         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11444         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11445         sigbuffer_free (&buf);
11446
11447         return result;
11448 }
11449
11450 typedef struct {
11451         MonoMethod *handle;
11452         MonoDomain *domain;
11453 } DynamicMethodReleaseData;
11454
11455 /*
11456  * The runtime automatically clean up those after finalization.
11457 */      
11458 static MonoReferenceQueue *dynamic_method_queue;
11459
11460 static void
11461 free_dynamic_method (void *dynamic_method)
11462 {
11463         DynamicMethodReleaseData *data = dynamic_method;
11464
11465         mono_runtime_free_method (data->domain, data->handle);
11466         g_free (data);
11467 }
11468
11469 void 
11470 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11471 {
11472         MonoReferenceQueue *queue;
11473         MonoMethod *handle;
11474         DynamicMethodReleaseData *release_data;
11475         ReflectionMethodBuilder rmb;
11476         MonoMethodSignature *sig;
11477         MonoClass *klass;
11478         GSList *l;
11479         int i;
11480
11481         if (mono_runtime_is_shutting_down ())
11482                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11483
11484         if (!(queue = dynamic_method_queue)) {
11485                 mono_loader_lock ();
11486                 if (!(queue = dynamic_method_queue))
11487                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11488                 mono_loader_unlock ();
11489         }
11490
11491         sig = dynamic_method_to_signature (mb);
11492
11493         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11494
11495         /*
11496          * Resolve references.
11497          */
11498         /* 
11499          * Every second entry in the refs array is reserved for storing handle_class,
11500          * which is needed by the ldtoken implementation in the JIT.
11501          */
11502         rmb.nrefs = mb->nrefs;
11503         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11504         for (i = 0; i < mb->nrefs; i += 2) {
11505                 MonoClass *handle_class;
11506                 gpointer ref;
11507                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11508
11509                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11510                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11511                         /*
11512                          * The referenced DynamicMethod should already be created by the managed
11513                          * code, except in the case of circular references. In that case, we store
11514                          * method in the refs array, and fix it up later when the referenced 
11515                          * DynamicMethod is created.
11516                          */
11517                         if (method->mhandle) {
11518                                 ref = method->mhandle;
11519                         } else {
11520                                 /* FIXME: GC object stored in unmanaged memory */
11521                                 ref = method;
11522
11523                                 /* FIXME: GC object stored in unmanaged memory */
11524                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11525                         }
11526                         handle_class = mono_defaults.methodhandle_class;
11527                 } else {
11528                         MonoException *ex = NULL;
11529                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11530                         if (!ref)
11531                                 ex = mono_get_exception_type_load (NULL, NULL);
11532                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11533                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11534
11535                         if (ex) {
11536                                 g_free (rmb.refs);
11537                                 mono_raise_exception (ex);
11538                                 return;
11539                         }
11540                 }
11541
11542                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11543                 rmb.refs [i + 1] = handle_class;
11544         }               
11545
11546         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11547
11548         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11549         release_data = g_new (DynamicMethodReleaseData, 1);
11550         release_data->handle = handle;
11551         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11552         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11553                 g_free (release_data);
11554
11555         /* Fix up refs entries pointing at us */
11556         for (l = mb->referenced_by; l; l = l->next) {
11557                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11558                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11559                 gpointer *data;
11560                 
11561                 g_assert (method->mhandle);
11562
11563                 data = (gpointer*)wrapper->method_data;
11564                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11565                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11566                                 data [i + 1] = mb->mhandle;
11567                 }
11568         }
11569         g_slist_free (mb->referenced_by);
11570
11571         g_free (rmb.refs);
11572
11573         /* ilgen is no longer needed */
11574         mb->ilgen = NULL;
11575 }
11576
11577 #endif /* DISABLE_REFLECTION_EMIT */
11578
11579 /**
11580  * 
11581  * mono_reflection_is_valid_dynamic_token:
11582  * 
11583  * Returns TRUE if token is valid.
11584  * 
11585  */
11586 gboolean
11587 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11588 {
11589         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11590 }
11591
11592 MonoMethodSignature *
11593 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11594 {
11595         MonoMethodSignature *sig;
11596         g_assert (image->dynamic);
11597
11598         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11599         if (sig)
11600                 return sig;
11601
11602         return mono_method_signature (method);
11603 }
11604
11605 #ifndef DISABLE_REFLECTION_EMIT
11606
11607 /**
11608  * mono_reflection_lookup_dynamic_token:
11609  *
11610  * Finish the Builder object pointed to by TOKEN and return the corresponding
11611  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11612  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11613  * mapping table.
11614  *
11615  * LOCKING: Take the loader lock
11616  */
11617 gpointer
11618 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11619 {
11620         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11621         MonoObject *obj;
11622         MonoClass *klass;
11623
11624         mono_loader_lock ();
11625         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11626         mono_loader_unlock ();
11627         if (!obj) {
11628                 if (valid_token)
11629                         g_error ("Could not find required dynamic token 0x%08x", token);
11630                 else
11631                         return NULL;
11632         }
11633
11634         if (!handle_class)
11635                 handle_class = &klass;
11636         return resolve_object (image, obj, handle_class, context);
11637 }
11638
11639 /*
11640  * ensure_complete_type:
11641  *
11642  *   Ensure that KLASS is completed if it is a dynamic type, or references
11643  * dynamic types.
11644  */
11645 static void
11646 ensure_complete_type (MonoClass *klass)
11647 {
11648         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11649                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11650
11651                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11652
11653                 // Asserting here could break a lot of code
11654                 //g_assert (klass->wastypebuilder);
11655         }
11656
11657         if (klass->generic_class) {
11658                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11659                 int i;
11660
11661                 for (i = 0; i < inst->type_argc; ++i) {
11662                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11663                 }
11664         }
11665 }
11666
11667 static gpointer
11668 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11669 {
11670         gpointer result = NULL;
11671
11672         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11673                 result = mono_string_intern ((MonoString*)obj);
11674                 *handle_class = mono_defaults.string_class;
11675                 g_assert (result);
11676         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11677                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11678                 MonoClass *mc = mono_class_from_mono_type (type);
11679                 if (!mono_class_init (mc))
11680                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11681
11682                 if (context) {
11683                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11684                         result = mono_class_from_mono_type (inflated);
11685                         mono_metadata_free_type (inflated);
11686                 } else {
11687                         result = mono_class_from_mono_type (type);
11688                 }
11689                 *handle_class = mono_defaults.typehandle_class;
11690                 g_assert (result);
11691         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11692                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11693                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11694                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11695                 result = ((MonoReflectionMethod*)obj)->method;
11696                 if (context)
11697                         result = mono_class_inflate_generic_method (result, context);
11698                 *handle_class = mono_defaults.methodhandle_class;
11699                 g_assert (result);
11700         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11701                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11702                 result = mb->mhandle;
11703                 if (!result) {
11704                         /* Type is not yet created */
11705                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11706
11707                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11708
11709                         /*
11710                          * Hopefully this has been filled in by calling CreateType() on the
11711                          * TypeBuilder.
11712                          */
11713                         /*
11714                          * TODO: This won't work if the application finishes another 
11715                          * TypeBuilder instance instead of this one.
11716                          */
11717                         result = mb->mhandle;
11718                 }
11719                 if (context)
11720                         result = mono_class_inflate_generic_method (result, context);
11721                 *handle_class = mono_defaults.methodhandle_class;
11722         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11723                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11724
11725                 result = cb->mhandle;
11726                 if (!result) {
11727                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11728
11729                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11730                         result = cb->mhandle;
11731                 }
11732                 if (context)
11733                         result = mono_class_inflate_generic_method (result, context);
11734                 *handle_class = mono_defaults.methodhandle_class;
11735         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11736                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11737
11738                 ensure_complete_type (field->parent);
11739                 if (context) {
11740                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11741                         MonoClass *class = mono_class_from_mono_type (inflated);
11742                         MonoClassField *inflated_field;
11743                         gpointer iter = NULL;
11744                         mono_metadata_free_type (inflated);
11745                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11746                                 if (!strcmp (field->name, inflated_field->name))
11747                                         break;
11748                         }
11749                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11750                         result = inflated_field;
11751                 } else {
11752                         result = field;
11753                 }
11754                 *handle_class = mono_defaults.fieldhandle_class;
11755                 g_assert (result);
11756         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11757                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11758                 result = fb->handle;
11759
11760                 if (!result) {
11761                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11762
11763                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11764                         result = fb->handle;
11765                 }
11766
11767                 if (fb->handle && fb->handle->parent->generic_container) {
11768                         MonoClass *klass = fb->handle->parent;
11769                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11770                         MonoClass *inflated = mono_class_from_mono_type (type);
11771
11772                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11773                         g_assert (result);
11774                         mono_metadata_free_type (type);
11775                 }
11776                 *handle_class = mono_defaults.fieldhandle_class;
11777         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11778                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11779                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11780                 MonoClass *klass;
11781
11782                 klass = type->data.klass;
11783                 if (klass->wastypebuilder) {
11784                         /* Already created */
11785                         result = klass;
11786                 }
11787                 else {
11788                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11789                         result = type->data.klass;
11790                         g_assert (result);
11791                 }
11792                 *handle_class = mono_defaults.typehandle_class;
11793         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11794                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11795                 MonoMethodSignature *sig;
11796                 int nargs, i;
11797
11798                 if (helper->arguments)
11799                         nargs = mono_array_length (helper->arguments);
11800                 else
11801                         nargs = 0;
11802
11803                 sig = mono_metadata_signature_alloc (image, nargs);
11804                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11805                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11806
11807                 if (helper->unmanaged_call_conv) { /* unmanaged */
11808                         sig->call_convention = helper->unmanaged_call_conv - 1;
11809                         sig->pinvoke = TRUE;
11810                 } else if (helper->call_conv & 0x02) {
11811                         sig->call_convention = MONO_CALL_VARARG;
11812                 } else {
11813                         sig->call_convention = MONO_CALL_DEFAULT;
11814                 }
11815
11816                 sig->param_count = nargs;
11817                 /* TODO: Copy type ? */
11818                 sig->ret = helper->return_type->type;
11819                 for (i = 0; i < nargs; ++i)
11820                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11821
11822                 result = sig;
11823                 *handle_class = NULL;
11824         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11825                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11826                 /* Already created by the managed code */
11827                 g_assert (method->mhandle);
11828                 result = method->mhandle;
11829                 *handle_class = mono_defaults.methodhandle_class;
11830         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11831                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11832                 type = mono_class_inflate_generic_type (type, context);
11833                 result = mono_class_from_mono_type (type);
11834                 *handle_class = mono_defaults.typehandle_class;
11835                 g_assert (result);
11836                 mono_metadata_free_type (type);
11837         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11838                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11839                 type = mono_class_inflate_generic_type (type, context);
11840                 result = mono_class_from_mono_type (type);
11841                 *handle_class = mono_defaults.typehandle_class;
11842                 g_assert (result);
11843                 mono_metadata_free_type (type);
11844         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11845                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11846                 MonoClass *inflated;
11847                 MonoType *type;
11848                 MonoClassField *field;
11849
11850                 if (is_sre_field_builder (mono_object_class (f->fb)))
11851                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11852                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11853                         field = ((MonoReflectionField*)f->fb)->field;
11854                 else
11855                         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)));
11856
11857                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11858                 inflated = mono_class_from_mono_type (type);
11859
11860                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11861                 ensure_complete_type (field->parent);
11862                 g_assert (result);
11863                 mono_metadata_free_type (type);
11864                 *handle_class = mono_defaults.fieldhandle_class;
11865         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11866                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11867                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11868                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11869                 MonoMethod *method;
11870
11871                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11872                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11873                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11874                         method = ((MonoReflectionMethod *)c->cb)->method;
11875                 else
11876                         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)));
11877
11878                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11879                 *handle_class = mono_defaults.methodhandle_class;
11880                 mono_metadata_free_type (type);
11881         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11882                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11883                 if (m->method_args) {
11884                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11885                         if (context)
11886                                 result = mono_class_inflate_generic_method (result, context);
11887                 } else {
11888                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11889                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11890                         MonoMethod *method;
11891
11892                         if (is_sre_method_builder (mono_object_class (m->mb)))
11893                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11894                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11895                                 method = ((MonoReflectionMethod *)m->mb)->method;
11896                         else
11897                                 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)));
11898
11899                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11900                         mono_metadata_free_type (type);
11901                 }
11902                 *handle_class = mono_defaults.methodhandle_class;
11903         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11904                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11905                 MonoType *mtype;
11906                 MonoClass *klass;
11907                 MonoMethod *method;
11908                 gpointer iter;
11909                 char *name;
11910
11911                 mtype = mono_reflection_type_get_handle (m->parent);
11912                 klass = mono_class_from_mono_type (mtype);
11913
11914                 /* Find the method */
11915
11916                 name = mono_string_to_utf8 (m->name);
11917                 iter = NULL;
11918                 while ((method = mono_class_get_methods (klass, &iter))) {
11919                         if (!strcmp (method->name, name))
11920                                 break;
11921                 }
11922                 g_free (name);
11923
11924                 // FIXME:
11925                 g_assert (method);
11926                 // FIXME: Check parameters/return value etc. match
11927
11928                 result = method;
11929                 *handle_class = mono_defaults.methodhandle_class;
11930         } else if (is_sre_array (mono_object_get_class(obj)) ||
11931                                 is_sre_byref (mono_object_get_class(obj)) ||
11932                                 is_sre_pointer (mono_object_get_class(obj))) {
11933                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11934                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11935                 result = mono_class_from_mono_type (type);
11936                 *handle_class = mono_defaults.typehandle_class;
11937         } else {
11938                 g_print ("%s\n", obj->vtable->klass->name);
11939                 g_assert_not_reached ();
11940         }
11941         return result;
11942 }
11943
11944 #else /* DISABLE_REFLECTION_EMIT */
11945
11946 MonoArray*
11947 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11948 {
11949         g_assert_not_reached ();
11950         return NULL;
11951 }
11952
11953 void
11954 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11955 {
11956         g_assert_not_reached ();
11957 }
11958
11959 void
11960 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11961 {
11962         g_assert_not_reached ();
11963 }
11964
11965 void
11966 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11967 {
11968         g_assert_not_reached ();
11969 }
11970
11971 void
11972 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11973 {
11974         g_assert_not_reached ();
11975 }
11976
11977 void
11978 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11979 {
11980         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11981 }
11982
11983 void
11984 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11985 {
11986         g_assert_not_reached ();
11987 }
11988
11989 void
11990 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11991 {
11992         g_assert_not_reached ();
11993 }
11994
11995 MonoReflectionModule *
11996 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11997 {
11998         g_assert_not_reached ();
11999         return NULL;
12000 }
12001
12002 guint32
12003 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12004 {
12005         g_assert_not_reached ();
12006         return 0;
12007 }
12008
12009 guint32
12010 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12011 {
12012         g_assert_not_reached ();
12013         return 0;
12014 }
12015
12016 guint32
12017 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12018                                                  gboolean create_open_instance, gboolean register_token)
12019 {
12020         g_assert_not_reached ();
12021         return 0;
12022 }
12023
12024 void
12025 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12026 {
12027 }
12028
12029 void
12030 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
12031                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12032                                           MonoArray *events)
12033 {
12034         g_assert_not_reached ();
12035 }
12036
12037 void
12038 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12039 {
12040         *overrides = NULL;
12041         *num_overrides = 0;
12042 }
12043
12044 MonoReflectionEvent *
12045 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12046 {
12047         g_assert_not_reached ();
12048         return NULL;
12049 }
12050
12051 MonoReflectionType*
12052 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12053 {
12054         g_assert_not_reached ();
12055         return NULL;
12056 }
12057
12058 void
12059 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12060 {
12061         g_assert_not_reached ();
12062 }
12063
12064 MonoArray *
12065 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12066 {
12067         g_assert_not_reached ();
12068         return NULL;
12069 }
12070
12071 MonoArray *
12072 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12073 {
12074         g_assert_not_reached ();
12075         return NULL;
12076 }
12077
12078 void 
12079 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12080 {
12081 }
12082
12083 gpointer
12084 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12085 {
12086         return NULL;
12087 }
12088
12089 MonoType*
12090 mono_reflection_type_get_handle (MonoReflectionType* ref)
12091 {
12092         if (!ref)
12093                 return NULL;
12094         return ref->type;
12095 }
12096
12097 void
12098 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12099 {
12100         g_assert_not_reached ();
12101 }
12102
12103 #endif /* DISABLE_REFLECTION_EMIT */
12104
12105 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12106 const static guint32 declsec_flags_map[] = {
12107         0x00000000,                                     /* empty */
12108         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12109         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12110         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12111         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12112         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12113         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12114         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12115         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12116         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12117         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12118         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12119         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12120         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12121         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12122         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12123         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12124         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12125         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12126 };
12127
12128 /*
12129  * Returns flags that includes all available security action associated to the handle.
12130  * @token: metadata token (either for a class or a method)
12131  * @image: image where resides the metadata.
12132  */
12133 static guint32
12134 mono_declsec_get_flags (MonoImage *image, guint32 token)
12135 {
12136         int index = mono_metadata_declsec_from_index (image, token);
12137         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12138         guint32 result = 0;
12139         guint32 action;
12140         int i;
12141
12142         /* HasSecurity can be present for other, not specially encoded, attributes,
12143            e.g. SuppressUnmanagedCodeSecurityAttribute */
12144         if (index < 0)
12145                 return 0;
12146
12147         for (i = index; i < t->rows; i++) {
12148                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12149
12150                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12151                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12152                         break;
12153
12154                 action = cols [MONO_DECL_SECURITY_ACTION];
12155                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12156                         result |= declsec_flags_map [action];
12157                 } else {
12158                         g_assert_not_reached ();
12159                 }
12160         }
12161         return result;
12162 }
12163
12164 /*
12165  * Get the security actions (in the form of flags) associated with the specified method.
12166  *
12167  * @method: The method for which we want the declarative security flags.
12168  * Return the declarative security flags for the method (only).
12169  *
12170  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12171  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12172  */
12173 guint32
12174 mono_declsec_flags_from_method (MonoMethod *method)
12175 {
12176         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12177                 /* FIXME: No cache (for the moment) */
12178                 guint32 idx = mono_method_get_index (method);
12179                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12180                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12181                 return mono_declsec_get_flags (method->klass->image, idx);
12182         }
12183         return 0;
12184 }
12185
12186 /*
12187  * Get the security actions (in the form of flags) associated with the specified class.
12188  *
12189  * @klass: The class for which we want the declarative security flags.
12190  * Return the declarative security flags for the class.
12191  *
12192  * Note: We cache the flags inside the MonoClass structure as this will get 
12193  *       called very often (at least for each method).
12194  */
12195 guint32
12196 mono_declsec_flags_from_class (MonoClass *klass)
12197 {
12198         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12199                 if (!klass->ext || !klass->ext->declsec_flags) {
12200                         guint32 idx;
12201
12202                         idx = mono_metadata_token_index (klass->type_token);
12203                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12204                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12205                         mono_loader_lock ();
12206                         mono_class_alloc_ext (klass);
12207                         mono_loader_unlock ();
12208                         /* we cache the flags on classes */
12209                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12210                 }
12211                 return klass->ext->declsec_flags;
12212         }
12213         return 0;
12214 }
12215
12216 /*
12217  * Get the security actions (in the form of flags) associated with the specified assembly.
12218  *
12219  * @assembly: The assembly for which we want the declarative security flags.
12220  * Return the declarative security flags for the assembly.
12221  */
12222 guint32
12223 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12224 {
12225         guint32 idx = 1; /* there is only one assembly */
12226         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12227         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12228         return mono_declsec_get_flags (assembly->image, idx);
12229 }
12230
12231
12232 /*
12233  * Fill actions for the specific index (which may either be an encoded class token or
12234  * an encoded method token) from the metadata image.
12235  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12236  */
12237 static MonoBoolean
12238 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12239         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12240 {
12241         MonoBoolean result = FALSE;
12242         MonoTableInfo *t;
12243         guint32 cols [MONO_DECL_SECURITY_SIZE];
12244         int index = mono_metadata_declsec_from_index (image, token);
12245         int i;
12246
12247         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12248         for (i = index; i < t->rows; i++) {
12249                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12250
12251                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12252                         return result;
12253
12254                 /* if present only replace (class) permissions with method permissions */
12255                 /* if empty accept either class or method permissions */
12256                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12257                         if (!actions->demand.blob) {
12258                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12259                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12260                                 actions->demand.blob = (char*) (blob + 2);
12261                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12262                                 result = TRUE;
12263                         }
12264                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12265                         if (!actions->noncasdemand.blob) {
12266                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12267                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12268                                 actions->noncasdemand.blob = (char*) (blob + 2);
12269                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12270                                 result = TRUE;
12271                         }
12272                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12273                         if (!actions->demandchoice.blob) {
12274                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12275                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12276                                 actions->demandchoice.blob = (char*) (blob + 2);
12277                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12278                                 result = TRUE;
12279                         }
12280                 }
12281         }
12282
12283         return result;
12284 }
12285
12286 static MonoBoolean
12287 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12288         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12289 {
12290         guint32 idx = mono_metadata_token_index (klass->type_token);
12291         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12292         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12293         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12294 }
12295
12296 static MonoBoolean
12297 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12298         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12299 {
12300         guint32 idx = mono_method_get_index (method);
12301         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12302         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12303         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12304 }
12305
12306 /*
12307  * Collect all actions (that requires to generate code in mini) assigned for
12308  * the specified method.
12309  * Note: Don't use the content of actions if the function return FALSE.
12310  */
12311 MonoBoolean
12312 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12313 {
12314         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12315                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12316         MonoBoolean result = FALSE;
12317         guint32 flags;
12318
12319         /* quick exit if no declarative security is present in the metadata */
12320         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12321                 return FALSE;
12322
12323         /* we want the original as the wrapper is "free" of the security informations */
12324         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12325                 method = mono_marshal_method_from_wrapper (method);
12326                 if (!method)
12327                         return FALSE;
12328         }
12329
12330         /* First we look for method-level attributes */
12331         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12332                 mono_class_init (method->klass);
12333                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12334
12335                 result = mono_declsec_get_method_demands_params (method, demands, 
12336                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12337         }
12338
12339         /* Here we use (or create) the class declarative cache to look for demands */
12340         flags = mono_declsec_flags_from_class (method->klass);
12341         if (flags & mask) {
12342                 if (!result) {
12343                         mono_class_init (method->klass);
12344                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12345                 }
12346                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12347                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12348         }
12349
12350         /* The boolean return value is used as a shortcut in case nothing needs to
12351            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12352         return result;
12353 }
12354
12355
12356 /*
12357  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12358  *
12359  * Note: Don't use the content of actions if the function return FALSE.
12360  */
12361 MonoBoolean
12362 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12363 {
12364         MonoBoolean result = FALSE;
12365         guint32 flags;
12366
12367         /* quick exit if no declarative security is present in the metadata */
12368         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12369                 return FALSE;
12370
12371         /* we want the original as the wrapper is "free" of the security informations */
12372         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12373                 method = mono_marshal_method_from_wrapper (method);
12374                 if (!method)
12375                         return FALSE;
12376         }
12377
12378         /* results are independant - zeroize both */
12379         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12380         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12381
12382         /* First we look for method-level attributes */
12383         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12384                 mono_class_init (method->klass);
12385
12386                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12387                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12388         }
12389
12390         /* Here we use (or create) the class declarative cache to look for demands */
12391         flags = mono_declsec_flags_from_class (method->klass);
12392         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12393                 mono_class_init (method->klass);
12394
12395                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12396                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12397         }
12398
12399         return result;
12400 }
12401
12402 /*
12403  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12404  *
12405  * @klass       The inherited class - this is the class that provides the security check (attributes)
12406  * @demans      
12407  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12408  * 
12409  * Note: Don't use the content of actions if the function return FALSE.
12410  */
12411 MonoBoolean
12412 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12413 {
12414         MonoBoolean result = FALSE;
12415         guint32 flags;
12416
12417         /* quick exit if no declarative security is present in the metadata */
12418         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12419                 return FALSE;
12420
12421         /* Here we use (or create) the class declarative cache to look for demands */
12422         flags = mono_declsec_flags_from_class (klass);
12423         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12424                 mono_class_init (klass);
12425                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12426
12427                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12428                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12429         }
12430
12431         return result;
12432 }
12433
12434 /*
12435  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12436  *
12437  * Note: Don't use the content of actions if the function return FALSE.
12438  */
12439 MonoBoolean
12440 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12441 {
12442         /* quick exit if no declarative security is present in the metadata */
12443         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12444                 return FALSE;
12445
12446         /* we want the original as the wrapper is "free" of the security informations */
12447         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12448                 method = mono_marshal_method_from_wrapper (method);
12449                 if (!method)
12450                         return FALSE;
12451         }
12452
12453         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12454                 mono_class_init (method->klass);
12455                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12456
12457                 return mono_declsec_get_method_demands_params (method, demands, 
12458                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12459         }
12460         return FALSE;
12461 }
12462
12463
12464 static MonoBoolean
12465 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12466 {
12467         guint32 cols [MONO_DECL_SECURITY_SIZE];
12468         MonoTableInfo *t;
12469         int i;
12470
12471         int index = mono_metadata_declsec_from_index (image, token);
12472         if (index == -1)
12473                 return FALSE;
12474
12475         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12476         for (i = index; i < t->rows; i++) {
12477                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12478
12479                 /* shortcut - index are ordered */
12480                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12481                         return FALSE;
12482
12483                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12484                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12485                         entry->blob = (char*) (metadata + 2);
12486                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12487                         return TRUE;
12488                 }
12489         }
12490
12491         return FALSE;
12492 }
12493
12494 MonoBoolean
12495 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12496 {
12497         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12498                 guint32 idx = mono_method_get_index (method);
12499                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12500                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12501                 return get_declsec_action (method->klass->image, idx, action, entry);
12502         }
12503         return FALSE;
12504 }
12505
12506 MonoBoolean
12507 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12508 {
12509         /* use cache */
12510         guint32 flags = mono_declsec_flags_from_class (klass);
12511         if (declsec_flags_map [action] & flags) {
12512                 guint32 idx = mono_metadata_token_index (klass->type_token);
12513                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12514                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12515                 return get_declsec_action (klass->image, idx, action, entry);
12516         }
12517         return FALSE;
12518 }
12519
12520 MonoBoolean
12521 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12522 {
12523         guint32 idx = 1; /* there is only one assembly */
12524         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12525         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12526
12527         return get_declsec_action (assembly->image, idx, action, entry);
12528 }
12529
12530 gboolean
12531 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12532 {
12533         MonoObject *res, *exc;
12534         void *params [1];
12535         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12536         static MonoMethod *method = NULL;
12537
12538         if (!System_Reflection_Emit_TypeBuilder) {
12539                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12540                 g_assert (System_Reflection_Emit_TypeBuilder);
12541         }
12542         if (method == NULL) {
12543                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12544                 g_assert (method);
12545         }
12546
12547         /* 
12548          * The result of mono_type_get_object () might be a System.MonoType but we
12549          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12550          */
12551         g_assert (mono_class_get_ref_info (klass));
12552         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12553
12554         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12555
12556         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12557         if (exc)
12558                 return FALSE;
12559         else
12560                 return *(MonoBoolean*)mono_object_unbox (res);
12561 }