[bug] Prevent a GetMethodBody call on a dynamic method. Fixes 665788
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45
46 static gboolean is_usertype (MonoReflectionType *ref);
47 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
48
49 typedef struct {
50         char *p;
51         char *buf;
52         char *end;
53 } SigBuffer;
54
55 #define TEXT_OFFSET 512
56 #define CLI_H_SIZE 136
57 #define FILE_ALIGN 512
58 #define VIRT_ALIGN 8192
59 #define START_TEXT_RVA  0x00002000
60
61 typedef struct {
62         MonoReflectionILGen *ilgen;
63         MonoReflectionType *rtype;
64         MonoArray *parameters;
65         MonoArray *generic_params;
66         MonoGenericContainer *generic_container;
67         MonoArray *pinfo;
68         MonoArray *opt_types;
69         guint32 attrs;
70         guint32 iattrs;
71         guint32 call_conv;
72         guint32 *table_idx; /* note: it's a pointer */
73         MonoArray *code;
74         MonoObject *type;
75         MonoString *name;
76         MonoBoolean init_locals;
77         MonoBoolean skip_visibility;
78         MonoArray *return_modreq;
79         MonoArray *return_modopt;
80         MonoArray *param_modreq;
81         MonoArray *param_modopt;
82         MonoArray *permissions;
83         MonoMethod *mhandle;
84         guint32 nrefs;
85         gpointer *refs;
86         /* for PInvoke */
87         int charset, extra_flags, native_cc;
88         MonoString *dll, *dllentry;
89 } ReflectionMethodBuilder;
90
91 typedef struct {
92         guint32 owner;
93         MonoReflectionGenericParam *gparam;
94 } GenericParamTableEntry;
95
96 const unsigned char table_sizes [MONO_TABLE_NUM] = {
97         MONO_MODULE_SIZE,
98         MONO_TYPEREF_SIZE,
99         MONO_TYPEDEF_SIZE,
100         0,
101         MONO_FIELD_SIZE,
102         0,
103         MONO_METHOD_SIZE,
104         0,
105         MONO_PARAM_SIZE,
106         MONO_INTERFACEIMPL_SIZE,
107         MONO_MEMBERREF_SIZE,    /* 0x0A */
108         MONO_CONSTANT_SIZE,
109         MONO_CUSTOM_ATTR_SIZE,
110         MONO_FIELD_MARSHAL_SIZE,
111         MONO_DECL_SECURITY_SIZE,
112         MONO_CLASS_LAYOUT_SIZE,
113         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
114         MONO_STAND_ALONE_SIGNATURE_SIZE,
115         MONO_EVENT_MAP_SIZE,
116         0,
117         MONO_EVENT_SIZE,
118         MONO_PROPERTY_MAP_SIZE,
119         0,
120         MONO_PROPERTY_SIZE,
121         MONO_METHOD_SEMA_SIZE,
122         MONO_METHODIMPL_SIZE,
123         MONO_MODULEREF_SIZE,    /* 0x1A */
124         MONO_TYPESPEC_SIZE,
125         MONO_IMPLMAP_SIZE,      
126         MONO_FIELD_RVA_SIZE,
127         0,
128         0,
129         MONO_ASSEMBLY_SIZE,     /* 0x20 */
130         MONO_ASSEMBLY_PROCESSOR_SIZE,
131         MONO_ASSEMBLYOS_SIZE,
132         MONO_ASSEMBLYREF_SIZE,
133         MONO_ASSEMBLYREFPROC_SIZE,
134         MONO_ASSEMBLYREFOS_SIZE,
135         MONO_FILE_SIZE,
136         MONO_EXP_TYPE_SIZE,
137         MONO_MANIFEST_SIZE,
138         MONO_NESTED_CLASS_SIZE,
139
140         MONO_GENERICPARAM_SIZE, /* 0x2A */
141         MONO_METHODSPEC_SIZE,
142         MONO_GENPARCONSTRAINT_SIZE
143
144 };
145
146 #ifndef DISABLE_REFLECTION_EMIT
147 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
148 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
149 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
150 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
151 static void    ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
153 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
154 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
155 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
156 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
157 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
158 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
159 #endif
160
161 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
162 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
163 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
164 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
165 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
166 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
167 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
168 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
169 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
170 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
171 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
172 static gboolean is_sre_array (MonoClass *class);
173 static gboolean is_sre_byref (MonoClass *class);
174 static gboolean is_sre_pointer (MonoClass *class);
175 static gboolean is_sre_type_builder (MonoClass *class);
176 static gboolean is_sre_method_builder (MonoClass *class);
177 static gboolean is_sre_ctor_builder (MonoClass *class);
178 static gboolean is_sre_field_builder (MonoClass *class);
179 static gboolean is_sr_mono_method (MonoClass *class);
180 static gboolean is_sr_mono_cmethod (MonoClass *class);
181 static gboolean is_sr_mono_generic_method (MonoClass *class);
182 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_field (MonoClass *class);
184 static gboolean is_sr_mono_property (MonoClass *class);
185 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
186 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
187
188 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
189 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
190 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
191
192 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
193 static void init_type_builder_generics (MonoObject *type);
194
195 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
196 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
197         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
198         __type = mono_reflection_type_resolve_user_types (__type);      \
199         mono_array_set (arr, MonoReflectionType*, index, __type);       \
200 } while (0)
201
202 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
203
204 void
205 mono_reflection_init (void)
206 {
207 }
208
209 static void
210 sigbuffer_init (SigBuffer *buf, int size)
211 {
212         buf->buf = g_malloc (size);
213         buf->p = buf->buf;
214         buf->end = buf->buf + size;
215 }
216
217 static void
218 sigbuffer_make_room (SigBuffer *buf, int size)
219 {
220         if (buf->end - buf->p < size) {
221                 int new_size = buf->end - buf->buf + size + 32;
222                 char *p = g_realloc (buf->buf, new_size);
223                 size = buf->p - buf->buf;
224                 buf->buf = p;
225                 buf->p = p + size;
226                 buf->end = buf->buf + new_size;
227         }
228 }
229
230 static void
231 sigbuffer_add_value (SigBuffer *buf, guint32 val)
232 {
233         sigbuffer_make_room (buf, 6);
234         mono_metadata_encode_value (val, buf->p, &buf->p);
235 }
236
237 static void
238 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
239 {
240         sigbuffer_make_room (buf, 1);
241         buf->p [0] = val;
242         buf->p++;
243 }
244
245 static void
246 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
247 {
248         sigbuffer_make_room (buf, size);
249         memcpy (buf->p, p, size);
250         buf->p += size;
251 }
252
253 static void
254 sigbuffer_free (SigBuffer *buf)
255 {
256         g_free (buf->buf);
257 }
258
259 #ifndef DISABLE_REFLECTION_EMIT
260 /**
261  * mp_g_alloc:
262  *
263  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
264  * from the C heap.
265  */
266 static gpointer
267 image_g_malloc (MonoImage *image, guint size)
268 {
269         if (image)
270                 return mono_image_alloc (image, size);
271         else
272                 return g_malloc (size);
273 }
274 #endif /* !DISABLE_REFLECTION_EMIT */
275
276 /**
277  * image_g_alloc0:
278  *
279  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
280  * from the C heap.
281  */
282 static gpointer
283 image_g_malloc0 (MonoImage *image, guint size)
284 {
285         if (image)
286                 return mono_image_alloc0 (image, size);
287         else
288                 return g_malloc0 (size);
289 }
290
291 #ifndef DISABLE_REFLECTION_EMIT
292 static char*
293 image_strdup (MonoImage *image, const char *s)
294 {
295         if (image)
296                 return mono_image_strdup (image, s);
297         else
298                 return g_strdup (s);
299 }
300 #endif
301
302 #define image_g_new(image,struct_type, n_structs)               \
303     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
304
305 #define image_g_new0(image,struct_type, n_structs)              \
306     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
307
308
309 static void
310 alloc_table (MonoDynamicTable *table, guint nrows)
311 {
312         table->rows = nrows;
313         g_assert (table->columns);
314         if (nrows + 1 >= table->alloc_rows) {
315                 while (nrows + 1 >= table->alloc_rows) {
316                         if (table->alloc_rows == 0)
317                                 table->alloc_rows = 16;
318                         else
319                                 table->alloc_rows *= 2;
320                 }
321
322                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
323         }
324 }
325
326 static void
327 make_room_in_stream (MonoDynamicStream *stream, int size)
328 {
329         if (size <= stream->alloc_size)
330                 return;
331         
332         while (stream->alloc_size <= size) {
333                 if (stream->alloc_size < 4096)
334                         stream->alloc_size = 4096;
335                 else
336                         stream->alloc_size *= 2;
337         }
338         
339         stream->data = g_realloc (stream->data, stream->alloc_size);
340 }
341
342 static guint32
343 string_heap_insert (MonoDynamicStream *sh, const char *str)
344 {
345         guint32 idx;
346         guint32 len;
347         gpointer oldkey, oldval;
348
349         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
350                 return GPOINTER_TO_UINT (oldval);
351
352         len = strlen (str) + 1;
353         idx = sh->index;
354         
355         make_room_in_stream (sh, idx + len);
356
357         /*
358          * We strdup the string even if we already copy them in sh->data
359          * so that the string pointers in the hash remain valid even if
360          * we need to realloc sh->data. We may want to avoid that later.
361          */
362         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
363         memcpy (sh->data + idx, str, len);
364         sh->index += len;
365         return idx;
366 }
367
368 static guint32
369 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
370 {
371         char *name = mono_string_to_utf8 (str);
372         guint32 idx;
373         idx = string_heap_insert (sh, name);
374         g_free (name);
375         return idx;
376 }
377
378 #ifndef DISABLE_REFLECTION_EMIT
379 static void
380 string_heap_init (MonoDynamicStream *sh)
381 {
382         sh->index = 0;
383         sh->alloc_size = 4096;
384         sh->data = g_malloc (4096);
385         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
386         string_heap_insert (sh, "");
387 }
388 #endif
389
390 static guint32
391 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
392 {
393         guint32 idx;
394         
395         make_room_in_stream (stream, stream->index + len);
396         memcpy (stream->data + stream->index, data, len);
397         idx = stream->index;
398         stream->index += len;
399         /* 
400          * align index? Not without adding an additional param that controls it since
401          * we may store a blob value in pieces.
402          */
403         return idx;
404 }
405
406 static guint32
407 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
408 {
409         guint32 idx;
410         
411         make_room_in_stream (stream, stream->index + len);
412         memset (stream->data + stream->index, 0, len);
413         idx = stream->index;
414         stream->index += len;
415         return idx;
416 }
417
418 static void
419 stream_data_align (MonoDynamicStream *stream)
420 {
421         char buf [4] = {0};
422         guint32 count = stream->index % 4;
423
424         /* we assume the stream data will be aligned */
425         if (count)
426                 mono_image_add_stream_data (stream, buf, 4 - count);
427 }
428
429 #ifndef DISABLE_REFLECTION_EMIT
430 static int
431 mono_blob_entry_hash (const char* str)
432 {
433         guint len, h;
434         const char *end;
435         len = mono_metadata_decode_blob_size (str, &str);
436         if (len > 0) {
437                 end = str + len;
438                 h = *str;
439                 for (str += 1; str < end; str++)
440                         h = (h << 5) - h + *str;
441                 return h;
442         } else {
443                 return 0;
444         }
445 }
446
447 static gboolean
448 mono_blob_entry_equal (const char *str1, const char *str2) {
449         int len, len2;
450         const char *end1;
451         const char *end2;
452         len = mono_metadata_decode_blob_size (str1, &end1);
453         len2 = mono_metadata_decode_blob_size (str2, &end2);
454         if (len != len2)
455                 return 0;
456         return memcmp (end1, end2, len) == 0;
457 }
458 #endif
459 static guint32
460 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
461 {
462         guint32 idx;
463         char *copy;
464         gpointer oldkey, oldval;
465
466         copy = g_malloc (s1+s2);
467         memcpy (copy, b1, s1);
468         memcpy (copy + s1, b2, s2);
469         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
470                 g_free (copy);
471                 idx = GPOINTER_TO_UINT (oldval);
472         } else {
473                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
474                 mono_image_add_stream_data (&assembly->blob, b2, s2);
475                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
476         }
477         return idx;
478 }
479
480 static guint32
481 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
482 {
483         char blob_size [8];
484         char *b = blob_size;
485         guint32 size = buf->p - buf->buf;
486         /* store length */
487         g_assert (size <= (buf->end - buf->buf));
488         mono_metadata_encode_value (size, b, &b);
489         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
490 }
491
492 /*
493  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
494  * dest may be misaligned.
495  */
496 static void
497 swap_with_size (char *dest, const char* val, int len, int nelem) {
498 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
499         int elem;
500
501         for (elem = 0; elem < nelem; ++elem) {
502                 switch (len) {
503                 case 1:
504                         *dest = *val;
505                         break;
506                 case 2:
507                         dest [0] = val [1];
508                         dest [1] = val [0];
509                         break;
510                 case 4:
511                         dest [0] = val [3];
512                         dest [1] = val [2];
513                         dest [2] = val [1];
514                         dest [3] = val [0];
515                         break;
516                 case 8:
517                         dest [0] = val [7];
518                         dest [1] = val [6];
519                         dest [2] = val [5];
520                         dest [3] = val [4];
521                         dest [4] = val [3];
522                         dest [5] = val [2];
523                         dest [6] = val [1];
524                         dest [7] = val [0];
525                         break;
526                 default:
527                         g_assert_not_reached ();
528                 }
529                 dest += len;
530                 val += len;
531         }
532 #else
533         memcpy (dest, val, len * nelem);
534 #endif
535 }
536
537 static guint32
538 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
539 {
540         char blob_size [64];
541         char *b = blob_size;
542         guint32 idx = 0, len;
543
544         len = str->length * 2;
545         mono_metadata_encode_value (len, b, &b);
546 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
547         {
548                 char *swapped = g_malloc (2 * mono_string_length (str));
549                 const char *p = (const char*)mono_string_chars (str);
550
551                 swap_with_size (swapped, p, 2, mono_string_length (str));
552                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
553                 g_free (swapped);
554         }
555 #else
556         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
557 #endif
558         return idx;
559 }
560
561 #ifndef DISABLE_REFLECTION_EMIT
562 static MonoClass *
563 default_class_from_mono_type (MonoType *type)
564 {
565         switch (type->type) {
566         case MONO_TYPE_OBJECT:
567                 return mono_defaults.object_class;
568         case MONO_TYPE_VOID:
569                 return mono_defaults.void_class;
570         case MONO_TYPE_BOOLEAN:
571                 return mono_defaults.boolean_class;
572         case MONO_TYPE_CHAR:
573                 return mono_defaults.char_class;
574         case MONO_TYPE_I1:
575                 return mono_defaults.sbyte_class;
576         case MONO_TYPE_U1:
577                 return mono_defaults.byte_class;
578         case MONO_TYPE_I2:
579                 return mono_defaults.int16_class;
580         case MONO_TYPE_U2:
581                 return mono_defaults.uint16_class;
582         case MONO_TYPE_I4:
583                 return mono_defaults.int32_class;
584         case MONO_TYPE_U4:
585                 return mono_defaults.uint32_class;
586         case MONO_TYPE_I:
587                 return mono_defaults.int_class;
588         case MONO_TYPE_U:
589                 return mono_defaults.uint_class;
590         case MONO_TYPE_I8:
591                 return mono_defaults.int64_class;
592         case MONO_TYPE_U8:
593                 return mono_defaults.uint64_class;
594         case MONO_TYPE_R4:
595                 return mono_defaults.single_class;
596         case MONO_TYPE_R8:
597                 return mono_defaults.double_class;
598         case MONO_TYPE_STRING:
599                 return mono_defaults.string_class;
600         default:
601                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
602                 g_assert_not_reached ();
603         }
604         
605         return NULL;
606 }
607 #endif
608
609 /*
610  * mono_class_get_ref_info:
611  *
612  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
613  */
614 gpointer
615 mono_class_get_ref_info (MonoClass *klass)
616 {
617         if (klass->ref_info_handle == 0)
618                 return NULL;
619         else
620                 return mono_gchandle_get_target (klass->ref_info_handle);
621 }
622
623 void
624 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
625 {
626         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
627         g_assert (klass->ref_info_handle != 0);
628 }
629
630 void
631 mono_class_free_ref_info (MonoClass *klass)
632 {
633         if (klass->ref_info_handle) {
634                 mono_gchandle_free (klass->ref_info_handle);
635                 klass->ref_info_handle = 0;
636         }
637 }
638
639 static void
640 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
641 {
642         int i;
643         MonoGenericInst *class_inst;
644         MonoClass *klass;
645
646         g_assert (gclass);
647
648         class_inst = gclass->context.class_inst;
649
650         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
651         klass = gclass->container_class;
652         sigbuffer_add_value (buf, klass->byval_arg.type);
653         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
654
655         sigbuffer_add_value (buf, class_inst->type_argc);
656         for (i = 0; i < class_inst->type_argc; ++i)
657                 encode_type (assembly, class_inst->type_argv [i], buf);
658
659 }
660
661 static void
662 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
663 {
664         if (!type) {
665                 g_assert_not_reached ();
666                 return;
667         }
668                 
669         if (type->byref)
670                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
671
672         switch (type->type){
673         case MONO_TYPE_VOID:
674         case MONO_TYPE_BOOLEAN:
675         case MONO_TYPE_CHAR:
676         case MONO_TYPE_I1:
677         case MONO_TYPE_U1:
678         case MONO_TYPE_I2:
679         case MONO_TYPE_U2:
680         case MONO_TYPE_I4:
681         case MONO_TYPE_U4:
682         case MONO_TYPE_I8:
683         case MONO_TYPE_U8:
684         case MONO_TYPE_R4:
685         case MONO_TYPE_R8:
686         case MONO_TYPE_I:
687         case MONO_TYPE_U:
688         case MONO_TYPE_STRING:
689         case MONO_TYPE_OBJECT:
690         case MONO_TYPE_TYPEDBYREF:
691                 sigbuffer_add_value (buf, type->type);
692                 break;
693         case MONO_TYPE_PTR:
694                 sigbuffer_add_value (buf, type->type);
695                 encode_type (assembly, type->data.type, buf);
696                 break;
697         case MONO_TYPE_SZARRAY:
698                 sigbuffer_add_value (buf, type->type);
699                 encode_type (assembly, &type->data.klass->byval_arg, buf);
700                 break;
701         case MONO_TYPE_VALUETYPE:
702         case MONO_TYPE_CLASS: {
703                 MonoClass *k = mono_class_from_mono_type (type);
704
705                 if (k->generic_container) {
706                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
707                         encode_generic_class (assembly, gclass, buf);
708                 } else {
709                         /*
710                          * Make sure we use the correct type.
711                          */
712                         sigbuffer_add_value (buf, k->byval_arg.type);
713                         /*
714                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
715                          * otherwise two typerefs could point to the same type, leading to
716                          * verification errors.
717                          */
718                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
719                 }
720                 break;
721         }
722         case MONO_TYPE_ARRAY:
723                 sigbuffer_add_value (buf, type->type);
724                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
725                 sigbuffer_add_value (buf, type->data.array->rank);
726                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
727                 sigbuffer_add_value (buf, 0);
728                 break;
729         case MONO_TYPE_GENERICINST:
730                 encode_generic_class (assembly, type->data.generic_class, buf);
731                 break;
732         case MONO_TYPE_VAR:
733         case MONO_TYPE_MVAR:
734                 sigbuffer_add_value (buf, type->type);
735                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
736                 break;
737         default:
738                 g_error ("need to encode type %x", type->type);
739         }
740 }
741
742 static void
743 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
744 {
745         if (!type) {
746                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
747                 return;
748         }
749
750         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
751 }
752
753 static void
754 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
755 {
756         int i;
757
758         if (modreq) {
759                 for (i = 0; i < mono_array_length (modreq); ++i) {
760                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
761                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
762                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
763                 }
764         }
765         if (modopt) {
766                 for (i = 0; i < mono_array_length (modopt); ++i) {
767                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
768                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
769                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
770                 }
771         }
772 }
773
774 #ifndef DISABLE_REFLECTION_EMIT
775 static guint32
776 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
777 {
778         SigBuffer buf;
779         int i;
780         guint32 nparams =  sig->param_count;
781         guint32 idx;
782
783         if (!assembly->save)
784                 return 0;
785
786         sigbuffer_init (&buf, 32);
787         /*
788          * FIXME: vararg, explicit_this, differenc call_conv values...
789          */
790         idx = sig->call_convention;
791         if (sig->hasthis)
792                 idx |= 0x20; /* hasthis */
793         if (sig->generic_param_count)
794                 idx |= 0x10; /* generic */
795         sigbuffer_add_byte (&buf, idx);
796         if (sig->generic_param_count)
797                 sigbuffer_add_value (&buf, sig->generic_param_count);
798         sigbuffer_add_value (&buf, nparams);
799         encode_type (assembly, sig->ret, &buf);
800         for (i = 0; i < nparams; ++i) {
801                 if (i == sig->sentinelpos)
802                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
803                 encode_type (assembly, sig->params [i], &buf);
804         }
805         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
806         sigbuffer_free (&buf);
807         return idx;
808 }
809 #endif
810
811 static guint32
812 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
813 {
814         /*
815          * FIXME: reuse code from method_encode_signature().
816          */
817         SigBuffer buf;
818         int i;
819         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
820         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
821         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
822         guint32 idx;
823
824         sigbuffer_init (&buf, 32);
825         /* LAMESPEC: all the call conv spec is foobared */
826         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
827         if (mb->call_conv & 2)
828                 idx |= 0x5; /* vararg */
829         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
830                 idx |= 0x20; /* hasthis */
831         if (ngparams)
832                 idx |= 0x10; /* generic */
833         sigbuffer_add_byte (&buf, idx);
834         if (ngparams)
835                 sigbuffer_add_value (&buf, ngparams);
836         sigbuffer_add_value (&buf, nparams + notypes);
837         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
838         encode_reflection_type (assembly, mb->rtype, &buf);
839         for (i = 0; i < nparams; ++i) {
840                 MonoArray *modreq = NULL;
841                 MonoArray *modopt = NULL;
842                 MonoReflectionType *pt;
843
844                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
845                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
846                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
847                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
848                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
849                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
850                 encode_reflection_type (assembly, pt, &buf);
851         }
852         if (notypes)
853                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
854         for (i = 0; i < notypes; ++i) {
855                 MonoReflectionType *pt;
856
857                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
858                 encode_reflection_type (assembly, pt, &buf);
859         }
860
861         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
862         sigbuffer_free (&buf);
863         return idx;
864 }
865
866 static guint32
867 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
868 {
869         MonoDynamicTable *table;
870         guint32 *values;
871         guint32 idx, sig_idx;
872         guint nl = mono_array_length (ilgen->locals);
873         SigBuffer buf;
874         int i;
875
876         sigbuffer_init (&buf, 32);
877         sigbuffer_add_value (&buf, 0x07);
878         sigbuffer_add_value (&buf, nl);
879         for (i = 0; i < nl; ++i) {
880                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
881                 
882                 if (lb->is_pinned)
883                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
884                 
885                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
886         }
887         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
888         sigbuffer_free (&buf);
889
890         if (assembly->standalonesig_cache == NULL)
891                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
892         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
893         if (idx)
894                 return idx;
895
896         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
897         idx = table->next_idx ++;
898         table->rows ++;
899         alloc_table (table, table->rows);
900         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
901
902         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
903
904         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
905
906         return idx;
907 }
908
909 static guint32
910 method_count_clauses (MonoReflectionILGen *ilgen)
911 {
912         guint32 num_clauses = 0;
913         int i;
914
915         MonoILExceptionInfo *ex_info;
916         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
917                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
918                 if (ex_info->handlers)
919                         num_clauses += mono_array_length (ex_info->handlers);
920                 else
921                         num_clauses++;
922         }
923
924         return num_clauses;
925 }
926
927 #ifndef DISABLE_REFLECTION_EMIT
928 static MonoExceptionClause*
929 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
930 {
931         MonoExceptionClause *clauses;
932         MonoExceptionClause *clause;
933         MonoILExceptionInfo *ex_info;
934         MonoILExceptionBlock *ex_block;
935         guint32 finally_start;
936         int i, j, clause_index;;
937
938         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
939
940         clause_index = 0;
941         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
942                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
943                 finally_start = ex_info->start + ex_info->len;
944                 if (!ex_info->handlers)
945                         continue;
946                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
947                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
948                         clause = &(clauses [clause_index]);
949
950                         clause->flags = ex_block->type;
951                         clause->try_offset = ex_info->start;
952
953                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
954                                 clause->try_len = finally_start - ex_info->start;
955                         else
956                                 clause->try_len = ex_info->len;
957                         clause->handler_offset = ex_block->start;
958                         clause->handler_len = ex_block->len;
959                         if (ex_block->extype) {
960                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
961                         } else {
962                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
963                                         clause->data.filter_offset = ex_block->filter_offset;
964                                 else
965                                         clause->data.filter_offset = 0;
966                         }
967                         finally_start = ex_block->start + ex_block->len;
968
969                         clause_index ++;
970                 }
971         }
972
973         return clauses;
974 }
975 #endif /* !DISABLE_REFLECTION_EMIT */
976
977 static guint32
978 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
979 {
980         char flags = 0;
981         guint32 idx;
982         guint32 code_size;
983         gint32 max_stack, i;
984         gint32 num_locals = 0;
985         gint32 num_exception = 0;
986         gint maybe_small;
987         guint32 fat_flags;
988         char fat_header [12];
989         guint32 int_value;
990         guint16 short_value;
991         guint32 local_sig = 0;
992         guint32 header_size = 12;
993         MonoArray *code;
994
995         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
996                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
997                 return 0;
998
999         /*if (mb->name)
1000                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1001         if (mb->ilgen) {
1002                 code = mb->ilgen->code;
1003                 code_size = mb->ilgen->code_len;
1004                 max_stack = mb->ilgen->max_stack;
1005                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1006                 if (mb->ilgen->ex_handlers)
1007                         num_exception = method_count_clauses (mb->ilgen);
1008         } else {
1009                 code = mb->code;
1010                 if (code == NULL){
1011                         char *name = mono_string_to_utf8 (mb->name);
1012                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1013                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1014                         g_free (str);
1015                         g_free (name);
1016                         mono_raise_exception (exception);
1017                 }
1018
1019                 code_size = mono_array_length (code);
1020                 max_stack = 8; /* we probably need to run a verifier on the code... */
1021         }
1022
1023         stream_data_align (&assembly->code);
1024
1025         /* check for exceptions, maxstack, locals */
1026         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1027         if (maybe_small) {
1028                 if (code_size < 64 && !(code_size & 1)) {
1029                         flags = (code_size << 2) | 0x2;
1030                 } else if (code_size < 32 && (code_size & 1)) {
1031                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1032                 } else {
1033                         goto fat_header;
1034                 }
1035                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1036                 /* add to the fixup todo list */
1037                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1038                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1039                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1040                 return assembly->text_rva + idx;
1041         } 
1042 fat_header:
1043         if (num_locals)
1044                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1045         /* 
1046          * FIXME: need to set also the header size in fat_flags.
1047          * (and more sects and init locals flags)
1048          */
1049         fat_flags =  0x03;
1050         if (num_exception)
1051                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1052         if (mb->init_locals)
1053                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1054         fat_header [0] = fat_flags;
1055         fat_header [1] = (header_size / 4 ) << 4;
1056         short_value = GUINT16_TO_LE (max_stack);
1057         memcpy (fat_header + 2, &short_value, 2);
1058         int_value = GUINT32_TO_LE (code_size);
1059         memcpy (fat_header + 4, &int_value, 4);
1060         int_value = GUINT32_TO_LE (local_sig);
1061         memcpy (fat_header + 8, &int_value, 4);
1062         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1063         /* add to the fixup todo list */
1064         if (mb->ilgen && mb->ilgen->num_token_fixups)
1065                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1066         
1067         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1068         if (num_exception) {
1069                 unsigned char sheader [4];
1070                 MonoILExceptionInfo * ex_info;
1071                 MonoILExceptionBlock * ex_block;
1072                 int j;
1073
1074                 stream_data_align (&assembly->code);
1075                 /* always use fat format for now */
1076                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1077                 num_exception *= 6 * sizeof (guint32);
1078                 num_exception += 4; /* include the size of the header */
1079                 sheader [1] = num_exception & 0xff;
1080                 sheader [2] = (num_exception >> 8) & 0xff;
1081                 sheader [3] = (num_exception >> 16) & 0xff;
1082                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1083                 /* fat header, so we are already aligned */
1084                 /* reverse order */
1085                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1086                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1087                         if (ex_info->handlers) {
1088                                 int finally_start = ex_info->start + ex_info->len;
1089                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1090                                         guint32 val;
1091                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1092                                         /* the flags */
1093                                         val = GUINT32_TO_LE (ex_block->type);
1094                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1095                                         /* try offset */
1096                                         val = GUINT32_TO_LE (ex_info->start);
1097                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1098                                         /* need fault, too, probably */
1099                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1100                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1101                                         else
1102                                                 val = GUINT32_TO_LE (ex_info->len);
1103                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1104                                         /* handler offset */
1105                                         val = GUINT32_TO_LE (ex_block->start);
1106                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1107                                         /* handler len */
1108                                         val = GUINT32_TO_LE (ex_block->len);
1109                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1110                                         finally_start = ex_block->start + ex_block->len;
1111                                         if (ex_block->extype) {
1112                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1113                                         } else {
1114                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1115                                                         val = ex_block->filter_offset;
1116                                                 else
1117                                                         val = 0;
1118                                         }
1119                                         val = GUINT32_TO_LE (val);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1122                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1123                                 }
1124                         } else {
1125                                 g_error ("No clauses for ex info block %d", i);
1126                         }
1127                 }
1128         }
1129         return assembly->text_rva + idx;
1130 }
1131
1132 static guint32
1133 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1134 {
1135         int i;
1136         MonoDynamicTable *table;
1137         guint32 *values;
1138         
1139         table = &assembly->tables [table_idx];
1140
1141         g_assert (col < table->columns);
1142
1143         values = table->values + table->columns;
1144         for (i = 1; i <= table->rows; ++i) {
1145                 if (values [col] == token)
1146                         return i;
1147                 values += table->columns;
1148         }
1149         return 0;
1150 }
1151
1152 /*
1153  * LOCKING: Acquires the loader lock. 
1154  */
1155 static MonoCustomAttrInfo*
1156 lookup_custom_attr (MonoImage *image, gpointer member)
1157 {
1158         MonoCustomAttrInfo* res;
1159
1160         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1161
1162         if (!res)
1163                 return NULL;
1164
1165         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1166         res->cached = 0;
1167         return res;
1168 }
1169
1170 static gboolean
1171 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1172 {
1173         /* FIXME: Need to do more checks */
1174         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1175                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1176
1177                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1178                         return FALSE;
1179         }
1180
1181         return TRUE;
1182 }
1183
1184 static MonoCustomAttrInfo*
1185 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1186 {
1187         int i, index, count, not_visible;
1188         MonoCustomAttrInfo *ainfo;
1189         MonoReflectionCustomAttr *cattr;
1190
1191         if (!cattrs)
1192                 return NULL;
1193         /* FIXME: check in assembly the Run flag is set */
1194
1195         count = mono_array_length (cattrs);
1196
1197         /* Skip nonpublic attributes since MS.NET seems to do the same */
1198         /* FIXME: This needs to be done more globally */
1199         not_visible = 0;
1200         for (i = 0; i < count; ++i) {
1201                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1202                 if (!custom_attr_visible (image, cattr))
1203                         not_visible ++;
1204         }
1205         count -= not_visible;
1206
1207         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1208
1209         ainfo->image = image;
1210         ainfo->num_attrs = count;
1211         ainfo->cached = alloc_img != NULL;
1212         index = 0;
1213         for (i = 0; i < count; ++i) {
1214                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1215                 if (custom_attr_visible (image, cattr)) {
1216                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1217                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1218                         ainfo->attrs [index].ctor = cattr->ctor->method;
1219                         ainfo->attrs [index].data = saved;
1220                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1221                         index ++;
1222                 }
1223         }
1224
1225         return ainfo;
1226 }
1227
1228 #ifndef DISABLE_REFLECTION_EMIT
1229 /*
1230  * LOCKING: Acquires the loader lock. 
1231  */
1232 static void
1233 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1234 {
1235         MonoCustomAttrInfo *ainfo, *tmp;
1236
1237         if (!cattrs || !mono_array_length (cattrs))
1238                 return;
1239
1240         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1241
1242         mono_loader_lock ();
1243         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1244         if (tmp)
1245                 mono_custom_attrs_free (tmp);
1246         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1247         mono_loader_unlock ();
1248
1249 }
1250 #endif
1251
1252 void
1253 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1254 {
1255         if (!ainfo->cached)
1256                 g_free (ainfo);
1257 }
1258
1259 /*
1260  * idx is the table index of the object
1261  * type is one of MONO_CUSTOM_ATTR_*
1262  */
1263 static void
1264 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1265 {
1266         MonoDynamicTable *table;
1267         MonoReflectionCustomAttr *cattr;
1268         guint32 *values;
1269         guint32 count, i, token;
1270         char blob_size [6];
1271         char *p = blob_size;
1272         
1273         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1274         if (!cattrs)
1275                 return;
1276         count = mono_array_length (cattrs);
1277         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1278         table->rows += count;
1279         alloc_table (table, table->rows);
1280         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1281         idx <<= MONO_CUSTOM_ATTR_BITS;
1282         idx |= type;
1283         for (i = 0; i < count; ++i) {
1284                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1285                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1286                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1287                 type = mono_metadata_token_index (token);
1288                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1289                 switch (mono_metadata_token_table (token)) {
1290                 case MONO_TABLE_METHOD:
1291                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1292                         break;
1293                 case MONO_TABLE_MEMBERREF:
1294                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1295                         break;
1296                 default:
1297                         g_warning ("got wrong token in custom attr");
1298                         continue;
1299                 }
1300                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1301                 p = blob_size;
1302                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1303                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1304                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1305                 values += MONO_CUSTOM_ATTR_SIZE;
1306                 ++table->next_idx;
1307         }
1308 }
1309
1310 static void
1311 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1312 {
1313         MonoDynamicTable *table;
1314         guint32 *values;
1315         guint32 count, i, idx;
1316         MonoReflectionPermissionSet *perm;
1317
1318         if (!permissions)
1319                 return;
1320
1321         count = mono_array_length (permissions);
1322         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1323         table->rows += count;
1324         alloc_table (table, table->rows);
1325
1326         for (i = 0; i < mono_array_length (permissions); ++i) {
1327                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1328
1329                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1330
1331                 idx = mono_metadata_token_index (parent_token);
1332                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1333                 switch (mono_metadata_token_table (parent_token)) {
1334                 case MONO_TABLE_TYPEDEF:
1335                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1336                         break;
1337                 case MONO_TABLE_METHOD:
1338                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1339                         break;
1340                 case MONO_TABLE_ASSEMBLY:
1341                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1342                         break;
1343                 default:
1344                         g_assert_not_reached ();
1345                 }
1346
1347                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1348                 values [MONO_DECL_SECURITY_PARENT] = idx;
1349                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1350
1351                 ++table->next_idx;
1352         }
1353 }
1354
1355 /*
1356  * Fill in the MethodDef and ParamDef tables for a method.
1357  * This is used for both normal methods and constructors.
1358  */
1359 static void
1360 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1361 {
1362         MonoDynamicTable *table;
1363         guint32 *values;
1364         guint i, count;
1365
1366         /* room in this table is already allocated */
1367         table = &assembly->tables [MONO_TABLE_METHOD];
1368         *mb->table_idx = table->next_idx ++;
1369         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1370         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1371         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1372         values [MONO_METHOD_FLAGS] = mb->attrs;
1373         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1374         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1375         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1376         
1377         table = &assembly->tables [MONO_TABLE_PARAM];
1378         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1379
1380         mono_image_add_decl_security (assembly, 
1381                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1382
1383         if (mb->pinfo) {
1384                 MonoDynamicTable *mtable;
1385                 guint32 *mvalues;
1386                 
1387                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1388                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1389                 
1390                 count = 0;
1391                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1392                         if (mono_array_get (mb->pinfo, gpointer, i))
1393                                 count++;
1394                 }
1395                 table->rows += count;
1396                 alloc_table (table, table->rows);
1397                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1398                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1399                         MonoReflectionParamBuilder *pb;
1400                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1401                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1402                                 values [MONO_PARAM_SEQUENCE] = i;
1403                                 if (pb->name != NULL) {
1404                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1405                                 } else {
1406                                         values [MONO_PARAM_NAME] = 0;
1407                                 }
1408                                 values += MONO_PARAM_SIZE;
1409                                 if (pb->marshal_info) {
1410                                         mtable->rows++;
1411                                         alloc_table (mtable, mtable->rows);
1412                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1413                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1414                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1415                                 }
1416                                 pb->table_idx = table->next_idx++;
1417                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1418                                         guint32 field_type = 0;
1419                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1420                                         mtable->rows ++;
1421                                         alloc_table (mtable, mtable->rows);
1422                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1423                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1424                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1425                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1426                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1427                                 }
1428                         }
1429                 }
1430         }
1431 }
1432
1433 #ifndef DISABLE_REFLECTION_EMIT
1434 static void
1435 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1436 {
1437         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1438
1439         rmb->ilgen = mb->ilgen;
1440         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1441         rmb->parameters = mb->parameters;
1442         rmb->generic_params = mb->generic_params;
1443         rmb->generic_container = mb->generic_container;
1444         rmb->opt_types = NULL;
1445         rmb->pinfo = mb->pinfo;
1446         rmb->attrs = mb->attrs;
1447         rmb->iattrs = mb->iattrs;
1448         rmb->call_conv = mb->call_conv;
1449         rmb->code = mb->code;
1450         rmb->type = mb->type;
1451         rmb->name = mb->name;
1452         rmb->table_idx = &mb->table_idx;
1453         rmb->init_locals = mb->init_locals;
1454         rmb->skip_visibility = FALSE;
1455         rmb->return_modreq = mb->return_modreq;
1456         rmb->return_modopt = mb->return_modopt;
1457         rmb->param_modreq = mb->param_modreq;
1458         rmb->param_modopt = mb->param_modopt;
1459         rmb->permissions = mb->permissions;
1460         rmb->mhandle = mb->mhandle;
1461         rmb->nrefs = 0;
1462         rmb->refs = NULL;
1463
1464         if (mb->dll) {
1465                 rmb->charset = mb->charset;
1466                 rmb->extra_flags = mb->extra_flags;
1467                 rmb->native_cc = mb->native_cc;
1468                 rmb->dllentry = mb->dllentry;
1469                 rmb->dll = mb->dll;
1470         }
1471 }
1472
1473 static void
1474 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1475 {
1476         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1477
1478         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1479
1480         rmb->ilgen = mb->ilgen;
1481         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1482         rmb->parameters = mb->parameters;
1483         rmb->generic_params = NULL;
1484         rmb->generic_container = NULL;
1485         rmb->opt_types = NULL;
1486         rmb->pinfo = mb->pinfo;
1487         rmb->attrs = mb->attrs;
1488         rmb->iattrs = mb->iattrs;
1489         rmb->call_conv = mb->call_conv;
1490         rmb->code = NULL;
1491         rmb->type = mb->type;
1492         rmb->name = mono_string_new (mono_domain_get (), name);
1493         rmb->table_idx = &mb->table_idx;
1494         rmb->init_locals = mb->init_locals;
1495         rmb->skip_visibility = FALSE;
1496         rmb->return_modreq = NULL;
1497         rmb->return_modopt = NULL;
1498         rmb->param_modreq = mb->param_modreq;
1499         rmb->param_modopt = mb->param_modopt;
1500         rmb->permissions = mb->permissions;
1501         rmb->mhandle = mb->mhandle;
1502         rmb->nrefs = 0;
1503         rmb->refs = NULL;
1504 }
1505
1506 static void
1507 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1508 {
1509         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1510
1511         rmb->ilgen = mb->ilgen;
1512         rmb->rtype = mb->rtype;
1513         rmb->parameters = mb->parameters;
1514         rmb->generic_params = NULL;
1515         rmb->generic_container = NULL;
1516         rmb->opt_types = NULL;
1517         rmb->pinfo = NULL;
1518         rmb->attrs = mb->attrs;
1519         rmb->iattrs = 0;
1520         rmb->call_conv = mb->call_conv;
1521         rmb->code = NULL;
1522         rmb->type = (MonoObject *) mb->owner;
1523         rmb->name = mb->name;
1524         rmb->table_idx = NULL;
1525         rmb->init_locals = mb->init_locals;
1526         rmb->skip_visibility = mb->skip_visibility;
1527         rmb->return_modreq = NULL;
1528         rmb->return_modopt = NULL;
1529         rmb->param_modreq = NULL;
1530         rmb->param_modopt = NULL;
1531         rmb->permissions = NULL;
1532         rmb->mhandle = mb->mhandle;
1533         rmb->nrefs = 0;
1534         rmb->refs = NULL;
1535 }       
1536 #endif
1537
1538 static void
1539 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1540 {
1541         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1542         MonoDynamicTable *table;
1543         guint32 *values;
1544         guint32 tok;
1545
1546         if (!mb->override_method)
1547                 return;
1548
1549         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1550         table->rows ++;
1551         alloc_table (table, table->rows);
1552         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1553         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1554         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1555
1556         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1557         switch (mono_metadata_token_table (tok)) {
1558         case MONO_TABLE_MEMBERREF:
1559                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1560                 break;
1561         case MONO_TABLE_METHOD:
1562                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1563                 break;
1564         default:
1565                 g_assert_not_reached ();
1566         }
1567         values [MONO_METHODIMPL_DECLARATION] = tok;
1568 }
1569
1570 #ifndef DISABLE_REFLECTION_EMIT
1571 static void
1572 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1573 {
1574         MonoDynamicTable *table;
1575         guint32 *values;
1576         ReflectionMethodBuilder rmb;
1577         int i;
1578
1579         reflection_methodbuilder_from_method_builder (&rmb, mb);
1580
1581         mono_image_basic_method (&rmb, assembly);
1582         mb->table_idx = *rmb.table_idx;
1583
1584         if (mb->dll) { /* It's a P/Invoke method */
1585                 guint32 moduleref;
1586                 /* map CharSet values to on-disk values */
1587                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1588                 int extra_flags = mb->extra_flags;
1589                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1590                 table->rows ++;
1591                 alloc_table (table, table->rows);
1592                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1593                 
1594                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1595                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1596                 if (mb->dllentry)
1597                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1598                 else
1599                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1600                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1601                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1602                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1603                         table->rows ++;
1604                         alloc_table (table, table->rows);
1605                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1606                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1607                 }
1608         }
1609
1610         if (mb->generic_params) {
1611                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1612                 table->rows += mono_array_length (mb->generic_params);
1613                 alloc_table (table, table->rows);
1614                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1615                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1616
1617                         mono_image_get_generic_param_info (
1618                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1619                 }
1620         }
1621
1622 }
1623
1624 static void
1625 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1626 {
1627         ReflectionMethodBuilder rmb;
1628
1629         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1630
1631         mono_image_basic_method (&rmb, assembly);
1632         mb->table_idx = *rmb.table_idx;
1633 }
1634 #endif
1635
1636 static char*
1637 type_get_fully_qualified_name (MonoType *type)
1638 {
1639         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1640 }
1641
1642 static char*
1643 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1644         MonoClass *klass;
1645         MonoAssembly *ta;
1646
1647         klass = mono_class_from_mono_type (type);
1648         if (!klass) 
1649                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1650         ta = klass->image->assembly;
1651         if (ta->dynamic || (ta == ass)) {
1652                 if (klass->generic_class || klass->generic_container)
1653                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1654                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1655                 else
1656                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1657         }
1658
1659         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1660 }
1661
1662 #ifndef DISABLE_REFLECTION_EMIT
1663 /*field_image is the image to which the eventual custom mods have been encoded against*/
1664 static guint32
1665 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1666 {
1667         SigBuffer buf;
1668         guint32 idx, i, token;
1669
1670         if (!assembly->save)
1671                 return 0;
1672
1673         sigbuffer_init (&buf, 32);
1674         
1675         sigbuffer_add_value (&buf, 0x06);
1676         /* encode custom attributes before the type */
1677         if (type->num_mods) {
1678                 for (i = 0; i < type->num_mods; ++i) {
1679                         if (field_image) {
1680                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1681                                 g_assert (class);
1682                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1683                         } else {
1684                                 token = type->modifiers [i].token;
1685                         }
1686
1687                         if (type->modifiers [i].required)
1688                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1689                         else
1690                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1691
1692                         sigbuffer_add_value (&buf, token);
1693                 }
1694         }
1695         encode_type (assembly, type, &buf);
1696         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1697         sigbuffer_free (&buf);
1698         return idx;
1699 }
1700 #endif
1701
1702 static guint32
1703 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1704 {
1705         SigBuffer buf;
1706         guint32 idx;
1707         guint32 typespec = 0;
1708         MonoType *type;
1709         MonoClass *class;
1710
1711         init_type_builder_generics (fb->type);
1712
1713         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1714         class = mono_class_from_mono_type (type);
1715
1716         sigbuffer_init (&buf, 32);
1717         
1718         sigbuffer_add_value (&buf, 0x06);
1719         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1720         /* encode custom attributes before the type */
1721
1722         if (class->generic_container)
1723                 typespec = create_typespec (assembly, type);
1724
1725         if (typespec) {
1726                 MonoGenericClass *gclass;
1727                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1728                 encode_generic_class (assembly, gclass, &buf);
1729         } else {
1730                 encode_type (assembly, type, &buf);
1731         }
1732         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1733         sigbuffer_free (&buf);
1734         return idx;
1735 }
1736
1737 static guint32
1738 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1739         char blob_size [64];
1740         char *b = blob_size;
1741         char *p, *box_val;
1742         char* buf;
1743         guint32 idx = 0, len = 0, dummy = 0;
1744 #ifdef ARM_FPU_FPA
1745 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1746         guint32 fpa_double [2];
1747         guint32 *fpa_p;
1748 #endif
1749 #endif
1750         
1751         p = buf = g_malloc (64);
1752         if (!val) {
1753                 *ret_type = MONO_TYPE_CLASS;
1754                 len = 4;
1755                 box_val = (char*)&dummy;
1756         } else {
1757                 box_val = ((char*)val) + sizeof (MonoObject);
1758                 *ret_type = val->vtable->klass->byval_arg.type;
1759         }
1760 handle_enum:
1761         switch (*ret_type) {
1762         case MONO_TYPE_BOOLEAN:
1763         case MONO_TYPE_U1:
1764         case MONO_TYPE_I1:
1765                 len = 1;
1766                 break;
1767         case MONO_TYPE_CHAR:
1768         case MONO_TYPE_U2:
1769         case MONO_TYPE_I2:
1770                 len = 2;
1771                 break;
1772         case MONO_TYPE_U4:
1773         case MONO_TYPE_I4:
1774         case MONO_TYPE_R4:
1775                 len = 4;
1776                 break;
1777         case MONO_TYPE_U8:
1778         case MONO_TYPE_I8:
1779                 len = 8;
1780                 break;
1781         case MONO_TYPE_R8:
1782                 len = 8;
1783 #ifdef ARM_FPU_FPA
1784 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1785                 fpa_p = (guint32*)box_val;
1786                 fpa_double [0] = fpa_p [1];
1787                 fpa_double [1] = fpa_p [0];
1788                 box_val = (char*)fpa_double;
1789 #endif
1790 #endif
1791                 break;
1792         case MONO_TYPE_VALUETYPE: {
1793                 MonoClass *klass = val->vtable->klass;
1794                 
1795                 if (klass->enumtype) {
1796                         *ret_type = mono_class_enum_basetype (klass)->type;
1797                         goto handle_enum;
1798                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1799                         len = 8;
1800                 } else 
1801                         g_error ("we can't encode valuetypes, we should have never reached this line");
1802                 break;
1803         }
1804         case MONO_TYPE_CLASS:
1805                 break;
1806         case MONO_TYPE_STRING: {
1807                 MonoString *str = (MonoString*)val;
1808                 /* there is no signature */
1809                 len = str->length * 2;
1810                 mono_metadata_encode_value (len, b, &b);
1811 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1812                 {
1813                         char *swapped = g_malloc (2 * mono_string_length (str));
1814                         const char *p = (const char*)mono_string_chars (str);
1815
1816                         swap_with_size (swapped, p, 2, mono_string_length (str));
1817                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1818                         g_free (swapped);
1819                 }
1820 #else
1821                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1822 #endif
1823
1824                 g_free (buf);
1825                 return idx;
1826         }
1827         case MONO_TYPE_GENERICINST:
1828                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1829                 goto handle_enum;
1830         default:
1831                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1832         }
1833
1834         /* there is no signature */
1835         mono_metadata_encode_value (len, b, &b);
1836 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1837         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1838         swap_with_size (blob_size, box_val, len, 1);
1839         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1840 #else
1841         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1842 #endif
1843
1844         g_free (buf);
1845         return idx;
1846 }
1847
1848 static guint32
1849 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1850         char *str;
1851         SigBuffer buf;
1852         guint32 idx, len;
1853
1854         sigbuffer_init (&buf, 32);
1855
1856         sigbuffer_add_value (&buf, minfo->type);
1857
1858         switch (minfo->type) {
1859         case MONO_NATIVE_BYVALTSTR:
1860         case MONO_NATIVE_BYVALARRAY:
1861                 sigbuffer_add_value (&buf, minfo->count);
1862                 break;
1863         case MONO_NATIVE_LPARRAY:
1864                 if (minfo->eltype || minfo->has_size) {
1865                         sigbuffer_add_value (&buf, minfo->eltype);
1866                         if (minfo->has_size) {
1867                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1868                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1869
1870                                 /* LAMESPEC: ElemMult is undocumented */
1871                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1872                         }
1873                 }
1874                 break;
1875         case MONO_NATIVE_SAFEARRAY:
1876                 if (minfo->eltype)
1877                         sigbuffer_add_value (&buf, minfo->eltype);
1878                 break;
1879         case MONO_NATIVE_CUSTOM:
1880                 if (minfo->guid) {
1881                         str = mono_string_to_utf8 (minfo->guid);
1882                         len = strlen (str);
1883                         sigbuffer_add_value (&buf, len);
1884                         sigbuffer_add_mem (&buf, str, len);
1885                         g_free (str);
1886                 } else {
1887                         sigbuffer_add_value (&buf, 0);
1888                 }
1889                 /* native type name */
1890                 sigbuffer_add_value (&buf, 0);
1891                 /* custom marshaler type name */
1892                 if (minfo->marshaltype || minfo->marshaltyperef) {
1893                         if (minfo->marshaltyperef)
1894                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1895                         else
1896                                 str = mono_string_to_utf8 (minfo->marshaltype);
1897                         len = strlen (str);
1898                         sigbuffer_add_value (&buf, len);
1899                         sigbuffer_add_mem (&buf, str, len);
1900                         g_free (str);
1901                 } else {
1902                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1903                         sigbuffer_add_value (&buf, 0);
1904                 }
1905                 if (minfo->mcookie) {
1906                         str = mono_string_to_utf8 (minfo->mcookie);
1907                         len = strlen (str);
1908                         sigbuffer_add_value (&buf, len);
1909                         sigbuffer_add_mem (&buf, str, len);
1910                         g_free (str);
1911                 } else {
1912                         sigbuffer_add_value (&buf, 0);
1913                 }
1914                 break;
1915         default:
1916                 break;
1917         }
1918         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1919         sigbuffer_free (&buf);
1920         return idx;
1921 }
1922
1923 static void
1924 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1925 {
1926         MonoDynamicTable *table;
1927         guint32 *values;
1928
1929         /* maybe this fixup should be done in the C# code */
1930         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1931                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1932         table = &assembly->tables [MONO_TABLE_FIELD];
1933         fb->table_idx = table->next_idx ++;
1934         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1935         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1936         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1937         values [MONO_FIELD_FLAGS] = fb->attrs;
1938         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1939
1940         if (fb->offset != -1) {
1941                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1942                 table->rows ++;
1943                 alloc_table (table, table->rows);
1944                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1945                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1946                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1947         }
1948         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1949                 guint32 field_type = 0;
1950                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1951                 table->rows ++;
1952                 alloc_table (table, table->rows);
1953                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1954                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1955                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1956                 values [MONO_CONSTANT_TYPE] = field_type;
1957                 values [MONO_CONSTANT_PADDING] = 0;
1958         }
1959         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1960                 guint32 rva_idx;
1961                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1962                 table->rows ++;
1963                 alloc_table (table, table->rows);
1964                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1965                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1966                 /*
1967                  * We store it in the code section because it's simpler for now.
1968                  */
1969                 if (fb->rva_data) {
1970                         if (mono_array_length (fb->rva_data) >= 10)
1971                                 stream_data_align (&assembly->code);
1972                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1973                 } else
1974                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1975                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1976         }
1977         if (fb->marshal_info) {
1978                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1979                 table->rows ++;
1980                 alloc_table (table, table->rows);
1981                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1982                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1983                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1984         }
1985 }
1986
1987 static guint32
1988 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1989 {
1990         SigBuffer buf;
1991         guint32 nparams = 0;
1992         MonoReflectionMethodBuilder *mb = fb->get_method;
1993         MonoReflectionMethodBuilder *smb = fb->set_method;
1994         guint32 idx, i;
1995
1996         if (mb && mb->parameters)
1997                 nparams = mono_array_length (mb->parameters);
1998         if (!mb && smb && smb->parameters)
1999                 nparams = mono_array_length (smb->parameters) - 1;
2000         sigbuffer_init (&buf, 32);
2001         if (fb->call_conv & 0x20)
2002                 sigbuffer_add_byte (&buf, 0x28);
2003         else
2004                 sigbuffer_add_byte (&buf, 0x08);
2005         sigbuffer_add_value (&buf, nparams);
2006         if (mb) {
2007                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2008                 for (i = 0; i < nparams; ++i) {
2009                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2010                         encode_reflection_type (assembly, pt, &buf);
2011                 }
2012         } else if (smb && smb->parameters) {
2013                 /* the property type is the last param */
2014                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2015                 for (i = 0; i < nparams; ++i) {
2016                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2017                         encode_reflection_type (assembly, pt, &buf);
2018                 }
2019         } else {
2020                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2021         }
2022
2023         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2024         sigbuffer_free (&buf);
2025         return idx;
2026 }
2027
2028 static void
2029 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2030 {
2031         MonoDynamicTable *table;
2032         guint32 *values;
2033         guint num_methods = 0;
2034         guint32 semaidx;
2035
2036         /* 
2037          * we need to set things in the following tables:
2038          * PROPERTYMAP (info already filled in _get_type_info ())
2039          * PROPERTY    (rows already preallocated in _get_type_info ())
2040          * METHOD      (method info already done with the generic method code)
2041          * METHODSEMANTICS
2042          * CONSTANT
2043          */
2044         table = &assembly->tables [MONO_TABLE_PROPERTY];
2045         pb->table_idx = table->next_idx ++;
2046         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2047         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2048         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2049         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2050
2051         /* FIXME: we still don't handle 'other' methods */
2052         if (pb->get_method) num_methods ++;
2053         if (pb->set_method) num_methods ++;
2054
2055         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2056         table->rows += num_methods;
2057         alloc_table (table, table->rows);
2058
2059         if (pb->get_method) {
2060                 semaidx = table->next_idx ++;
2061                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2062                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2063                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2064                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2065         }
2066         if (pb->set_method) {
2067                 semaidx = table->next_idx ++;
2068                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2069                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2070                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2071                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2072         }
2073         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2074                 guint32 field_type = 0;
2075                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2076                 table->rows ++;
2077                 alloc_table (table, table->rows);
2078                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2079                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2080                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2081                 values [MONO_CONSTANT_TYPE] = field_type;
2082                 values [MONO_CONSTANT_PADDING] = 0;
2083         }
2084 }
2085
2086 static void
2087 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2088 {
2089         MonoDynamicTable *table;
2090         guint32 *values;
2091         guint num_methods = 0;
2092         guint32 semaidx;
2093
2094         /* 
2095          * we need to set things in the following tables:
2096          * EVENTMAP (info already filled in _get_type_info ())
2097          * EVENT    (rows already preallocated in _get_type_info ())
2098          * METHOD      (method info already done with the generic method code)
2099          * METHODSEMANTICS
2100          */
2101         table = &assembly->tables [MONO_TABLE_EVENT];
2102         eb->table_idx = table->next_idx ++;
2103         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2104         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2105         values [MONO_EVENT_FLAGS] = eb->attrs;
2106         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2107
2108         /*
2109          * FIXME: we still don't handle 'other' methods 
2110          */
2111         if (eb->add_method) num_methods ++;
2112         if (eb->remove_method) num_methods ++;
2113         if (eb->raise_method) num_methods ++;
2114
2115         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2116         table->rows += num_methods;
2117         alloc_table (table, table->rows);
2118
2119         if (eb->add_method) {
2120                 semaidx = table->next_idx ++;
2121                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2122                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2123                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2124                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2125         }
2126         if (eb->remove_method) {
2127                 semaidx = table->next_idx ++;
2128                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2129                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2130                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2131                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2132         }
2133         if (eb->raise_method) {
2134                 semaidx = table->next_idx ++;
2135                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2136                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2137                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2138                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2139         }
2140 }
2141
2142 static void
2143 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2144 {
2145         MonoDynamicTable *table;
2146         guint32 num_constraints, i;
2147         guint32 *values;
2148         guint32 table_idx;
2149
2150         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2151         num_constraints = gparam->iface_constraints ?
2152                 mono_array_length (gparam->iface_constraints) : 0;
2153         table->rows += num_constraints;
2154         if (gparam->base_type)
2155                 table->rows++;
2156         alloc_table (table, table->rows);
2157
2158         if (gparam->base_type) {
2159                 table_idx = table->next_idx ++;
2160                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2161
2162                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2163                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2164                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2165         }
2166
2167         for (i = 0; i < num_constraints; i++) {
2168                 MonoReflectionType *constraint = mono_array_get (
2169                         gparam->iface_constraints, gpointer, i);
2170
2171                 table_idx = table->next_idx ++;
2172                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2173
2174                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2175                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2176                         assembly, mono_reflection_type_get_handle (constraint));
2177         }
2178 }
2179
2180 static void
2181 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2182 {
2183         GenericParamTableEntry *entry;
2184
2185         /*
2186          * The GenericParam table must be sorted according to the `owner' field.
2187          * We need to do this sorting prior to writing the GenericParamConstraint
2188          * table, since we have to use the final GenericParam table indices there
2189          * and they must also be sorted.
2190          */
2191
2192         entry = g_new0 (GenericParamTableEntry, 1);
2193         entry->owner = owner;
2194         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2195         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2196         entry->gparam = gparam;
2197         
2198         g_ptr_array_add (assembly->gen_params, entry);
2199 }
2200
2201 static void
2202 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2203 {
2204         MonoDynamicTable *table;
2205         MonoGenericParam *param;
2206         guint32 *values;
2207         guint32 table_idx;
2208
2209         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2210         table_idx = table->next_idx ++;
2211         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2212
2213         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2214
2215         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2216         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2217         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2218         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2219
2220         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2221
2222         encode_constraints (entry->gparam, table_idx, assembly);
2223 }
2224
2225 static guint32
2226 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2227 {
2228         MonoDynamicTable *table;
2229         guint32 token;
2230         guint32 *values;
2231         guint32 cols [MONO_ASSEMBLY_SIZE];
2232         const char *pubkey;
2233         guint32 publen;
2234
2235         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2236                 return token;
2237
2238         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2239                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2240                 token = table->next_idx ++;
2241                 table->rows ++;
2242                 alloc_table (table, table->rows);
2243                 values = table->values + token * MONO_MODULEREF_SIZE;
2244                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2245
2246                 token <<= MONO_RESOLTION_SCOPE_BITS;
2247                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2248                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2249
2250                 return token;
2251         }
2252         
2253         if (image->assembly->dynamic)
2254                 /* FIXME: */
2255                 memset (cols, 0, sizeof (cols));
2256         else {
2257                 /* image->assembly->image is the manifest module */
2258                 image = image->assembly->image;
2259                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2260         }
2261
2262         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2263         token = table->next_idx ++;
2264         table->rows ++;
2265         alloc_table (table, table->rows);
2266         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2267         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2268         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2269         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2270         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2271         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2272         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2273         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2274         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2275
2276         if (strcmp ("", image->assembly->aname.culture)) {
2277                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2278                                 image->assembly->aname.culture);
2279         }
2280
2281         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2282                 guchar pubtoken [9];
2283                 pubtoken [0] = 8;
2284                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2285                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2286         } else {
2287                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2288         }
2289         token <<= MONO_RESOLTION_SCOPE_BITS;
2290         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2291         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2292         return token;
2293 }
2294
2295 static guint32
2296 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2297 {
2298         MonoDynamicTable *table;
2299         guint32 *values;
2300         guint32 token;
2301         SigBuffer buf;
2302
2303         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2304                 return token;
2305
2306         sigbuffer_init (&buf, 32);
2307         switch (type->type) {
2308         case MONO_TYPE_FNPTR:
2309         case MONO_TYPE_PTR:
2310         case MONO_TYPE_SZARRAY:
2311         case MONO_TYPE_ARRAY:
2312         case MONO_TYPE_VAR:
2313         case MONO_TYPE_MVAR:
2314         case MONO_TYPE_GENERICINST:
2315                 encode_type (assembly, type, &buf);
2316                 break;
2317         case MONO_TYPE_CLASS:
2318         case MONO_TYPE_VALUETYPE: {
2319                 MonoClass *k = mono_class_from_mono_type (type);
2320                 if (!k || !k->generic_container) {
2321                         sigbuffer_free (&buf);
2322                         return 0;
2323                 }
2324                 encode_type (assembly, type, &buf);
2325                 break;
2326         }
2327         default:
2328                 sigbuffer_free (&buf);
2329                 return 0;
2330         }
2331
2332         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2333         if (assembly->save) {
2334                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2335                 alloc_table (table, table->rows + 1);
2336                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2337                 values [MONO_TYPESPEC_SIGNATURE] = token;
2338         }
2339         sigbuffer_free (&buf);
2340
2341         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2342         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2343         table->next_idx ++;
2344         return token;
2345 }
2346
2347 static guint32
2348 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2349 {
2350         MonoDynamicTable *table;
2351         guint32 *values;
2352         guint32 token, scope, enclosing;
2353         MonoClass *klass;
2354
2355         /* if the type requires a typespec, we must try that first*/
2356         if (try_typespec && (token = create_typespec (assembly, type)))
2357                 return token;
2358         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2359         if (token)
2360                 return token;
2361         klass = mono_class_from_mono_type (type);
2362         if (!klass)
2363                 klass = mono_class_from_mono_type (type);
2364
2365         /*
2366          * If it's in the same module and not a generic type parameter:
2367          */
2368         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2369                         (type->type != MONO_TYPE_MVAR)) {
2370                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2371                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2372                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2373                 return token;
2374         }
2375
2376         if (klass->nested_in) {
2377                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2378                 /* get the typeref idx of the enclosing type */
2379                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2380                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2381         } else {
2382                 scope = resolution_scope_from_image (assembly, klass->image);
2383         }
2384         table = &assembly->tables [MONO_TABLE_TYPEREF];
2385         if (assembly->save) {
2386                 alloc_table (table, table->rows + 1);
2387                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2388                 values [MONO_TYPEREF_SCOPE] = scope;
2389                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2390                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2391         }
2392         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2393         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2394         table->next_idx ++;
2395         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2396         return token;
2397 }
2398
2399 /*
2400  * Despite the name, we handle also TypeSpec (with the above helper).
2401  */
2402 static guint32
2403 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2404 {
2405         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2406 }
2407
2408 #ifndef DISABLE_REFLECTION_EMIT
2409 static guint32
2410 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2411 {
2412         MonoDynamicTable *table;
2413         guint32 *values;
2414         guint32 token, pclass;
2415
2416         switch (parent & MONO_TYPEDEFORREF_MASK) {
2417         case MONO_TYPEDEFORREF_TYPEREF:
2418                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2419                 break;
2420         case MONO_TYPEDEFORREF_TYPESPEC:
2421                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2422                 break;
2423         case MONO_TYPEDEFORREF_TYPEDEF:
2424                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2425                 break;
2426         default:
2427                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2428                 return 0;
2429         }
2430         /* extract the index */
2431         parent >>= MONO_TYPEDEFORREF_BITS;
2432
2433         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2434
2435         if (assembly->save) {
2436                 alloc_table (table, table->rows + 1);
2437                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2438                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2439                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2440                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2441         }
2442
2443         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2444         table->next_idx ++;
2445
2446         return token;
2447 }
2448
2449 /*
2450  * Insert a memberef row into the metadata: the token that point to the memberref
2451  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2452  * mono_image_get_fieldref_token()).
2453  * The sig param is an index to an already built signature.
2454  */
2455 static guint32
2456 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2457 {
2458         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2459         return mono_image_add_memberef_row (assembly, parent, name, sig);
2460 }
2461
2462
2463 static guint32
2464 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2465 {
2466         guint32 token;
2467         MonoMethodSignature *sig;
2468         
2469         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2470
2471         if (create_typespec) {
2472                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2473                 if (token)
2474                         return token;
2475         } 
2476
2477         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2478         if (token && !create_typespec)
2479                 return token;
2480
2481         g_assert (!method->is_inflated);
2482         if (!token) {
2483                 /*
2484                  * A methodref signature can't contain an unmanaged calling convention.
2485                  */
2486                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2487                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2488                         sig->call_convention = MONO_CALL_DEFAULT;
2489                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2490                         method->name,  method_encode_signature (assembly, sig));
2491                 g_free (sig);
2492                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2493         }
2494
2495         if (create_typespec) {
2496                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2497                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2498                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2499
2500                 if (assembly->save) {
2501                         guint32 *values;
2502
2503                         alloc_table (table, table->rows + 1);
2504                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2505                         values [MONO_METHODSPEC_METHOD] = token;
2506                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2507                 }
2508
2509                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2510                 table->next_idx ++;
2511                 /*methodspec and memberef tokens are diferent, */
2512                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2513                 return token;
2514         }
2515         return token;
2516 }
2517
2518 static guint32
2519 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2520 {
2521         guint32 token, parent, sig;
2522         ReflectionMethodBuilder rmb;
2523         char *name;
2524         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2525         
2526         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2527         if (token)
2528                 return token;
2529
2530         name = mono_string_to_utf8 (method->name);
2531         reflection_methodbuilder_from_method_builder (&rmb, method);
2532
2533         /*
2534          * A methodref signature can't contain an unmanaged calling convention.
2535          * Since some flags are encoded as part of call_conv, we need to check against it.
2536         */
2537         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2538                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2539
2540         sig = method_builder_encode_signature (assembly, &rmb);
2541
2542         if (tb->generic_params)
2543                 parent = create_generic_typespec (assembly, tb);
2544         else
2545                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2546
2547         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2548
2549         g_free (name);
2550         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2551         return token;
2552 }
2553
2554 static guint32
2555 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2556                                      const gchar *name, guint32 sig)
2557 {
2558         MonoDynamicTable *table;
2559         guint32 token;
2560         guint32 *values;
2561         
2562         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2563
2564         if (assembly->save) {
2565                 alloc_table (table, table->rows + 1);
2566                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2567                 values [MONO_MEMBERREF_CLASS] = original;
2568                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2569                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2570         }
2571
2572         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2573         table->next_idx ++;
2574
2575         return token;
2576 }
2577
2578 static guint32
2579 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2580 {
2581         SigBuffer buf;
2582         int i;
2583         guint32 nparams = mono_array_length (mb->generic_params);
2584         guint32 idx;
2585
2586         if (!assembly->save)
2587                 return 0;
2588
2589         sigbuffer_init (&buf, 32);
2590
2591         sigbuffer_add_value (&buf, 0xa);
2592         sigbuffer_add_value (&buf, nparams);
2593
2594         for (i = 0; i < nparams; i++) {
2595                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2596                 sigbuffer_add_value (&buf, i);
2597         }
2598
2599         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2600         sigbuffer_free (&buf);
2601         return idx;
2602 }
2603
2604 static guint32
2605 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2606 {
2607         MonoDynamicTable *table;
2608         guint32 *values;
2609         guint32 token, mtoken = 0;
2610
2611         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2612         if (token)
2613                 return token;
2614
2615         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2616
2617         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2618         switch (mono_metadata_token_table (mtoken)) {
2619         case MONO_TABLE_MEMBERREF:
2620                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2621                 break;
2622         case MONO_TABLE_METHOD:
2623                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2624                 break;
2625         default:
2626                 g_assert_not_reached ();
2627         }
2628
2629         if (assembly->save) {
2630                 alloc_table (table, table->rows + 1);
2631                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2632                 values [MONO_METHODSPEC_METHOD] = mtoken;
2633                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2634         }
2635
2636         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2637         table->next_idx ++;
2638
2639         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2640         return token;
2641 }
2642
2643 static guint32
2644 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2645 {
2646         guint32 token;
2647
2648         if (mb->generic_params && create_methodspec) 
2649                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2650
2651         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2652         if (token)
2653                 return token;
2654
2655         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2656         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2657         return token;
2658 }
2659
2660 static guint32
2661 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2662 {
2663         guint32 token, parent, sig;
2664         ReflectionMethodBuilder rmb;
2665         char *name;
2666         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2667         
2668         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2669         if (token)
2670                 return token;
2671
2672         g_assert (tb->generic_params);
2673
2674         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2675
2676         parent = create_generic_typespec (assembly, tb);
2677         name = mono_string_to_utf8 (rmb.name);
2678         sig = method_builder_encode_signature (assembly, &rmb);
2679
2680         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2681
2682         g_free (name);
2683         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2684         return token;
2685 }
2686 #endif
2687
2688 static gboolean
2689 is_field_on_inst (MonoClassField *field)
2690 {
2691         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2692 }
2693
2694 /*
2695  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2696  */
2697 static MonoType*
2698 get_field_on_inst_generic_type (MonoClassField *field)
2699 {
2700         MonoClass *class, *gtd;
2701         MonoDynamicGenericClass *dgclass;
2702         int field_index;
2703
2704         g_assert (is_field_on_inst (field));
2705
2706         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2707
2708         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2709                 field_index = field - dgclass->fields;
2710                 return dgclass->field_generic_types [field_index];              
2711         }
2712
2713         class = field->parent;
2714         gtd = class->generic_class->container_class;
2715
2716         if (field >= class->fields && field - class->fields < class->field.count) {
2717                 field_index = field - class->fields;
2718                 return gtd->fields [field_index].type;
2719         }
2720
2721         g_assert_not_reached ();
2722         return 0;
2723 }
2724
2725 #ifndef DISABLE_REFLECTION_EMIT
2726 static guint32
2727 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2728 {
2729         MonoType *type;
2730         guint32 token;
2731
2732         g_assert (field);
2733         g_assert (field->parent);
2734
2735         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2736         if (token)
2737                 return token;
2738
2739         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2740                 int index = field - field->parent->fields;
2741                 type = field->parent->generic_class->container_class->fields [index].type;
2742         } else {
2743                 if (is_field_on_inst (field))
2744                         type = get_field_on_inst_generic_type (field);
2745                 else
2746                         type = field->type;
2747         }
2748         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2749                                                                                         mono_field_get_name (field),
2750                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2751         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2752         return token;
2753 }
2754
2755 static guint32
2756 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2757 {
2758         guint32 token;
2759         MonoClass *klass;
2760         MonoGenericClass *gclass;
2761         MonoDynamicGenericClass *dgclass;
2762         MonoType *type;
2763         char *name;
2764
2765         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2766         if (token)
2767                 return token;
2768         if (is_sre_field_builder (mono_object_class (f->fb))) {
2769                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2770                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2771                 klass = mono_class_from_mono_type (type);
2772                 gclass = type->data.generic_class;
2773                 g_assert (gclass->is_dynamic);
2774                 dgclass = (MonoDynamicGenericClass *) gclass;
2775
2776                 name = mono_string_to_utf8 (fb->name);
2777                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2778                                                                                                 field_encode_signature (assembly, fb));
2779                 g_free (name);          
2780         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2781                 guint32 sig;
2782                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2783
2784                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785                 klass = mono_class_from_mono_type (type);
2786
2787                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2788                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2789         } else {
2790                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2791                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2792         }
2793
2794         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2795         return token;
2796 }
2797
2798 static guint32
2799 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2800 {
2801         guint32 sig, token;
2802         MonoClass *klass;
2803         MonoGenericClass *gclass;
2804         MonoType *type;
2805
2806         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2807
2808         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2809         if (token)
2810                 return token;
2811
2812         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2813                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2814                 MonoDynamicGenericClass *dgclass;
2815                 ReflectionMethodBuilder rmb;
2816                 char *name;
2817
2818                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2819                 klass = mono_class_from_mono_type (type);
2820
2821                 gclass = type->data.generic_class;
2822                 g_assert (gclass->is_dynamic);
2823                 dgclass = (MonoDynamicGenericClass *) gclass;
2824
2825                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2826
2827                 name = mono_string_to_utf8 (rmb.name);
2828
2829                 sig = method_builder_encode_signature (assembly, &rmb);
2830
2831                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2832                 g_free (name);
2833         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2834                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2835
2836                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2837                 klass = mono_class_from_mono_type (type);
2838
2839                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2840                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2841         } else {
2842                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2843                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2844         }
2845
2846
2847         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2848         return token;
2849 }
2850
2851 static MonoMethod*
2852 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2853 {
2854         MonoClass *klass;
2855         MonoGenericContext tmp_context;
2856         MonoType **type_argv;
2857         MonoGenericInst *ginst;
2858         MonoMethod *method, *inflated;
2859         int count, i;
2860
2861         init_type_builder_generics ((MonoObject*)m->inst);
2862
2863         method = inflate_method (m->inst, (MonoObject*)m->mb);
2864
2865         klass = method->klass;
2866
2867         if (m->method_args == NULL)
2868                 return method;
2869
2870         if (method->is_inflated)
2871                 method = ((MonoMethodInflated *) method)->declaring;
2872
2873         count = mono_array_length (m->method_args);
2874
2875         type_argv = g_new0 (MonoType *, count);
2876         for (i = 0; i < count; i++) {
2877                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2878                 type_argv [i] = mono_reflection_type_get_handle (garg);
2879         }
2880         ginst = mono_metadata_get_generic_inst (count, type_argv);
2881         g_free (type_argv);
2882
2883         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2884         tmp_context.method_inst = ginst;
2885
2886         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2887         return inflated;
2888 }
2889
2890 static guint32
2891 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2892 {
2893         guint32 sig, token = 0;
2894         MonoType *type;
2895         MonoClass *klass;
2896
2897         if (m->method_args) {
2898                 MonoMethod *inflated;
2899
2900                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2901                 if (create_methodspec)
2902                         token = mono_image_get_methodspec_token (assembly, inflated);
2903                 else
2904                         token = mono_image_get_inflated_method_token (assembly, inflated);
2905                 return token;
2906         }
2907
2908         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2909         if (token)
2910                 return token;
2911
2912         if (is_sre_method_builder (mono_object_class (m->mb))) {
2913                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2914                 MonoGenericClass *gclass;
2915                 ReflectionMethodBuilder rmb;
2916                 char *name;
2917
2918                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2919                 klass = mono_class_from_mono_type (type);
2920                 gclass = type->data.generic_class;
2921                 g_assert (gclass->is_dynamic);
2922
2923                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2924
2925                 name = mono_string_to_utf8 (rmb.name);
2926
2927                 sig = method_builder_encode_signature (assembly, &rmb);
2928
2929                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2930                 g_free (name);          
2931         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2932                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2933
2934                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2935                 klass = mono_class_from_mono_type (type);
2936
2937                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2938                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2939         } else {
2940                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2941                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2942         }
2943
2944         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2945         return token;
2946 }
2947
2948 static guint32
2949 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2950 {
2951         SigBuffer buf;
2952         int i;
2953         guint32 nparams = context->method_inst->type_argc;
2954         guint32 idx;
2955
2956         if (!assembly->save)
2957                 return 0;
2958
2959         sigbuffer_init (&buf, 32);
2960         /*
2961          * FIXME: vararg, explicit_this, differenc call_conv values...
2962          */
2963         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2964         sigbuffer_add_value (&buf, nparams);
2965
2966         for (i = 0; i < nparams; i++)
2967                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2968
2969         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2970         sigbuffer_free (&buf);
2971         return idx;
2972 }
2973
2974 static guint32
2975 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2976 {
2977         MonoDynamicTable *table;
2978         guint32 *values;
2979         guint32 token, mtoken = 0, sig;
2980         MonoMethodInflated *imethod;
2981         MonoMethod *declaring;
2982
2983         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2984
2985         g_assert (method->is_inflated);
2986         imethod = (MonoMethodInflated *) method;
2987         declaring = imethod->declaring;
2988
2989         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2990         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2991
2992         if (!mono_method_signature (declaring)->generic_param_count)
2993                 return mtoken;
2994
2995         switch (mono_metadata_token_table (mtoken)) {
2996         case MONO_TABLE_MEMBERREF:
2997                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2998                 break;
2999         case MONO_TABLE_METHOD:
3000                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3001                 break;
3002         default:
3003                 g_assert_not_reached ();
3004         }
3005
3006         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3007
3008         if (assembly->save) {
3009                 alloc_table (table, table->rows + 1);
3010                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3011                 values [MONO_METHODSPEC_METHOD] = mtoken;
3012                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3013         }
3014
3015         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3016         table->next_idx ++;
3017
3018         return token;
3019 }
3020
3021 static guint32
3022 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3023 {
3024         MonoMethodInflated *imethod;
3025         guint32 token;
3026         
3027         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3028         if (token)
3029                 return token;
3030
3031         g_assert (method->is_inflated);
3032         imethod = (MonoMethodInflated *) method;
3033
3034         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3035                 token = method_encode_methodspec (assembly, method);
3036         } else {
3037                 guint32 sig = method_encode_signature (
3038                         assembly, mono_method_signature (imethod->declaring));
3039                 token = mono_image_get_memberref_token (
3040                         assembly, &method->klass->byval_arg, method->name, sig);
3041         }
3042
3043         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3044         return token;
3045 }
3046
3047 static guint32
3048 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3049 {
3050         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3051         guint32 sig, token;
3052
3053         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3054         token = mono_image_get_memberref_token (
3055                 assembly, &m->klass->byval_arg, m->name, sig);
3056
3057         return token;
3058 }
3059
3060 static guint32
3061 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3062 {
3063         MonoDynamicTable *table;
3064         MonoClass *klass;
3065         MonoType *type;
3066         guint32 *values;
3067         guint32 token;
3068         SigBuffer buf;
3069         int count, i;
3070
3071         /*
3072          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3073          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3074          * Because of this, we must not insert it into the `typeref' hash table.
3075          */
3076         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3077         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3078         if (token)
3079                 return token;
3080
3081         sigbuffer_init (&buf, 32);
3082
3083         g_assert (tb->generic_params);
3084         klass = mono_class_from_mono_type (type);
3085
3086         if (tb->generic_container)
3087                 mono_reflection_create_generic_class (tb);
3088
3089         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3090         g_assert (klass->generic_container);
3091         sigbuffer_add_value (&buf, klass->byval_arg.type);
3092         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3093
3094         count = mono_array_length (tb->generic_params);
3095         sigbuffer_add_value (&buf, count);
3096         for (i = 0; i < count; i++) {
3097                 MonoReflectionGenericParam *gparam;
3098
3099                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3100
3101                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3102         }
3103
3104         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3105
3106         if (assembly->save) {
3107                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3108                 alloc_table (table, table->rows + 1);
3109                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3110                 values [MONO_TYPESPEC_SIGNATURE] = token;
3111         }
3112         sigbuffer_free (&buf);
3113
3114         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3115         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3116         table->next_idx ++;
3117         return token;
3118 }
3119
3120 /*
3121  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3122  */
3123 static MonoType*
3124 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3125 {
3126         int i, count, len, pos;
3127         MonoType *t;
3128
3129         count = 0;
3130         if (modreq)
3131                 count += mono_array_length (modreq);
3132         if (modopt)
3133                 count += mono_array_length (modopt);
3134
3135         if (count == 0)
3136                 return mono_metadata_type_dup (NULL, type);
3137
3138         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3139         t = g_malloc (len);
3140         memcpy (t, type, MONO_SIZEOF_TYPE);
3141
3142         t->num_mods = count;
3143         pos = 0;
3144         if (modreq) {
3145                 for (i = 0; i < mono_array_length (modreq); ++i) {
3146                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3147                         t->modifiers [pos].required = 1;
3148                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3149                         pos ++;
3150                 }
3151         }
3152         if (modopt) {
3153                 for (i = 0; i < mono_array_length (modopt); ++i) {
3154                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3155                         t->modifiers [pos].required = 0;
3156                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3157                         pos ++;
3158                 }
3159         }
3160
3161         return t;
3162 }
3163
3164 static void
3165 init_type_builder_generics (MonoObject *type)
3166 {
3167         MonoReflectionTypeBuilder *tb;
3168
3169         if (!is_sre_type_builder(mono_object_class (type)))
3170                 return;
3171         tb = (MonoReflectionTypeBuilder *)type;
3172
3173         if (tb && tb->generic_container)
3174                 mono_reflection_create_generic_class (tb);
3175 }
3176
3177 static guint32
3178 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3179 {
3180         MonoDynamicTable *table;
3181         MonoClass *klass;
3182         MonoType *custom = NULL, *type;
3183         guint32 *values;
3184         guint32 token, pclass, parent, sig;
3185         gchar *name;
3186
3187         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3188         if (token)
3189                 return token;
3190
3191         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3192         name = mono_string_to_utf8 (fb->name);
3193
3194         /*FIXME this is one more layer of ugliness due how types are created.*/
3195         init_type_builder_generics (fb->type);
3196
3197         /* fb->type does not include the custom modifiers */
3198         /* FIXME: We should do this in one place when a fieldbuilder is created */
3199         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3200         if (fb->modreq || fb->modopt)
3201                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3202
3203         sig = fieldref_encode_signature (assembly, NULL, type);
3204         g_free (custom);
3205
3206         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3207         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3208         
3209         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3210         parent >>= MONO_TYPEDEFORREF_BITS;
3211
3212         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3213
3214         if (assembly->save) {
3215                 alloc_table (table, table->rows + 1);
3216                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3217                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3218                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3219                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3220         }
3221
3222         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3223         table->next_idx ++;
3224         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3225         g_free (name);
3226         return token;
3227 }
3228
3229 static guint32
3230 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3231 {
3232         SigBuffer buf;
3233         guint32 nargs;
3234         guint32 size;
3235         guint32 i, idx;
3236
3237         if (!assembly->save)
3238                 return 0;
3239
3240         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3241         g_assert (helper->type == 2);
3242
3243         if (helper->arguments)
3244                 nargs = mono_array_length (helper->arguments);
3245         else
3246                 nargs = 0;
3247
3248         size = 10 + (nargs * 10);
3249         
3250         sigbuffer_init (&buf, 32);
3251
3252         /* Encode calling convention */
3253         /* Change Any to Standard */
3254         if ((helper->call_conv & 0x03) == 0x03)
3255                 helper->call_conv = 0x01;
3256         /* explicit_this implies has_this */
3257         if (helper->call_conv & 0x40)
3258                 helper->call_conv &= 0x20;
3259
3260         if (helper->call_conv == 0) { /* Unmanaged */
3261                 idx = helper->unmanaged_call_conv - 1;
3262         } else {
3263                 /* Managed */
3264                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3265                 if (helper->call_conv & 0x02) /* varargs */
3266                         idx += 0x05;
3267         }
3268
3269         sigbuffer_add_byte (&buf, idx);
3270         sigbuffer_add_value (&buf, nargs);
3271         encode_reflection_type (assembly, helper->return_type, &buf);
3272         for (i = 0; i < nargs; ++i) {
3273                 MonoArray *modreqs = NULL;
3274                 MonoArray *modopts = NULL;
3275                 MonoReflectionType *pt;
3276
3277                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3278                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3279                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3280                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3281
3282                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3283                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3284                 encode_reflection_type (assembly, pt, &buf);
3285         }
3286         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3287         sigbuffer_free (&buf);
3288
3289         return idx;
3290 }
3291
3292 static guint32 
3293 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3294 {
3295         guint32 idx;
3296         MonoDynamicTable *table;
3297         guint32 *values;
3298
3299         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3300         idx = table->next_idx ++;
3301         table->rows ++;
3302         alloc_table (table, table->rows);
3303         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3304
3305         values [MONO_STAND_ALONE_SIGNATURE] =
3306                 mono_reflection_encode_sighelper (assembly, helper);
3307
3308         return idx;
3309 }
3310
3311 static int
3312 reflection_cc_to_file (int call_conv) {
3313         switch (call_conv & 0x3) {
3314         case 0:
3315         case 1: return MONO_CALL_DEFAULT;
3316         case 2: return MONO_CALL_VARARG;
3317         default:
3318                 g_assert_not_reached ();
3319         }
3320         return 0;
3321 }
3322 #endif /* !DISABLE_REFLECTION_EMIT */
3323
3324 typedef struct {
3325         MonoType *parent;
3326         MonoMethodSignature *sig;
3327         char *name;
3328         guint32 token;
3329 } ArrayMethod;
3330
3331 #ifndef DISABLE_REFLECTION_EMIT
3332 static guint32
3333 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3334 {
3335         guint32 nparams, i;
3336         GList *tmp;
3337         char *name;
3338         MonoMethodSignature *sig;
3339         ArrayMethod *am;
3340         MonoType *mtype;
3341
3342         name = mono_string_to_utf8 (m->name);
3343         nparams = mono_array_length (m->parameters);
3344         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3345         sig->hasthis = 1;
3346         sig->sentinelpos = -1;
3347         sig->call_convention = reflection_cc_to_file (m->call_conv);
3348         sig->param_count = nparams;
3349         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3350         mtype = mono_reflection_type_get_handle (m->parent);
3351         for (i = 0; i < nparams; ++i)
3352                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3353
3354         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3355                 am = tmp->data;
3356                 if (strcmp (name, am->name) == 0 && 
3357                                 mono_metadata_type_equal (am->parent, mtype) &&
3358                                 mono_metadata_signature_equal (am->sig, sig)) {
3359                         g_free (name);
3360                         g_free (sig);
3361                         m->table_idx = am->token & 0xffffff;
3362                         return am->token;
3363                 }
3364         }
3365         am = g_new0 (ArrayMethod, 1);
3366         am->name = name;
3367         am->sig = sig;
3368         am->parent = mtype;
3369         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3370                 method_encode_signature (assembly, sig));
3371         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3372         m->table_idx = am->token & 0xffffff;
3373         return am->token;
3374 }
3375
3376 /*
3377  * Insert into the metadata tables all the info about the TypeBuilder tb.
3378  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3379  */
3380 static void
3381 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3382 {
3383         MonoDynamicTable *table;
3384         guint *values;
3385         int i, is_object = 0, is_system = 0;
3386         char *n;
3387
3388         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3389         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3390         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3391         n = mono_string_to_utf8 (tb->name);
3392         if (strcmp (n, "Object") == 0)
3393                 is_object++;
3394         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3395         g_free (n);
3396         n = mono_string_to_utf8 (tb->nspace);
3397         if (strcmp (n, "System") == 0)
3398                 is_system++;
3399         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3400         g_free (n);
3401         if (tb->parent && !(is_system && is_object) && 
3402                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3403                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3404         } else {
3405                 values [MONO_TYPEDEF_EXTENDS] = 0;
3406         }
3407         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3408         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3409
3410         /*
3411          * if we have explicitlayout or sequentiallayouts, output data in the
3412          * ClassLayout table.
3413          */
3414         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3415                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3416                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3417                 table->rows++;
3418                 alloc_table (table, table->rows);
3419                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3420                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3421                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3422                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3423         }
3424
3425         /* handle interfaces */
3426         if (tb->interfaces) {
3427                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3428                 i = table->rows;
3429                 table->rows += mono_array_length (tb->interfaces);
3430                 alloc_table (table, table->rows);
3431                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3432                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3433                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3434                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3435                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3436                         values += MONO_INTERFACEIMPL_SIZE;
3437                 }
3438         }
3439
3440         /* handle fields */
3441         if (tb->fields) {
3442                 table = &assembly->tables [MONO_TABLE_FIELD];
3443                 table->rows += tb->num_fields;
3444                 alloc_table (table, table->rows);
3445                 for (i = 0; i < tb->num_fields; ++i)
3446                         mono_image_get_field_info (
3447                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3448         }
3449
3450         /* handle constructors */
3451         if (tb->ctors) {
3452                 table = &assembly->tables [MONO_TABLE_METHOD];
3453                 table->rows += mono_array_length (tb->ctors);
3454                 alloc_table (table, table->rows);
3455                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3456                         mono_image_get_ctor_info (domain,
3457                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3458         }
3459
3460         /* handle methods */
3461         if (tb->methods) {
3462                 table = &assembly->tables [MONO_TABLE_METHOD];
3463                 table->rows += tb->num_methods;
3464                 alloc_table (table, table->rows);
3465                 for (i = 0; i < tb->num_methods; ++i)
3466                         mono_image_get_method_info (
3467                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3468         }
3469
3470         /* Do the same with properties etc.. */
3471         if (tb->events && mono_array_length (tb->events)) {
3472                 table = &assembly->tables [MONO_TABLE_EVENT];
3473                 table->rows += mono_array_length (tb->events);
3474                 alloc_table (table, table->rows);
3475                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3476                 table->rows ++;
3477                 alloc_table (table, table->rows);
3478                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3479                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3480                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3481                 for (i = 0; i < mono_array_length (tb->events); ++i)
3482                         mono_image_get_event_info (
3483                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3484         }
3485         if (tb->properties && mono_array_length (tb->properties)) {
3486                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3487                 table->rows += mono_array_length (tb->properties);
3488                 alloc_table (table, table->rows);
3489                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3490                 table->rows ++;
3491                 alloc_table (table, table->rows);
3492                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3493                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3494                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3495                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3496                         mono_image_get_property_info (
3497                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3498         }
3499
3500         /* handle generic parameters */
3501         if (tb->generic_params) {
3502                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3503                 table->rows += mono_array_length (tb->generic_params);
3504                 alloc_table (table, table->rows);
3505                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3506                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3507
3508                         mono_image_get_generic_param_info (
3509                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3510                 }
3511         }
3512
3513         mono_image_add_decl_security (assembly, 
3514                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3515
3516         if (tb->subtypes) {
3517                 MonoDynamicTable *ntable;
3518                 
3519                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3520                 ntable->rows += mono_array_length (tb->subtypes);
3521                 alloc_table (ntable, ntable->rows);
3522                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3523
3524                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3525                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3526
3527                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3528                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3529                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3530                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3531                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3532                                 ntable->next_idx, ntable->rows);*/
3533                         values += MONO_NESTED_CLASS_SIZE;
3534                         ntable->next_idx++;
3535                 }
3536         }
3537 }
3538 #endif
3539
3540 static void
3541 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3542 {
3543         int i;
3544
3545         mono_ptr_array_append (*types, type);
3546
3547         if (!type->subtypes)
3548                 return;
3549
3550         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3551                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3552                 collect_types (types, subtype);
3553         }
3554 }
3555
3556 static gint
3557 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3558 {
3559         if ((*type1)->table_idx < (*type2)->table_idx)
3560                 return -1;
3561         else
3562                 if ((*type1)->table_idx > (*type2)->table_idx)
3563                         return 1;
3564         else
3565                 return 0;
3566 }
3567
3568 static void
3569 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3570         int i;
3571
3572         if (!pinfo)
3573                 return;
3574         for (i = 0; i < mono_array_length (pinfo); ++i) {
3575                 MonoReflectionParamBuilder *pb;
3576                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3577                 if (!pb)
3578                         continue;
3579                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3580         }
3581 }
3582
3583 static void
3584 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3585         int i;
3586         
3587         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3588         if (tb->fields) {
3589                 for (i = 0; i < tb->num_fields; ++i) {
3590                         MonoReflectionFieldBuilder* fb;
3591                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3592                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3593                 }
3594         }
3595         if (tb->events) {
3596                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3597                         MonoReflectionEventBuilder* eb;
3598                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3599                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3600                 }
3601         }
3602         if (tb->properties) {
3603                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3604                         MonoReflectionPropertyBuilder* pb;
3605                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3606                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3607                 }
3608         }
3609         if (tb->ctors) {
3610                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3611                         MonoReflectionCtorBuilder* cb;
3612                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3613                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3614                         params_add_cattrs (assembly, cb->pinfo);
3615                 }
3616         }
3617
3618         if (tb->methods) {
3619                 for (i = 0; i < tb->num_methods; ++i) {
3620                         MonoReflectionMethodBuilder* mb;
3621                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3622                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3623                         params_add_cattrs (assembly, mb->pinfo);
3624                 }
3625         }
3626
3627         if (tb->subtypes) {
3628                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3629                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3630         }
3631 }
3632
3633 static void
3634 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3635 {
3636         int i;
3637         
3638         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3639
3640         if (moduleb->global_methods) {
3641                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3642                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3643                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3644                         params_add_cattrs (assembly, mb->pinfo);
3645                 }
3646         }
3647
3648         if (moduleb->global_fields) {
3649                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3650                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3651                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3652                 }
3653         }
3654         
3655         if (moduleb->types) {
3656                 for (i = 0; i < moduleb->num_types; ++i)
3657                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3658         }
3659 }
3660
3661 static void
3662 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3663 {
3664         MonoDynamicTable *table;
3665         guint32 *values;
3666         char blob_size [6];
3667         guchar hash [20];
3668         char *b = blob_size;
3669         char *dir, *path;
3670
3671         table = &assembly->tables [MONO_TABLE_FILE];
3672         table->rows++;
3673         alloc_table (table, table->rows);
3674         values = table->values + table->next_idx * MONO_FILE_SIZE;
3675         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3676         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3677         if (module->image->dynamic) {
3678                 /* This depends on the fact that the main module is emitted last */
3679                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3680                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3681         } else {
3682                 dir = NULL;
3683                 path = g_strdup (module->image->name);
3684         }
3685         mono_sha1_get_digest_from_file (path, hash);
3686         g_free (dir);
3687         g_free (path);
3688         mono_metadata_encode_value (20, b, &b);
3689         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3690         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3691         table->next_idx ++;
3692 }
3693
3694 static void
3695 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3696 {
3697         MonoDynamicTable *table;
3698         int i;
3699
3700         table = &assembly->tables [MONO_TABLE_MODULE];
3701         mb->table_idx = table->next_idx ++;
3702         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3703         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3704         i /= 16;
3705         ++i;
3706         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3707         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3708         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3709         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3710 }
3711
3712 static guint32
3713 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3714         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3715 {
3716         MonoDynamicTable *table;
3717         guint32 *values;
3718         guint32 visib, res;
3719
3720         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3721         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3722                 return 0;
3723
3724         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3725         table->rows++;
3726         alloc_table (table, table->rows);
3727         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3728
3729         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3730         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3731         if (klass->nested_in)
3732                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3733         else
3734                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3735         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3736         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3737
3738         res = table->next_idx;
3739
3740         table->next_idx ++;
3741
3742         /* Emit nested types */
3743         if (klass->ext && klass->ext->nested_classes) {
3744                 GList *tmp;
3745
3746                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3747                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3748         }
3749
3750         return res;
3751 }
3752
3753 static void
3754 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3755         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3756 {
3757         MonoClass *klass;
3758         guint32 idx, i;
3759
3760         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3761
3762         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3763
3764         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3765                                                                                                    parent_index, assembly);
3766
3767         /* 
3768          * Emit nested types
3769          * We need to do this ourselves since klass->nested_classes is not set up.
3770          */
3771         if (tb->subtypes) {
3772                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3773                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3774         }
3775 }
3776
3777 static void
3778 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3779         guint32 module_index, MonoDynamicImage *assembly)
3780 {
3781         MonoImage *image = module->image;
3782         MonoTableInfo  *t;
3783         guint32 i;
3784
3785         t = &image->tables [MONO_TABLE_TYPEDEF];
3786
3787         for (i = 0; i < t->rows; ++i) {
3788                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3789
3790                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3791                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3792         }
3793 }
3794
3795 static void
3796 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3797 {
3798         MonoDynamicTable *table;
3799         guint32 *values;
3800         guint32 scope, scope_idx, impl, current_idx;
3801         gboolean forwarder = TRUE;
3802         gpointer iter = NULL;
3803         MonoClass *nested;
3804
3805         if (klass->nested_in) {
3806                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3807                 forwarder = FALSE;
3808         } else {
3809                 scope = resolution_scope_from_image (assembly, klass->image);
3810                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3811                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3812                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3813         }
3814
3815         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3816
3817         table->rows++;
3818         alloc_table (table, table->rows);
3819         current_idx = table->next_idx;
3820         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3821
3822         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3823         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3824         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3825         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3826         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3827
3828         table->next_idx++;
3829
3830         while ((nested = mono_class_get_nested_types (klass, &iter)))
3831                 add_exported_type (assemblyb, assembly, nested, current_idx);
3832 }
3833
3834 static void
3835 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3836 {
3837         MonoClass *klass;
3838         int i;
3839
3840         if (!assemblyb->type_forwarders)
3841                 return;
3842
3843         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3844                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3845                 MonoType *type;
3846                 if (!t)
3847                         continue;
3848
3849                 type = mono_reflection_type_get_handle (t);
3850                 g_assert (type);
3851
3852                 klass = mono_class_from_mono_type (type);
3853
3854                 add_exported_type (assemblyb, assembly, klass, 0);
3855         }
3856 }
3857
3858 #define align_pointer(base,p)\
3859         do {\
3860                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3861                 if (__diff & 3)\
3862                         (p) += 4 - (__diff & 3);\
3863         } while (0)
3864
3865 static int
3866 compare_constants (const void *a, const void *b)
3867 {
3868         const guint32 *a_values = a;
3869         const guint32 *b_values = b;
3870         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3871 }
3872
3873 static int
3874 compare_semantics (const void *a, const void *b)
3875 {
3876         const guint32 *a_values = a;
3877         const guint32 *b_values = b;
3878         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3879         if (assoc)
3880                 return assoc;
3881         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3882 }
3883
3884 static int
3885 compare_custom_attrs (const void *a, const void *b)
3886 {
3887         const guint32 *a_values = a;
3888         const guint32 *b_values = b;
3889
3890         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3891 }
3892
3893 static int
3894 compare_field_marshal (const void *a, const void *b)
3895 {
3896         const guint32 *a_values = a;
3897         const guint32 *b_values = b;
3898
3899         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3900 }
3901
3902 static int
3903 compare_nested (const void *a, const void *b)
3904 {
3905         const guint32 *a_values = a;
3906         const guint32 *b_values = b;
3907
3908         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3909 }
3910
3911 static int
3912 compare_genericparam (const void *a, const void *b)
3913 {
3914         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3915         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3916
3917         if ((*b_entry)->owner == (*a_entry)->owner)
3918                 return 
3919                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3920                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3921         else
3922                 return (*a_entry)->owner - (*b_entry)->owner;
3923 }
3924
3925 static int
3926 compare_declsecurity_attrs (const void *a, const void *b)
3927 {
3928         const guint32 *a_values = a;
3929         const guint32 *b_values = b;
3930
3931         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3932 }
3933
3934 static int
3935 compare_interface_impl (const void *a, const void *b)
3936 {
3937         const guint32 *a_values = a;
3938         const guint32 *b_values = b;
3939
3940         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3941         if (klass)
3942                 return klass;
3943
3944         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3945 }
3946
3947 static void
3948 pad_heap (MonoDynamicStream *sh)
3949 {
3950         if (sh->index & 3) {
3951                 int sz = 4 - (sh->index & 3);
3952                 memset (sh->data + sh->index, 0, sz);
3953                 sh->index += sz;
3954         }
3955 }
3956
3957 struct StreamDesc {
3958         const char *name;
3959         MonoDynamicStream *stream;
3960 };
3961
3962 /*
3963  * build_compressed_metadata() fills in the blob of data that represents the 
3964  * raw metadata as it will be saved in the PE file. The five streams are output 
3965  * and the metadata tables are comnpressed from the guint32 array representation, 
3966  * to the compressed on-disk format.
3967  */
3968 static void
3969 build_compressed_metadata (MonoDynamicImage *assembly)
3970 {
3971         MonoDynamicTable *table;
3972         int i;
3973         guint64 valid_mask = 0;
3974         guint64 sorted_mask;
3975         guint32 heapt_size = 0;
3976         guint32 meta_size = 256; /* allow for header and other stuff */
3977         guint32 table_offset;
3978         guint32 ntables = 0;
3979         guint64 *int64val;
3980         guint32 *int32val;
3981         guint16 *int16val;
3982         MonoImage *meta;
3983         unsigned char *p;
3984         struct StreamDesc stream_desc [5];
3985
3986         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3987         for (i = 0; i < assembly->gen_params->len; i++){
3988                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3989                 write_generic_param_entry (assembly, entry);
3990         }
3991
3992         stream_desc [0].name  = "#~";
3993         stream_desc [0].stream = &assembly->tstream;
3994         stream_desc [1].name  = "#Strings";
3995         stream_desc [1].stream = &assembly->sheap;
3996         stream_desc [2].name  = "#US";
3997         stream_desc [2].stream = &assembly->us;
3998         stream_desc [3].name  = "#Blob";
3999         stream_desc [3].stream = &assembly->blob;
4000         stream_desc [4].name  = "#GUID";
4001         stream_desc [4].stream = &assembly->guid;
4002         
4003         /* tables that are sorted */
4004         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4005                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4006                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4007                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4008                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4009                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4010                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4011         
4012         /* Compute table sizes */
4013         /* the MonoImage has already been created in mono_image_basic_init() */
4014         meta = &assembly->image;
4015
4016         /* sizes should be multiple of 4 */
4017         pad_heap (&assembly->blob);
4018         pad_heap (&assembly->guid);
4019         pad_heap (&assembly->sheap);
4020         pad_heap (&assembly->us);
4021
4022         /* Setup the info used by compute_sizes () */
4023         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4024         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4025         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4026
4027         meta_size += assembly->blob.index;
4028         meta_size += assembly->guid.index;
4029         meta_size += assembly->sheap.index;
4030         meta_size += assembly->us.index;
4031
4032         for (i=0; i < MONO_TABLE_NUM; ++i)
4033                 meta->tables [i].rows = assembly->tables [i].rows;
4034         
4035         for (i = 0; i < MONO_TABLE_NUM; i++){
4036                 if (meta->tables [i].rows == 0)
4037                         continue;
4038                 valid_mask |= (guint64)1 << i;
4039                 ntables ++;
4040                 meta->tables [i].row_size = mono_metadata_compute_size (
4041                         meta, i, &meta->tables [i].size_bitfield);
4042                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4043         }
4044         heapt_size += 24; /* #~ header size */
4045         heapt_size += ntables * 4;
4046         /* make multiple of 4 */
4047         heapt_size += 3;
4048         heapt_size &= ~3;
4049         meta_size += heapt_size;
4050         meta->raw_metadata = g_malloc0 (meta_size);
4051         p = (unsigned char*)meta->raw_metadata;
4052         /* the metadata signature */
4053         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4054         /* version numbers and 4 bytes reserved */
4055         int16val = (guint16*)p;
4056         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4057         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4058         p += 8;
4059         /* version string */
4060         int32val = (guint32*)p;
4061         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4062         p += 4;
4063         memcpy (p, meta->version, strlen (meta->version));
4064         p += GUINT32_FROM_LE (*int32val);
4065         align_pointer (meta->raw_metadata, p);
4066         int16val = (guint16*)p;
4067         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4068         *int16val = GUINT16_TO_LE (5); /* number of streams */
4069         p += 4;
4070
4071         /*
4072          * write the stream info.
4073          */
4074         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4075         table_offset += 3; table_offset &= ~3;
4076
4077         assembly->tstream.index = heapt_size;
4078         for (i = 0; i < 5; ++i) {
4079                 int32val = (guint32*)p;
4080                 stream_desc [i].stream->offset = table_offset;
4081                 *int32val++ = GUINT32_TO_LE (table_offset);
4082                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4083                 table_offset += GUINT32_FROM_LE (*int32val);
4084                 table_offset += 3; table_offset &= ~3;
4085                 p += 8;
4086                 strcpy ((char*)p, stream_desc [i].name);
4087                 p += strlen (stream_desc [i].name) + 1;
4088                 align_pointer (meta->raw_metadata, p);
4089         }
4090         /* 
4091          * now copy the data, the table stream header and contents goes first.
4092          */
4093         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4094         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4095         int32val = (guint32*)p;
4096         *int32val = GUINT32_TO_LE (0); /* reserved */
4097         p += 4;
4098
4099         *p++ = 2; /* version */
4100         *p++ = 0;
4101
4102         if (meta->idx_string_wide)
4103                 *p |= 0x01;
4104         if (meta->idx_guid_wide)
4105                 *p |= 0x02;
4106         if (meta->idx_blob_wide)
4107                 *p |= 0x04;
4108         ++p;
4109         *p++ = 1; /* reserved */
4110         int64val = (guint64*)p;
4111         *int64val++ = GUINT64_TO_LE (valid_mask);
4112         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4113         p += 16;
4114         int32val = (guint32*)p;
4115         for (i = 0; i < MONO_TABLE_NUM; i++){
4116                 if (meta->tables [i].rows == 0)
4117                         continue;
4118                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4119         }
4120         p = (unsigned char*)int32val;
4121
4122         /* sort the tables that still need sorting */
4123         table = &assembly->tables [MONO_TABLE_CONSTANT];
4124         if (table->rows)
4125                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4126         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4127         if (table->rows)
4128                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4129         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4130         if (table->rows)
4131                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4132         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4133         if (table->rows)
4134                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4135         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4136         if (table->rows)
4137                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4138         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4139         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4140         if (table->rows)
4141                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4142         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4143         if (table->rows)
4144                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4145
4146         /* compress the tables */
4147         for (i = 0; i < MONO_TABLE_NUM; i++){
4148                 int row, col;
4149                 guint32 *values;
4150                 guint32 bitfield = meta->tables [i].size_bitfield;
4151                 if (!meta->tables [i].rows)
4152                         continue;
4153                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4154                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4155                 meta->tables [i].base = (char*)p;
4156                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4157                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4158                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4159                                 switch (mono_metadata_table_size (bitfield, col)) {
4160                                 case 1:
4161                                         *p++ = values [col];
4162                                         break;
4163                                 case 2:
4164                                         *p++ = values [col] & 0xff;
4165                                         *p++ = (values [col] >> 8) & 0xff;
4166                                         break;
4167                                 case 4:
4168                                         *p++ = values [col] & 0xff;
4169                                         *p++ = (values [col] >> 8) & 0xff;
4170                                         *p++ = (values [col] >> 16) & 0xff;
4171                                         *p++ = (values [col] >> 24) & 0xff;
4172                                         break;
4173                                 default:
4174                                         g_assert_not_reached ();
4175                                 }
4176                         }
4177                 }
4178                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4179         }
4180         
4181         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4182         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4183         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4184         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4185         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4186
4187         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4188 }
4189
4190 /*
4191  * Some tables in metadata need to be sorted according to some criteria, but
4192  * when methods and fields are first created with reflection, they may be assigned a token
4193  * that doesn't correspond to the final token they will get assigned after the sorting.
4194  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4195  * with the reflection objects that represent them. Once all the tables are set up, the 
4196  * reflection objects will contains the correct table index. fixup_method() will fixup the
4197  * tokens for the method with ILGenerator @ilgen.
4198  */
4199 static void
4200 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4201 {
4202         guint32 code_idx = GPOINTER_TO_UINT (value);
4203         MonoReflectionILTokenInfo *iltoken;
4204         MonoReflectionFieldBuilder *field;
4205         MonoReflectionCtorBuilder *ctor;
4206         MonoReflectionMethodBuilder *method;
4207         MonoReflectionTypeBuilder *tb;
4208         MonoReflectionArrayMethod *am;
4209         guint32 i, idx = 0;
4210         unsigned char *target;
4211
4212         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4213                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4214                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4215                 switch (target [3]) {
4216                 case MONO_TABLE_FIELD:
4217                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4218                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4219                                 idx = field->table_idx;
4220                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4221                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4222                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4223                         } else {
4224                                 g_assert_not_reached ();
4225                         }
4226                         break;
4227                 case MONO_TABLE_METHOD:
4228                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4229                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4230                                 idx = method->table_idx;
4231                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4233                                 idx = ctor->table_idx;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4235                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4236                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4237                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4238                         } else {
4239                                 g_assert_not_reached ();
4240                         }
4241                         break;
4242                 case MONO_TABLE_TYPEDEF:
4243                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4244                                 g_assert_not_reached ();
4245                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4246                         idx = tb->table_idx;
4247                         break;
4248                 case MONO_TABLE_MEMBERREF:
4249                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4250                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4251                                 idx = am->table_idx;
4252                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4253                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4254                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4255                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4256                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4257                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4258                                 continue;
4259                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4260                                 continue;
4261                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4262                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4263                                 g_assert (is_field_on_inst (f));
4264                                 continue;
4265                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4266                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4267                                 continue;
4268                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4269                                 continue;
4270                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4271                                 continue;
4272                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4273                                 continue;
4274                         } else {
4275                                 g_assert_not_reached ();
4276                         }
4277                         break;
4278                 case MONO_TABLE_METHODSPEC:
4279                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4280                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4281                                 g_assert (mono_method_signature (m)->generic_param_count);
4282                                 continue;
4283                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4284                                 continue;
4285                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4286                                 continue;
4287                         } else {
4288                                 g_assert_not_reached ();
4289                         }
4290                         break;
4291                 default:
4292                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4293                 }
4294                 target [0] = idx & 0xff;
4295                 target [1] = (idx >> 8) & 0xff;
4296                 target [2] = (idx >> 16) & 0xff;
4297         }
4298 }
4299
4300 /*
4301  * fixup_cattrs:
4302  *
4303  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4304  * value is not known when the table is emitted.
4305  */
4306 static void
4307 fixup_cattrs (MonoDynamicImage *assembly)
4308 {
4309         MonoDynamicTable *table;
4310         guint32 *values;
4311         guint32 type, i, idx, token;
4312         MonoObject *ctor;
4313
4314         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4315
4316         for (i = 0; i < table->rows; ++i) {
4317                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4318
4319                 type = values [MONO_CUSTOM_ATTR_TYPE];
4320                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4321                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4322                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4323                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4324                         g_assert (ctor);
4325
4326                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4327                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4328                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4329                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4330                         }
4331                 }
4332         }
4333 }
4334
4335 static void
4336 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4337 {
4338         MonoDynamicTable *table;
4339         guint32 *values;
4340
4341         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4342         table->rows++;
4343         alloc_table (table, table->rows);
4344         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4345         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4346         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4347         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4348         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4349         table->next_idx++;
4350 }
4351
4352 static void
4353 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4354 {
4355         MonoDynamicTable *table;
4356         guint32 *values;
4357         char blob_size [6];
4358         guchar hash [20];
4359         char *b = blob_size;
4360         char *name, *sname;
4361         guint32 idx, offset;
4362
4363         if (rsrc->filename) {
4364                 name = mono_string_to_utf8 (rsrc->filename);
4365                 sname = g_path_get_basename (name);
4366         
4367                 table = &assembly->tables [MONO_TABLE_FILE];
4368                 table->rows++;
4369                 alloc_table (table, table->rows);
4370                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4371                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4372                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4373                 g_free (sname);
4374
4375                 mono_sha1_get_digest_from_file (name, hash);
4376                 mono_metadata_encode_value (20, b, &b);
4377                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4378                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4379                 g_free (name);
4380                 idx = table->next_idx++;
4381                 rsrc->offset = 0;
4382                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4383         } else {
4384                 char sizebuf [4];
4385                 char *data;
4386                 guint len;
4387                 if (rsrc->data) {
4388                         data = mono_array_addr (rsrc->data, char, 0);
4389                         len = mono_array_length (rsrc->data);
4390                 } else {
4391                         data = NULL;
4392                         len = 0;
4393                 }
4394                 offset = len;
4395                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4396                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4397                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4398                 mono_image_add_stream_data (&assembly->resources, data, len);
4399
4400                 if (!mb->is_main)
4401                         /* 
4402                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4403                          * the main module, but that needs to reference the FILE table
4404                          * which isn't emitted yet.
4405                          */
4406                         return;
4407                 else
4408                         idx = 0;
4409         }
4410
4411         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4412 }
4413
4414 static void
4415 set_version_from_string (MonoString *version, guint32 *values)
4416 {
4417         gchar *ver, *p, *str;
4418         guint32 i;
4419         
4420         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4421         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4422         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4423         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4424         if (!version)
4425                 return;
4426         ver = str = mono_string_to_utf8 (version);
4427         for (i = 0; i < 4; ++i) {
4428                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4429                 switch (*p) {
4430                 case '.':
4431                         p++;
4432                         break;
4433                 case '*':
4434                         /* handle Revision and Build */
4435                         p++;
4436                         break;
4437                 }
4438                 ver = p;
4439         }
4440         g_free (str);
4441 }
4442
4443 static guint32
4444 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4445         gsize len;
4446         guint32 token = 0;
4447         char blob_size [6];
4448         char *b = blob_size;
4449
4450         if (!pkey)
4451                 return token;
4452
4453         len = mono_array_length (pkey);
4454         mono_metadata_encode_value (len, b, &b);
4455         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4456         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4457
4458         assembly->public_key = g_malloc (len);
4459         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4460         assembly->public_key_len = len;
4461
4462         /* Special case: check for ECMA key (16 bytes) */
4463         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4464                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4465                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4466         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4467                 /* minimum key size (in 2.0) is 384 bits */
4468                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4469         } else {
4470                 /* FIXME - verifier */
4471                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4472                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4473         }
4474         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4475
4476         return token;
4477 }
4478
4479 static void
4480 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4481 {
4482         MonoDynamicTable *table;
4483         MonoDynamicImage *assembly;
4484         MonoReflectionAssemblyBuilder *assemblyb;
4485         MonoDomain *domain;
4486         guint32 *values;
4487         int i;
4488         guint32 module_index;
4489
4490         assemblyb = moduleb->assemblyb;
4491         assembly = moduleb->dynamic_image;
4492         domain = mono_object_domain (assemblyb);
4493
4494         /* Emit ASSEMBLY table */
4495         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4496         alloc_table (table, 1);
4497         values = table->values + MONO_ASSEMBLY_SIZE;
4498         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4499         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4500         if (assemblyb->culture) {
4501                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4502         } else {
4503                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4504         }
4505         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4506         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4507         set_version_from_string (assemblyb->version, values);
4508
4509         /* Emit FILE + EXPORTED_TYPE table */
4510         module_index = 0;
4511         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4512                 int j;
4513                 MonoReflectionModuleBuilder *file_module = 
4514                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4515                 if (file_module != moduleb) {
4516                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4517                         module_index ++;
4518                         if (file_module->types) {
4519                                 for (j = 0; j < file_module->num_types; ++j) {
4520                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4521                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4522                                 }
4523                         }
4524                 }
4525         }
4526         if (assemblyb->loaded_modules) {
4527                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4528                         MonoReflectionModule *file_module = 
4529                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4530                         mono_image_fill_file_table (domain, file_module, assembly);
4531                         module_index ++;
4532                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4533                 }
4534         }
4535         if (assemblyb->type_forwarders)
4536                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4537
4538         /* Emit MANIFESTRESOURCE table */
4539         module_index = 0;
4540         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4541                 int j;
4542                 MonoReflectionModuleBuilder *file_module = 
4543                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4544                 /* The table for the main module is emitted later */
4545                 if (file_module != moduleb) {
4546                         module_index ++;
4547                         if (file_module->resources) {
4548                                 int len = mono_array_length (file_module->resources);
4549                                 for (j = 0; j < len; ++j) {
4550                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4551                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4552                                 }
4553                         }
4554                 }
4555         }               
4556 }
4557
4558 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4559
4560 /*
4561  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4562  * for the modulebuilder @moduleb.
4563  * At the end of the process, method and field tokens are fixed up and the 
4564  * on-disk compressed metadata representation is created.
4565  */
4566 void
4567 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4568 {
4569         MonoDynamicTable *table;
4570         MonoDynamicImage *assembly;
4571         MonoReflectionAssemblyBuilder *assemblyb;
4572         MonoDomain *domain;
4573         MonoPtrArray types;
4574         guint32 *values;
4575         int i, j;
4576
4577         assemblyb = moduleb->assemblyb;
4578         assembly = moduleb->dynamic_image;
4579         domain = mono_object_domain (assemblyb);
4580
4581         if (assembly->text_rva)
4582                 return;
4583
4584         assembly->text_rva = START_TEXT_RVA;
4585
4586         if (moduleb->is_main) {
4587                 mono_image_emit_manifest (moduleb);
4588         }
4589
4590         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4591         table->rows = 1; /* .<Module> */
4592         table->next_idx++;
4593         alloc_table (table, table->rows);
4594         /*
4595          * Set the first entry.
4596          */
4597         values = table->values + table->columns;
4598         values [MONO_TYPEDEF_FLAGS] = 0;
4599         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4600         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4601         values [MONO_TYPEDEF_EXTENDS] = 0;
4602         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4603         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4604
4605         /* 
4606          * handle global methods 
4607          * FIXME: test what to do when global methods are defined in multiple modules.
4608          */
4609         if (moduleb->global_methods) {
4610                 table = &assembly->tables [MONO_TABLE_METHOD];
4611                 table->rows += mono_array_length (moduleb->global_methods);
4612                 alloc_table (table, table->rows);
4613                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4614                         mono_image_get_method_info (
4615                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4616         }
4617         if (moduleb->global_fields) {
4618                 table = &assembly->tables [MONO_TABLE_FIELD];
4619                 table->rows += mono_array_length (moduleb->global_fields);
4620                 alloc_table (table, table->rows);
4621                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4622                         mono_image_get_field_info (
4623                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4624         }
4625
4626         table = &assembly->tables [MONO_TABLE_MODULE];
4627         alloc_table (table, 1);
4628         mono_image_fill_module_table (domain, moduleb, assembly);
4629
4630         /* Collect all types into a list sorted by their table_idx */
4631         mono_ptr_array_init (types, moduleb->num_types);
4632
4633         if (moduleb->types)
4634                 for (i = 0; i < moduleb->num_types; ++i) {
4635                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4636                         collect_types (&types, type);
4637                 }
4638
4639         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4640         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4641         table->rows += mono_ptr_array_size (types);
4642         alloc_table (table, table->rows);
4643
4644         /*
4645          * Emit type names + namespaces at one place inside the string heap,
4646          * so load_class_names () needs to touch fewer pages.
4647          */
4648         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4649                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4650                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4651         }
4652         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4653                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4654                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4655         }
4656
4657         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4658                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4659                 mono_image_get_type_info (domain, type, assembly);
4660         }
4661
4662         /* 
4663          * table->rows is already set above and in mono_image_fill_module_table.
4664          */
4665         /* add all the custom attributes at the end, once all the indexes are stable */
4666         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4667
4668         /* CAS assembly permissions */
4669         if (assemblyb->permissions_minimum)
4670                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4671         if (assemblyb->permissions_optional)
4672                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4673         if (assemblyb->permissions_refused)
4674                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4675
4676         module_add_cattrs (assembly, moduleb);
4677
4678         /* fixup tokens */
4679         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4680
4681         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4682          * the final tokens and don't need another fixup pass. */
4683
4684         if (moduleb->global_methods) {
4685                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4686                         MonoReflectionMethodBuilder *mb = mono_array_get (
4687                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4688                         mono_image_add_methodimpl (assembly, mb);
4689                 }
4690         }
4691
4692         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4693                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4694                 if (type->methods) {
4695                         for (j = 0; j < type->num_methods; ++j) {
4696                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4697                                         type->methods, MonoReflectionMethodBuilder*, j);
4698
4699                                 mono_image_add_methodimpl (assembly, mb);
4700                         }
4701                 }
4702         }
4703
4704         mono_ptr_array_destroy (types);
4705
4706         fixup_cattrs (assembly);
4707 }
4708
4709 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4710
4711 void
4712 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4713 {
4714         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4715 }
4716
4717 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4718
4719
4720 typedef struct {
4721         guint32 import_lookup_table;
4722         guint32 timestamp;
4723         guint32 forwarder;
4724         guint32 name_rva;
4725         guint32 import_address_table_rva;
4726 } MonoIDT;
4727
4728 typedef struct {
4729         guint32 name_rva;
4730         guint32 flags;
4731 } MonoILT;
4732
4733 #ifndef DISABLE_REFLECTION_EMIT
4734
4735 /*
4736  * mono_image_insert_string:
4737  * @module: module builder object
4738  * @str: a string
4739  *
4740  * Insert @str into the user string stream of @module.
4741  */
4742 guint32
4743 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4744 {
4745         MonoDynamicImage *assembly;
4746         guint32 idx;
4747         char buf [16];
4748         char *b = buf;
4749         
4750         MONO_ARCH_SAVE_REGS;
4751
4752         if (!module->dynamic_image)
4753                 mono_image_module_basic_init (module);
4754
4755         assembly = module->dynamic_image;
4756         
4757         if (assembly->save) {
4758                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4759                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4760 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4761         {
4762                 char *swapped = g_malloc (2 * mono_string_length (str));
4763                 const char *p = (const char*)mono_string_chars (str);
4764
4765                 swap_with_size (swapped, p, 2, mono_string_length (str));
4766                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4767                 g_free (swapped);
4768         }
4769 #else
4770                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4771 #endif
4772                 mono_image_add_stream_data (&assembly->us, "", 1);
4773         } else {
4774                 idx = assembly->us.index ++;
4775         }
4776
4777         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4778
4779         return MONO_TOKEN_STRING | idx;
4780 }
4781
4782 guint32
4783 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4784 {
4785         MonoClass *klass;
4786         guint32 token = 0;
4787         MonoMethodSignature *sig;
4788
4789         klass = obj->vtable->klass;
4790         if (strcmp (klass->name, "MonoMethod") == 0) {
4791                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4792                 MonoMethodSignature *old;
4793                 guint32 sig_token, parent;
4794                 int nargs, i;
4795
4796                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4797
4798                 nargs = mono_array_length (opt_param_types);
4799                 old = mono_method_signature (method);
4800                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4801
4802                 sig->hasthis = old->hasthis;
4803                 sig->explicit_this = old->explicit_this;
4804                 sig->call_convention = old->call_convention;
4805                 sig->generic_param_count = old->generic_param_count;
4806                 sig->param_count = old->param_count + nargs;
4807                 sig->sentinelpos = old->param_count;
4808                 sig->ret = old->ret;
4809
4810                 for (i = 0; i < old->param_count; i++)
4811                         sig->params [i] = old->params [i];
4812
4813                 for (i = 0; i < nargs; i++) {
4814                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4815                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4816                 }
4817
4818                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4819                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4820                 parent >>= MONO_TYPEDEFORREF_BITS;
4821
4822                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4823                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4824
4825                 sig_token = method_encode_signature (assembly, sig);
4826                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4827         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4828                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4829                 ReflectionMethodBuilder rmb;
4830                 guint32 parent, sig_token;
4831                 int nopt_args, nparams, ngparams, i;
4832                 char *name;
4833
4834                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4835                 rmb.opt_types = opt_param_types;
4836                 nopt_args = mono_array_length (opt_param_types);
4837
4838                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4839                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4840                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4841
4842                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4843                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4844                 sig->call_convention = rmb.call_conv;
4845                 sig->generic_param_count = ngparams;
4846                 sig->param_count = nparams + nopt_args;
4847                 sig->sentinelpos = nparams;
4848                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4849
4850                 for (i = 0; i < nparams; i++) {
4851                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4852                         sig->params [i] = mono_reflection_type_get_handle (rt);
4853                 }
4854
4855                 for (i = 0; i < nopt_args; i++) {
4856                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4857                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4858                 }
4859
4860                 sig_token = method_builder_encode_signature (assembly, &rmb);
4861
4862                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4863                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4864
4865                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4866                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4867
4868                 name = mono_string_to_utf8 (rmb.name);
4869                 token = mono_image_get_varargs_method_token (
4870                         assembly, parent, name, sig_token);
4871                 g_free (name);
4872         } else {
4873                 g_error ("requested method token for %s\n", klass->name);
4874         }
4875
4876         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4877         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4878         return token;
4879 }
4880
4881 /*
4882  * mono_image_create_token:
4883  * @assembly: a dynamic assembly
4884  * @obj:
4885  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4886  *
4887  * Get a token to insert in the IL code stream for the given MemberInfo.
4888  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4889  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4890  * entry.
4891  */
4892 guint32
4893 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4894                                                  gboolean create_open_instance, gboolean register_token)
4895 {
4896         MonoClass *klass;
4897         guint32 token = 0;
4898
4899         klass = obj->vtable->klass;
4900
4901         /* Check for user defined reflection objects */
4902         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4903         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4904                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4905
4906         if (strcmp (klass->name, "MethodBuilder") == 0) {
4907                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4908                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4909
4910                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4911                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4912                 else
4913                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4914                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4915         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4916                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4917                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4918
4919                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4920                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4921                 else
4922                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4923                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4924         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4925                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4926                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4927                 if (tb->generic_params) {
4928                         token = mono_image_get_generic_field_token (assembly, fb);
4929                 } else {
4930                         if ((tb->module->dynamic_image == assembly)) {
4931                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4932                         } else {
4933                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4934                         }
4935                 }
4936         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4937                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4938                 if (create_open_instance && tb->generic_params) {
4939                         MonoType *type;
4940                         init_type_builder_generics (obj);
4941                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4942                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4943                         token = mono_metadata_token_from_dor (token);
4944                 } else {
4945                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4946                 }
4947         } else if (strcmp (klass->name, "MonoType") == 0) {
4948                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4949                 MonoClass *mc = mono_class_from_mono_type (type);
4950                 token = mono_metadata_token_from_dor (
4951                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4952         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4953                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4954                 token = mono_metadata_token_from_dor (
4955                         mono_image_typedef_or_ref (assembly, type));
4956         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4957                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4958                 token = mono_metadata_token_from_dor (
4959                         mono_image_typedef_or_ref (assembly, type));
4960         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4961                    strcmp (klass->name, "MonoMethod") == 0 ||
4962                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4963                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4964                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4965                 if (m->method->is_inflated) {
4966                         if (create_open_instance)
4967                                 token = mono_image_get_methodspec_token (assembly, m->method);
4968                         else
4969                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4970                 } else if ((m->method->klass->image == &assembly->image) &&
4971                          !m->method->klass->generic_class) {
4972                         static guint32 method_table_idx = 0xffffff;
4973                         if (m->method->klass->wastypebuilder) {
4974                                 /* we use the same token as the one that was assigned
4975                                  * to the Methodbuilder.
4976                                  * FIXME: do the equivalent for Fields.
4977                                  */
4978                                 token = m->method->token;
4979                         } else {
4980                                 /*
4981                                  * Each token should have a unique index, but the indexes are
4982                                  * assigned by managed code, so we don't know about them. An
4983                                  * easy solution is to count backwards...
4984                                  */
4985                                 method_table_idx --;
4986                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4987                         }
4988                 } else {
4989                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4990                 }
4991                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4992         } else if (strcmp (klass->name, "MonoField") == 0) {
4993                 MonoReflectionField *f = (MonoReflectionField *)obj;
4994                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4995                         static guint32 field_table_idx = 0xffffff;
4996                         field_table_idx --;
4997                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4998                 } else {
4999                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5000                 }
5001                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5002         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5003                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5004                 token = mono_image_get_array_token (assembly, m);
5005         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5006                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5007                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5008         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5009                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5010                 token = mono_metadata_token_from_dor (
5011                         mono_image_typedef_or_ref (assembly, type));
5012         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5013                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5014                 token = mono_image_get_field_on_inst_token (assembly, f);
5015         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5016                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5017                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5018         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5019                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5020                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5021         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5022                 MonoReflectionType *type = (MonoReflectionType *)obj;
5023                 token = mono_metadata_token_from_dor (
5024                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5025         } else {
5026                 g_error ("requested token for %s\n", klass->name);
5027         }
5028
5029         if (register_token)
5030                 mono_image_register_token (assembly, token, obj);
5031
5032         return token;
5033 }
5034
5035 /*
5036  * mono_image_register_token:
5037  *
5038  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5039  * the Module.ResolveXXXToken () methods to work.
5040  */
5041 void
5042 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5043 {
5044         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5045         if (prev) {
5046                 /* There could be multiple MethodInfo objects with the same token */
5047                 //g_assert (prev == obj);
5048         } else {
5049                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5050         }
5051 }
5052
5053 static MonoDynamicImage*
5054 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5055 {
5056         static const guchar entrycode [16] = {0xff, 0x25, 0};
5057         MonoDynamicImage *image;
5058         int i;
5059
5060         const char *version;
5061
5062         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5063                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5064         else
5065                 version = mono_get_runtime_info ()->runtime_version;
5066
5067 #if HAVE_BOEHM_GC
5068         /* The MonoGHashTable's need GC tracking */
5069         image = GC_MALLOC (sizeof (MonoDynamicImage));
5070 #else
5071         image = g_new0 (MonoDynamicImage, 1);
5072 #endif
5073         
5074         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5075         
5076         /*g_print ("created image %p\n", image);*/
5077         /* keep in sync with image.c */
5078         image->image.name = assembly_name;
5079         image->image.assembly_name = image->image.name; /* they may be different */
5080         image->image.module_name = module_name;
5081         image->image.version = g_strdup (version);
5082         image->image.md_version_major = 1;
5083         image->image.md_version_minor = 1;
5084         image->image.dynamic = TRUE;
5085
5086         image->image.references = g_new0 (MonoAssembly*, 1);
5087         image->image.references [0] = NULL;
5088
5089         mono_image_init (&image->image);
5090
5091         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5092         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5093         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5094         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5095         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5096         image->handleref = g_hash_table_new (NULL, NULL);
5097         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5098         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5099         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5100         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5101         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5102         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5103         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5104         image->gen_params = g_ptr_array_new ();
5105
5106         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5107         string_heap_init (&image->sheap);
5108         mono_image_add_stream_data (&image->us, "", 1);
5109         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5110         /* import tables... */
5111         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5112         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5113         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5114         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5115         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5116         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5117         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5118         stream_data_align (&image->code);
5119
5120         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5121
5122         for (i=0; i < MONO_TABLE_NUM; ++i) {
5123                 image->tables [i].next_idx = 1;
5124                 image->tables [i].columns = table_sizes [i];
5125         }
5126
5127         image->image.assembly = (MonoAssembly*)assembly;
5128         image->run = assembly->run;
5129         image->save = assembly->save;
5130         image->pe_kind = 0x1; /* ILOnly */
5131         image->machine = 0x14c; /* I386 */
5132         
5133         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5134
5135         return image;
5136 }
5137 #endif
5138
5139 static void
5140 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5141 {
5142         g_free (key);
5143 }
5144
5145 void
5146 mono_dynamic_image_free (MonoDynamicImage *image)
5147 {
5148         MonoDynamicImage *di = image;
5149         GList *list;
5150         int i;
5151
5152         if (di->methodspec)
5153                 mono_g_hash_table_destroy (di->methodspec);
5154         if (di->typespec)
5155                 g_hash_table_destroy (di->typespec);
5156         if (di->typeref)
5157                 g_hash_table_destroy (di->typeref);
5158         if (di->handleref)
5159                 g_hash_table_destroy (di->handleref);
5160         if (di->handleref_managed)
5161                 mono_g_hash_table_destroy (di->handleref_managed);
5162         if (di->tokens)
5163                 mono_g_hash_table_destroy (di->tokens);
5164         if (di->generic_def_objects)
5165                 mono_g_hash_table_destroy (di->generic_def_objects);
5166         if (di->blob_cache) {
5167                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5168                 g_hash_table_destroy (di->blob_cache);
5169         }
5170         if (di->standalonesig_cache)
5171                 g_hash_table_destroy (di->standalonesig_cache);
5172         for (list = di->array_methods; list; list = list->next) {
5173                 ArrayMethod *am = (ArrayMethod *)list->data;
5174                 g_free (am->sig);
5175                 g_free (am->name);
5176                 g_free (am);
5177         }
5178         g_list_free (di->array_methods);
5179         if (di->gen_params) {
5180                 for (i = 0; i < di->gen_params->len; i++) {
5181                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5182                         mono_gc_deregister_root ((char*) &entry->gparam);
5183                         g_free (entry);
5184                 }
5185                 g_ptr_array_free (di->gen_params, TRUE);
5186         }
5187         if (di->token_fixups)
5188                 mono_g_hash_table_destroy (di->token_fixups);
5189         if (di->method_to_table_idx)
5190                 g_hash_table_destroy (di->method_to_table_idx);
5191         if (di->field_to_table_idx)
5192                 g_hash_table_destroy (di->field_to_table_idx);
5193         if (di->method_aux_hash)
5194                 g_hash_table_destroy (di->method_aux_hash);
5195         if (di->vararg_aux_hash)
5196                 g_hash_table_destroy (di->vararg_aux_hash);
5197         g_free (di->strong_name);
5198         g_free (di->win32_res);
5199         if (di->public_key)
5200                 g_free (di->public_key);
5201
5202         /*g_print ("string heap destroy for image %p\n", di);*/
5203         mono_dynamic_stream_reset (&di->sheap);
5204         mono_dynamic_stream_reset (&di->code);
5205         mono_dynamic_stream_reset (&di->resources);
5206         mono_dynamic_stream_reset (&di->us);
5207         mono_dynamic_stream_reset (&di->blob);
5208         mono_dynamic_stream_reset (&di->tstream);
5209         mono_dynamic_stream_reset (&di->guid);
5210         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5211                 g_free (di->tables [i].values);
5212         }
5213 }       
5214
5215 #ifndef DISABLE_REFLECTION_EMIT
5216
5217 /*
5218  * mono_image_basic_init:
5219  * @assembly: an assembly builder object
5220  *
5221  * Create the MonoImage that represents the assembly builder and setup some
5222  * of the helper hash table and the basic metadata streams.
5223  */
5224 void
5225 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5226 {
5227         MonoDynamicAssembly *assembly;
5228         MonoDynamicImage *image;
5229         MonoDomain *domain = mono_object_domain (assemblyb);
5230         
5231         MONO_ARCH_SAVE_REGS;
5232
5233         if (assemblyb->dynamic_assembly)
5234                 return;
5235
5236 #if HAVE_BOEHM_GC
5237         /* assembly->assembly.image might be GC allocated */
5238         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5239 #else
5240         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5241 #endif
5242
5243         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5244         
5245         assembly->assembly.ref_count = 1;
5246         assembly->assembly.dynamic = TRUE;
5247         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5248         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5249         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5250         if (assemblyb->culture)
5251                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5252         else
5253                 assembly->assembly.aname.culture = g_strdup ("");
5254
5255         if (assemblyb->version) {
5256                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5257                         char **version = g_strsplit (vstr, ".", 4);
5258                         char **parts = version;
5259                         assembly->assembly.aname.major = atoi (*parts++);
5260                         assembly->assembly.aname.minor = atoi (*parts++);
5261                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5262                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5263
5264                         g_strfreev (version);
5265                         g_free (vstr);
5266         } else {
5267                         assembly->assembly.aname.major = 0;
5268                         assembly->assembly.aname.minor = 0;
5269                         assembly->assembly.aname.build = 0;
5270                         assembly->assembly.aname.revision = 0;
5271         }
5272
5273         assembly->run = assemblyb->access != 2;
5274         assembly->save = assemblyb->access != 1;
5275         assembly->domain = domain;
5276
5277         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5278         image->initial_image = TRUE;
5279         assembly->assembly.aname.name = image->image.name;
5280         assembly->assembly.image = &image->image;
5281         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5282                 /* -1 to correct for the trailing NULL byte */
5283                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5284                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5285                 }
5286                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5287         }
5288
5289         mono_domain_assemblies_lock (domain);
5290         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5291         mono_domain_assemblies_unlock (domain);
5292
5293         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5294         
5295         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5296         
5297         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5298 }
5299
5300 #endif /* !DISABLE_REFLECTION_EMIT */
5301
5302 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5303
5304 static int
5305 calc_section_size (MonoDynamicImage *assembly)
5306 {
5307         int nsections = 0;
5308
5309         /* alignment constraints */
5310         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5311         g_assert ((assembly->code.index % 4) == 0);
5312         assembly->meta_size += 3;
5313         assembly->meta_size &= ~3;
5314         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5315         g_assert ((assembly->resources.index % 4) == 0);
5316
5317         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5318         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5319         nsections++;
5320
5321         if (assembly->win32_res) {
5322                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5323
5324                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5325                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5326                 nsections++;
5327         }
5328
5329         assembly->sections [MONO_SECTION_RELOC].size = 12;
5330         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5331         nsections++;
5332
5333         return nsections;
5334 }
5335
5336 typedef struct {
5337         guint32 id;
5338         guint32 offset;
5339         GSList *children;
5340         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5341 } ResTreeNode;
5342
5343 static int
5344 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5345 {
5346         ResTreeNode *t1 = (ResTreeNode*)a;
5347         ResTreeNode *t2 = (ResTreeNode*)b;
5348
5349         return t1->id - t2->id;
5350 }
5351
5352 /*
5353  * resource_tree_create:
5354  *
5355  *  Organize the resources into a resource tree.
5356  */
5357 static ResTreeNode *
5358 resource_tree_create (MonoArray *win32_resources)
5359 {
5360         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5361         GSList *l;
5362         int i;
5363
5364         tree = g_new0 (ResTreeNode, 1);
5365         
5366         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5367                 MonoReflectionWin32Resource *win32_res =
5368                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5369
5370                 /* Create node */
5371
5372                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5373                 lang_node = g_new0 (ResTreeNode, 1);
5374                 lang_node->id = win32_res->lang_id;
5375                 lang_node->win32_res = win32_res;
5376
5377                 /* Create type node if neccesary */
5378                 type_node = NULL;
5379                 for (l = tree->children; l; l = l->next)
5380                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5381                                 type_node = (ResTreeNode*)l->data;
5382                                 break;
5383                         }
5384
5385                 if (!type_node) {
5386                         type_node = g_new0 (ResTreeNode, 1);
5387                         type_node->id = win32_res->res_type;
5388
5389                         /* 
5390                          * The resource types have to be sorted otherwise
5391                          * Windows Explorer can't display the version information.
5392                          */
5393                         tree->children = g_slist_insert_sorted (tree->children, 
5394                                 type_node, resource_tree_compare_by_id);
5395                 }
5396
5397                 /* Create res node if neccesary */
5398                 res_node = NULL;
5399                 for (l = type_node->children; l; l = l->next)
5400                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5401                                 res_node = (ResTreeNode*)l->data;
5402                                 break;
5403                         }
5404
5405                 if (!res_node) {
5406                         res_node = g_new0 (ResTreeNode, 1);
5407                         res_node->id = win32_res->res_id;
5408                         type_node->children = g_slist_append (type_node->children, res_node);
5409                 }
5410
5411                 res_node->children = g_slist_append (res_node->children, lang_node);
5412         }
5413
5414         return tree;
5415 }
5416
5417 /*
5418  * resource_tree_encode:
5419  * 
5420  *   Encode the resource tree into the format used in the PE file.
5421  */
5422 static void
5423 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5424 {
5425         char *entries;
5426         MonoPEResourceDir dir;
5427         MonoPEResourceDirEntry dir_entry;
5428         MonoPEResourceDataEntry data_entry;
5429         GSList *l;
5430         guint32 res_id_entries;
5431
5432         /*
5433          * For the format of the resource directory, see the article
5434          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5435          * Matt Pietrek
5436          */
5437
5438         memset (&dir, 0, sizeof (dir));
5439         memset (&dir_entry, 0, sizeof (dir_entry));
5440         memset (&data_entry, 0, sizeof (data_entry));
5441
5442         g_assert (sizeof (dir) == 16);
5443         g_assert (sizeof (dir_entry) == 8);
5444         g_assert (sizeof (data_entry) == 16);
5445
5446         node->offset = p - begin;
5447
5448         /* IMAGE_RESOURCE_DIRECTORY */
5449         res_id_entries = g_slist_length (node->children);
5450         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5451
5452         memcpy (p, &dir, sizeof (dir));
5453         p += sizeof (dir);
5454
5455         /* Reserve space for entries */
5456         entries = p;
5457         p += sizeof (dir_entry) * res_id_entries;
5458
5459         /* Write children */
5460         for (l = node->children; l; l = l->next) {
5461                 ResTreeNode *child = (ResTreeNode*)l->data;
5462
5463                 if (child->win32_res) {
5464                         guint32 size;
5465
5466                         child->offset = p - begin;
5467
5468                         /* IMAGE_RESOURCE_DATA_ENTRY */
5469                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5470                         size = mono_array_length (child->win32_res->res_data);
5471                         data_entry.rde_size = GUINT32_TO_LE (size);
5472
5473                         memcpy (p, &data_entry, sizeof (data_entry));
5474                         p += sizeof (data_entry);
5475
5476                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5477                         p += size;
5478                 } else {
5479                         resource_tree_encode (child, begin, p, &p);
5480                 }
5481         }
5482
5483         /* IMAGE_RESOURCE_ENTRY */
5484         for (l = node->children; l; l = l->next) {
5485                 ResTreeNode *child = (ResTreeNode*)l->data;
5486
5487                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5488                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5489
5490                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5491                 entries += sizeof (dir_entry);
5492         }
5493
5494         *endbuf = p;
5495 }
5496
5497 static void
5498 resource_tree_free (ResTreeNode * node)
5499 {
5500         GSList * list;
5501         for (list = node->children; list; list = list->next)
5502                 resource_tree_free ((ResTreeNode*)list->data);
5503         g_slist_free(node->children);
5504         g_free (node);
5505 }
5506
5507 static void
5508 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5509 {
5510         char *buf;
5511         char *p;
5512         guint32 size, i;
5513         MonoReflectionWin32Resource *win32_res;
5514         ResTreeNode *tree;
5515
5516         if (!assemblyb->win32_resources)
5517                 return;
5518
5519         /*
5520          * Resources are stored in a three level tree inside the PE file.
5521          * - level one contains a node for each type of resource
5522          * - level two contains a node for each resource
5523          * - level three contains a node for each instance of a resource for a
5524          *   specific language.
5525          */
5526
5527         tree = resource_tree_create (assemblyb->win32_resources);
5528
5529         /* Estimate the size of the encoded tree */
5530         size = 0;
5531         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5532                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5533                 size += mono_array_length (win32_res->res_data);
5534         }
5535         /* Directory structure */
5536         size += mono_array_length (assemblyb->win32_resources) * 256;
5537         p = buf = g_malloc (size);
5538
5539         resource_tree_encode (tree, p, p, &p);
5540
5541         g_assert (p - buf <= size);
5542
5543         assembly->win32_res = g_malloc (p - buf);
5544         assembly->win32_res_size = p - buf;
5545         memcpy (assembly->win32_res, buf, p - buf);
5546
5547         g_free (buf);
5548         resource_tree_free (tree);
5549 }
5550
5551 static void
5552 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5553 {
5554         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5555         int i;
5556
5557         p += sizeof (MonoPEResourceDir);
5558         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5559                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5560                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5561                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5562                         fixup_resource_directory (res_section, child, rva);
5563                 } else {
5564                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5565                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5566                 }
5567
5568                 p += sizeof (MonoPEResourceDirEntry);
5569         }
5570 }
5571
5572 static void
5573 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5574 {
5575         guint32 dummy;
5576         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5577                 g_error ("WriteFile returned %d\n", GetLastError ());
5578 }
5579
5580 /*
5581  * mono_image_create_pefile:
5582  * @mb: a module builder object
5583  * 
5584  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5585  * assembly->pefile where it can be easily retrieved later in chunks.
5586  */
5587 void
5588 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5589 {
5590         MonoMSDOSHeader *msdos;
5591         MonoDotNetHeader *header;
5592         MonoSectionTable *section;
5593         MonoCLIHeader *cli_header;
5594         guint32 size, image_size, virtual_base, text_offset;
5595         guint32 header_start, section_start, file_offset, virtual_offset;
5596         MonoDynamicImage *assembly;
5597         MonoReflectionAssemblyBuilder *assemblyb;
5598         MonoDynamicStream pefile_stream = {0};
5599         MonoDynamicStream *pefile = &pefile_stream;
5600         int i, nsections;
5601         guint32 *rva, value;
5602         guchar *p;
5603         static const unsigned char msheader[] = {
5604                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5605                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5606                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5607                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5608                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5609                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5610                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5611                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5612         };
5613
5614         assemblyb = mb->assemblyb;
5615
5616         mono_image_basic_init (assemblyb);
5617         assembly = mb->dynamic_image;
5618
5619         assembly->pe_kind = assemblyb->pe_kind;
5620         assembly->machine = assemblyb->machine;
5621         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5622         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5623         
5624         mono_image_build_metadata (mb);
5625
5626         if (mb->is_main && assemblyb->resources) {
5627                 int len = mono_array_length (assemblyb->resources);
5628                 for (i = 0; i < len; ++i)
5629                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5630         }
5631
5632         if (mb->resources) {
5633                 int len = mono_array_length (mb->resources);
5634                 for (i = 0; i < len; ++i)
5635                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5636         }
5637
5638         build_compressed_metadata (assembly);
5639
5640         if (mb->is_main)
5641                 assembly_add_win32_resources (assembly, assemblyb);
5642
5643         nsections = calc_section_size (assembly);
5644         
5645         /* The DOS header and stub */
5646         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5647         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5648
5649         /* the dotnet header */
5650         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5651
5652         /* the section tables */
5653         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5654
5655         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5656         virtual_offset = VIRT_ALIGN;
5657         image_size = 0;
5658
5659         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5660                 if (!assembly->sections [i].size)
5661                         continue;
5662                 /* align offsets */
5663                 file_offset += FILE_ALIGN - 1;
5664                 file_offset &= ~(FILE_ALIGN - 1);
5665                 virtual_offset += VIRT_ALIGN - 1;
5666                 virtual_offset &= ~(VIRT_ALIGN - 1);
5667
5668                 assembly->sections [i].offset = file_offset;
5669                 assembly->sections [i].rva = virtual_offset;
5670
5671                 file_offset += assembly->sections [i].size;
5672                 virtual_offset += assembly->sections [i].size;
5673                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5674         }
5675
5676         file_offset += FILE_ALIGN - 1;
5677         file_offset &= ~(FILE_ALIGN - 1);
5678
5679         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5680
5681         /* back-patch info */
5682         msdos = (MonoMSDOSHeader*)pefile->data;
5683         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5684
5685         header = (MonoDotNetHeader*)(pefile->data + header_start);
5686         header->pesig [0] = 'P';
5687         header->pesig [1] = 'E';
5688         
5689         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5690         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5691         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5692         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5693         if (assemblyb->pekind == 1) {
5694                 /* it's a dll */
5695                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5696         } else {
5697                 /* it's an exe */
5698                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5699         }
5700
5701         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5702
5703         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5704         header->pe.pe_major = 6;
5705         header->pe.pe_minor = 0;
5706         size = assembly->sections [MONO_SECTION_TEXT].size;
5707         size += FILE_ALIGN - 1;
5708         size &= ~(FILE_ALIGN - 1);
5709         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5710         size = assembly->sections [MONO_SECTION_RSRC].size;
5711         size += FILE_ALIGN - 1;
5712         size &= ~(FILE_ALIGN - 1);
5713         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5714         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5715         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5716         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5717         /* pe_rva_entry_point always at the beginning of the text section */
5718         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5719
5720         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5721         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5722         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5723         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5724         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5725         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5726         size = section_start;
5727         size += FILE_ALIGN - 1;
5728         size &= ~(FILE_ALIGN - 1);
5729         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5730         size = image_size;
5731         size += VIRT_ALIGN - 1;
5732         size &= ~(VIRT_ALIGN - 1);
5733         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5734
5735         /*
5736         // Translate the PEFileKind value to the value expected by the Windows loader
5737         */
5738         {
5739                 short kind;
5740
5741                 /*
5742                 // PEFileKinds.Dll == 1
5743                 // PEFileKinds.ConsoleApplication == 2
5744                 // PEFileKinds.WindowApplication == 3
5745                 //
5746                 // need to get:
5747                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5748                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5749                 */
5750                 if (assemblyb->pekind == 3)
5751                         kind = 2;
5752                 else
5753                         kind = 3;
5754                 
5755                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5756         }    
5757         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5758         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5759         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5760         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5761         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5762         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5763
5764         /* fill data directory entries */
5765
5766         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5767         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5768
5769         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5770         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5771
5772         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5773         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5774         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5775         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5776         /* patch entrypoint name */
5777         if (assemblyb->pekind == 1)
5778                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5779         else
5780                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5781         /* patch imported function RVA name */
5782         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5783         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5784
5785         /* the import table */
5786         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5787         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5788         /* patch imported dll RVA name and other entries in the dir */
5789         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5790         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5791         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5792         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5793         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5794         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5795
5796         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5797         value = (assembly->text_rva + assembly->imp_names_offset);
5798         *p++ = (value) & 0xff;
5799         *p++ = (value >> 8) & (0xff);
5800         *p++ = (value >> 16) & (0xff);
5801         *p++ = (value >> 24) & (0xff);
5802
5803         /* the CLI header info */
5804         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5805         cli_header->ch_size = GUINT32_FROM_LE (72);
5806         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5807         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5808         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5809         if (assemblyb->entry_point) {
5810                 guint32 table_idx = 0;
5811                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5812                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5813                         table_idx = methodb->table_idx;
5814                 } else {
5815                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5816                 }
5817                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5818         } else {
5819                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5820         }
5821         /* The embedded managed resources */
5822         text_offset = assembly->text_rva + assembly->code.index;
5823         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5824         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5825         text_offset += assembly->resources.index;
5826         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5827         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5828         text_offset += assembly->meta_size;
5829         if (assembly->strong_name_size) {
5830                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5831                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5832                 text_offset += assembly->strong_name_size;
5833         }
5834
5835         /* write the section tables and section content */
5836         section = (MonoSectionTable*)(pefile->data + section_start);
5837         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5838                 static const char section_names [][7] = {
5839                         ".text", ".rsrc", ".reloc"
5840                 };
5841                 if (!assembly->sections [i].size)
5842                         continue;
5843                 strcpy (section->st_name, section_names [i]);
5844                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5845                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5846                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5847                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5848                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5849                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5850                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5851                 section ++;
5852         }
5853         
5854         checked_write_file (file, pefile->data, pefile->index);
5855         
5856         mono_dynamic_stream_reset (pefile);
5857         
5858         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5859                 if (!assembly->sections [i].size)
5860                         continue;
5861                 
5862                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5863                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5864                 
5865                 switch (i) {
5866                 case MONO_SECTION_TEXT:
5867                         /* patch entry point */
5868                         p = (guchar*)(assembly->code.data + 2);
5869                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5870                         *p++ = (value) & 0xff;
5871                         *p++ = (value >> 8) & 0xff;
5872                         *p++ = (value >> 16) & 0xff;
5873                         *p++ = (value >> 24) & 0xff;
5874                 
5875                         checked_write_file (file, assembly->code.data, assembly->code.index);
5876                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5877                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5878                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5879                                 
5880
5881                         g_free (assembly->image.raw_metadata);
5882                         break;
5883                 case MONO_SECTION_RELOC: {
5884                         struct {
5885                                 guint32 page_rva;
5886                                 guint32 block_size;
5887                                 guint16 type_and_offset;
5888                                 guint16 term;
5889                         } reloc;
5890                         
5891                         g_assert (sizeof (reloc) == 12);
5892                         
5893                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5894                         reloc.block_size = GUINT32_FROM_LE (12);
5895                         
5896                         /* 
5897                          * the entrypoint is always at the start of the text section 
5898                          * 3 is IMAGE_REL_BASED_HIGHLOW
5899                          * 2 is patch_size_rva - text_rva
5900                          */
5901                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5902                         reloc.term = 0;
5903                         
5904                         checked_write_file (file, &reloc, sizeof (reloc));
5905                         
5906                         break;
5907                 }
5908                 case MONO_SECTION_RSRC:
5909                         if (assembly->win32_res) {
5910
5911                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5912                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5913                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5914                         }
5915                         break;
5916                 default:
5917                         g_assert_not_reached ();
5918                 }
5919         }
5920         
5921         /* check that the file is properly padded */
5922         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5923                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5924         if (! SetEndOfFile (file))
5925                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5926         
5927         mono_dynamic_stream_reset (&assembly->code);
5928         mono_dynamic_stream_reset (&assembly->us);
5929         mono_dynamic_stream_reset (&assembly->blob);
5930         mono_dynamic_stream_reset (&assembly->guid);
5931         mono_dynamic_stream_reset (&assembly->sheap);
5932
5933         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5934         g_hash_table_destroy (assembly->blob_cache);
5935         assembly->blob_cache = NULL;
5936 }
5937
5938 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5939
5940 void
5941 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5942 {
5943         g_assert_not_reached ();
5944 }
5945
5946 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5947
5948 #ifndef DISABLE_REFLECTION_EMIT
5949
5950 MonoReflectionModule *
5951 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5952 {
5953         char *name;
5954         MonoImage *image;
5955         MonoImageOpenStatus status;
5956         MonoDynamicAssembly *assembly;
5957         guint32 module_count;
5958         MonoImage **new_modules;
5959         gboolean *new_modules_loaded;
5960         
5961         name = mono_string_to_utf8 (fileName);
5962
5963         image = mono_image_open (name, &status);
5964         if (!image) {
5965                 MonoException *exc;
5966                 if (status == MONO_IMAGE_ERROR_ERRNO)
5967                         exc = mono_get_exception_file_not_found (fileName);
5968                 else
5969                         exc = mono_get_exception_bad_image_format (name);
5970                 g_free (name);
5971                 mono_raise_exception (exc);
5972         }
5973
5974         g_free (name);
5975
5976         assembly = ab->dynamic_assembly;
5977         image->assembly = (MonoAssembly*)assembly;
5978
5979         module_count = image->assembly->image->module_count;
5980         new_modules = g_new0 (MonoImage *, module_count + 1);
5981         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5982
5983         if (image->assembly->image->modules)
5984                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5985         if (image->assembly->image->modules_loaded)
5986                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5987         new_modules [module_count] = image;
5988         new_modules_loaded [module_count] = TRUE;
5989         mono_image_addref (image);
5990
5991         g_free (image->assembly->image->modules);
5992         image->assembly->image->modules = new_modules;
5993         image->assembly->image->modules_loaded = new_modules_loaded;
5994         image->assembly->image->module_count ++;
5995
5996         mono_assembly_load_references (image, &status);
5997         if (status) {
5998                 mono_image_close (image);
5999                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6000         }
6001
6002         return mono_module_get_object (mono_domain_get (), image);
6003 }
6004
6005 #endif /* DISABLE_REFLECTION_EMIT */
6006
6007 /*
6008  * We need to return always the same object for MethodInfo, FieldInfo etc..
6009  * but we need to consider the reflected type.
6010  * type uses a different hash, since it uses custom hash/equal functions.
6011  */
6012
6013 typedef struct {
6014         gpointer item;
6015         MonoClass *refclass;
6016 } ReflectedEntry;
6017
6018 static gboolean
6019 reflected_equal (gconstpointer a, gconstpointer b) {
6020         const ReflectedEntry *ea = a;
6021         const ReflectedEntry *eb = b;
6022
6023         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6024 }
6025
6026 static guint
6027 reflected_hash (gconstpointer a) {
6028         const ReflectedEntry *ea = a;
6029         return mono_aligned_addr_hash (ea->item);
6030 }
6031
6032 #define CHECK_OBJECT(t,p,k)     \
6033         do {    \
6034                 t _obj; \
6035                 ReflectedEntry e;       \
6036                 e.item = (p);   \
6037                 e.refclass = (k);       \
6038                 mono_domain_lock (domain);      \
6039                 if (!domain->refobject_hash)    \
6040                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6041                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6042                         mono_domain_unlock (domain);    \
6043                         return _obj;    \
6044                 }       \
6045         mono_domain_unlock (domain); \
6046         } while (0)
6047
6048 #ifdef HAVE_BOEHM_GC
6049 /* ReflectedEntry doesn't need to be GC tracked */
6050 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6051 #define FREE_REFENTRY(entry) g_free ((entry))
6052 #define REFENTRY_REQUIRES_CLEANUP
6053 #else
6054 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6055 /* FIXME: */
6056 #define FREE_REFENTRY(entry)
6057 #endif
6058
6059 #define CACHE_OBJECT(t,p,o,k)   \
6060         do {    \
6061                 t _obj; \
6062         ReflectedEntry pe; \
6063         pe.item = (p); \
6064         pe.refclass = (k); \
6065         mono_domain_lock (domain); \
6066                 if (!domain->refobject_hash)    \
6067                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6068         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6069         if (!_obj) { \
6070                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6071                     e->item = (p);      \
6072                     e->refclass = (k);  \
6073                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6074             _obj = o; \
6075         } \
6076                 mono_domain_unlock (domain);    \
6077         return _obj; \
6078         } while (0)
6079
6080 static void
6081 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6082 {
6083         mono_domain_lock (domain);
6084         if (domain->refobject_hash) {
6085         ReflectedEntry pe;
6086                 gpointer orig_pe, orig_value;
6087
6088                 pe.item = o;
6089                 pe.refclass = klass;
6090                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6091                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6092                         FREE_REFENTRY (orig_pe);
6093                 }
6094         }
6095         mono_domain_unlock (domain);
6096 }
6097
6098 #ifdef REFENTRY_REQUIRES_CLEANUP
6099 static void
6100 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6101 {
6102         FREE_REFENTRY (key);
6103 }
6104 #endif
6105
6106 void
6107 mono_reflection_cleanup_domain (MonoDomain *domain)
6108 {
6109         if (domain->refobject_hash) {
6110 /*let's avoid scanning the whole hashtable if not needed*/
6111 #ifdef REFENTRY_REQUIRES_CLEANUP
6112                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6113 #endif
6114                 mono_g_hash_table_destroy (domain->refobject_hash);
6115                 domain->refobject_hash = NULL;
6116         }
6117 }
6118
6119 #ifndef DISABLE_REFLECTION_EMIT
6120 static gpointer
6121 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6122 {
6123         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6124 }
6125
6126 static gpointer
6127 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6128 {
6129         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6130 }
6131
6132 void
6133 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6134 {
6135         MonoDynamicImage *image = moduleb->dynamic_image;
6136         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6137         if (!image) {
6138                 MonoError error;
6139                 int module_count;
6140                 MonoImage **new_modules;
6141                 MonoImage *ass;
6142                 char *name, *fqname;
6143                 /*
6144                  * FIXME: we already created an image in mono_image_basic_init (), but
6145                  * we don't know which module it belongs to, since that is only 
6146                  * determined at assembly save time.
6147                  */
6148                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6149                 name = mono_string_to_utf8 (ab->name);
6150                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6151                 if (!mono_error_ok (&error)) {
6152                         g_free (name);
6153                         mono_error_raise_exception (&error);
6154                 }
6155                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6156
6157                 moduleb->module.image = &image->image;
6158                 moduleb->dynamic_image = image;
6159                 register_module (mono_object_domain (moduleb), moduleb, image);
6160
6161                 /* register the module with the assembly */
6162                 ass = ab->dynamic_assembly->assembly.image;
6163                 module_count = ass->module_count;
6164                 new_modules = g_new0 (MonoImage *, module_count + 1);
6165
6166                 if (ass->modules)
6167                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6168                 new_modules [module_count] = &image->image;
6169                 mono_image_addref (&image->image);
6170
6171                 g_free (ass->modules);
6172                 ass->modules = new_modules;
6173                 ass->module_count ++;
6174         }
6175 }
6176
6177 void
6178 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6179 {
6180         MonoDynamicImage *image = moduleb->dynamic_image;
6181
6182         g_assert (type->type);
6183         image->wrappers_type = mono_class_from_mono_type (type->type);
6184 }
6185
6186 #endif
6187
6188 /*
6189  * mono_assembly_get_object:
6190  * @domain: an app domain
6191  * @assembly: an assembly
6192  *
6193  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6194  */
6195 MonoReflectionAssembly*
6196 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6197 {
6198         static MonoClass *assembly_type;
6199         MonoReflectionAssembly *res;
6200         
6201         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6202         if (!assembly_type) {
6203                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6204                 if (class == NULL)
6205                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6206                 g_assert (class);
6207                 assembly_type = class;
6208         }
6209         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6210         res->assembly = assembly;
6211
6212         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6213 }
6214
6215
6216
6217 MonoReflectionModule*   
6218 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6219 {
6220         static MonoClass *module_type;
6221         MonoReflectionModule *res;
6222         char* basename;
6223         
6224         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6225         if (!module_type) {
6226                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6227                 if (class == NULL)
6228                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6229                 g_assert (class);
6230                 module_type = class;
6231         }
6232         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6233
6234         res->image = image;
6235         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6236
6237         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6238         basename = g_path_get_basename (image->name);
6239         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6240         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6241         
6242         g_free (basename);
6243
6244         if (image->assembly->image == image) {
6245                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6246         } else {
6247                 int i;
6248                 res->token = 0;
6249                 if (image->assembly->image->modules) {
6250                         for (i = 0; i < image->assembly->image->module_count; i++) {
6251                                 if (image->assembly->image->modules [i] == image)
6252                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6253                         }
6254                         g_assert (res->token);
6255                 }
6256         }
6257
6258         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6259 }
6260
6261 MonoReflectionModule*   
6262 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6263 {
6264         static MonoClass *module_type;
6265         MonoReflectionModule *res;
6266         MonoTableInfo *table;
6267         guint32 cols [MONO_FILE_SIZE];
6268         const char *name;
6269         guint32 i, name_idx;
6270         const char *val;
6271         
6272         if (!module_type) {
6273                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6274                 if (class == NULL)
6275                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6276                 g_assert (class);
6277                 module_type = class;
6278         }
6279         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6280
6281         table = &image->tables [MONO_TABLE_FILE];
6282         g_assert (table_index < table->rows);
6283         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6284
6285         res->image = NULL;
6286         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6287         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6288
6289         /* Check whenever the row has a corresponding row in the moduleref table */
6290         table = &image->tables [MONO_TABLE_MODULEREF];
6291         for (i = 0; i < table->rows; ++i) {
6292                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6293                 val = mono_metadata_string_heap (image, name_idx);
6294                 if (strcmp (val, name) == 0)
6295                         res->image = image->modules [i];
6296         }
6297
6298         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6299         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6300         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6301         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6302         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6303
6304         return res;
6305 }
6306
6307 static gboolean
6308 verify_safe_for_managed_space (MonoType *type)
6309 {
6310         switch (type->type) {
6311 #ifdef DEBUG_HARDER
6312         case MONO_TYPE_ARRAY:
6313                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6314         case MONO_TYPE_PTR:
6315                 return verify_safe_for_managed_space (type->data.type);
6316         case MONO_TYPE_SZARRAY:
6317                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6318         case MONO_TYPE_GENERICINST: {
6319                 MonoGenericInst *inst = type->data.generic_class->inst;
6320                 int i;
6321                 if (!inst->is_open)
6322                         break;
6323                 for (i = 0; i < inst->type_argc; ++i)
6324                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6325                                 return FALSE;
6326                 break;
6327         }
6328 #endif
6329         case MONO_TYPE_VAR:
6330         case MONO_TYPE_MVAR:
6331                 return TRUE;
6332         }
6333         return TRUE;
6334 }
6335
6336 static MonoType*
6337 mono_type_normalize (MonoType *type)
6338 {
6339         int i;
6340         MonoGenericClass *gclass;
6341         MonoGenericInst *ginst;
6342         MonoClass *gtd;
6343         MonoGenericContainer *gcontainer;
6344         MonoType **argv = NULL;
6345         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6346
6347         if (type->type != MONO_TYPE_GENERICINST)
6348                 return type;
6349
6350         gclass = type->data.generic_class;
6351         ginst = gclass->context.class_inst;
6352         if (!ginst->is_open)
6353                 return type;
6354
6355         gtd = gclass->container_class;
6356         gcontainer = gtd->generic_container;
6357         argv = g_newa (MonoType*, ginst->type_argc);
6358
6359         for (i = 0; i < ginst->type_argc; ++i) {
6360                 MonoType *t = ginst->type_argv [i], *norm;
6361                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6362                         is_denorm_gtd = FALSE;
6363                 norm = mono_type_normalize (t);
6364                 argv [i] = norm;
6365                 if (norm != t)
6366                         requires_rebind = TRUE;
6367         }
6368
6369         if (is_denorm_gtd)
6370                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6371
6372         if (requires_rebind) {
6373                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6374                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6375         }
6376
6377         return type;
6378 }
6379 /*
6380  * mono_type_get_object:
6381  * @domain: an app domain
6382  * @type: a type
6383  *
6384  * Return an System.MonoType object representing the type @type.
6385  */
6386 MonoReflectionType*
6387 mono_type_get_object (MonoDomain *domain, MonoType *type)
6388 {
6389         MonoType *norm_type;
6390         MonoReflectionType *res;
6391         MonoClass *klass = mono_class_from_mono_type (type);
6392
6393         /*we must avoid using @type as it might have come
6394          * from a mono_metadata_type_dup and the caller
6395          * expects that is can be freed.
6396          * Using the right type from 
6397          */
6398         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6399
6400         /* void is very common */
6401         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6402                 return (MonoReflectionType*)domain->typeof_void;
6403
6404         /*
6405          * If the vtable of the given class was already created, we can use
6406          * the MonoType from there and avoid all locking and hash table lookups.
6407          * 
6408          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6409          * that the resulting object is different.   
6410          */
6411         if (type == &klass->byval_arg && !klass->image->dynamic) {
6412                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6413                 if (vtable && vtable->type)
6414                         return vtable->type;
6415         }
6416
6417         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6418         mono_domain_lock (domain);
6419         if (!domain->type_hash)
6420                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6421                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6422         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6423                 mono_domain_unlock (domain);
6424                 mono_loader_unlock ();
6425                 return res;
6426         }
6427
6428         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6429          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6430          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6431          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6432          * artifact of how generics are encoded and should be transparent to managed code so we
6433          * need to weed out this diference when retrieving managed System.Type objects.
6434          */
6435         norm_type = mono_type_normalize (type);
6436         if (norm_type != type) {
6437                 res = mono_type_get_object (domain, norm_type);
6438                 mono_g_hash_table_insert (domain->type_hash, type, res);
6439                 mono_domain_unlock (domain);
6440                 mono_loader_unlock ();
6441                 return res;
6442         }
6443
6444         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6445         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6446                 g_assert (0);
6447
6448         if (!verify_safe_for_managed_space (type)) {
6449                 mono_domain_unlock (domain);
6450                 mono_loader_unlock ();
6451                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6452         }
6453
6454         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6455                 gboolean is_type_done = TRUE;
6456                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6457                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6458                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6459                 */
6460                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6461                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6462
6463                         if (gparam->owner && gparam->owner->is_method) {
6464                                 MonoMethod *method = gparam->owner->owner.method;
6465                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6466                                         is_type_done = FALSE;
6467                         } else if (gparam->owner && !gparam->owner->is_method) {
6468                                 MonoClass *klass = gparam->owner->owner.klass;
6469                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6470                                         is_type_done = FALSE;
6471                         }
6472                 } 
6473
6474                 /* g_assert_not_reached (); */
6475                 /* should this be considered an error condition? */
6476                 if (is_type_done && !type->byref) {
6477                         mono_domain_unlock (domain);
6478                         mono_loader_unlock ();
6479                         return mono_class_get_ref_info (klass);
6480                 }
6481         }
6482         /* This is stored in vtables/JITted code so it has to be pinned */
6483         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6484         res->type = type;
6485         mono_g_hash_table_insert (domain->type_hash, type, res);
6486
6487         if (type->type == MONO_TYPE_VOID)
6488                 domain->typeof_void = (MonoObject*)res;
6489
6490         mono_domain_unlock (domain);
6491         mono_loader_unlock ();
6492         return res;
6493 }
6494
6495 /*
6496  * mono_method_get_object:
6497  * @domain: an app domain
6498  * @method: a method
6499  * @refclass: the reflected type (can be NULL)
6500  *
6501  * Return an System.Reflection.MonoMethod object representing the method @method.
6502  */
6503 MonoReflectionMethod*
6504 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6505 {
6506         /*
6507          * We use the same C representation for methods and constructors, but the type 
6508          * name in C# is different.
6509          */
6510         static MonoClass *System_Reflection_MonoMethod = NULL;
6511         static MonoClass *System_Reflection_MonoCMethod = NULL;
6512         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6513         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6514         MonoClass *klass;
6515         MonoReflectionMethod *ret;
6516
6517         if (method->is_inflated) {
6518                 MonoReflectionGenericMethod *gret;
6519
6520                 refclass = method->klass;
6521                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6522                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6523                         if (!System_Reflection_MonoGenericCMethod)
6524                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6525                         klass = System_Reflection_MonoGenericCMethod;
6526                 } else {
6527                         if (!System_Reflection_MonoGenericMethod)
6528                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6529                         klass = System_Reflection_MonoGenericMethod;
6530                 }
6531                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6532                 gret->method.method = method;
6533                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6534                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6535                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6536         }
6537
6538         if (!refclass)
6539                 refclass = method->klass;
6540
6541         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6542         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6543                 if (!System_Reflection_MonoCMethod)
6544                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6545                 klass = System_Reflection_MonoCMethod;
6546         }
6547         else {
6548                 if (!System_Reflection_MonoMethod)
6549                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6550                 klass = System_Reflection_MonoMethod;
6551         }
6552         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6553         ret->method = method;
6554         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6555         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6556 }
6557
6558 /*
6559  * mono_method_clear_object:
6560  *
6561  *   Clear the cached reflection objects for the dynamic method METHOD.
6562  */
6563 void
6564 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6565 {
6566         MonoClass *klass;
6567         g_assert (method->dynamic);
6568
6569         klass = method->klass;
6570         while (klass) {
6571                 clear_cached_object (domain, method, klass);
6572                 klass = klass->parent;
6573         }
6574         /* Added by mono_param_get_objects () */
6575         clear_cached_object (domain, &(method->signature), NULL);
6576         klass = method->klass;
6577         while (klass) {
6578                 clear_cached_object (domain, &(method->signature), klass);
6579                 klass = klass->parent;
6580         }
6581 }
6582
6583 /*
6584  * mono_field_get_object:
6585  * @domain: an app domain
6586  * @klass: a type
6587  * @field: a field
6588  *
6589  * Return an System.Reflection.MonoField object representing the field @field
6590  * in class @klass.
6591  */
6592 MonoReflectionField*
6593 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6594 {
6595         MonoReflectionField *res;
6596         static MonoClass *monofield_klass;
6597
6598         CHECK_OBJECT (MonoReflectionField *, field, klass);
6599         if (!monofield_klass)
6600                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6601         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6602         res->klass = klass;
6603         res->field = field;
6604         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6605
6606         if (is_field_on_inst (field)) {
6607                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6608                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6609         } else {
6610                 if (field->type)
6611                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6612                 res->attrs = mono_field_get_flags (field);
6613         }
6614         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6615 }
6616
6617 /*
6618  * mono_property_get_object:
6619  * @domain: an app domain
6620  * @klass: a type
6621  * @property: a property
6622  *
6623  * Return an System.Reflection.MonoProperty object representing the property @property
6624  * in class @klass.
6625  */
6626 MonoReflectionProperty*
6627 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6628 {
6629         MonoReflectionProperty *res;
6630         static MonoClass *monoproperty_klass;
6631
6632         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6633         if (!monoproperty_klass)
6634                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6635         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6636         res->klass = klass;
6637         res->property = property;
6638         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6639 }
6640
6641 /*
6642  * mono_event_get_object:
6643  * @domain: an app domain
6644  * @klass: a type
6645  * @event: a event
6646  *
6647  * Return an System.Reflection.MonoEvent object representing the event @event
6648  * in class @klass.
6649  */
6650 MonoReflectionEvent*
6651 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6652 {
6653         MonoReflectionEvent *res;
6654         MonoReflectionMonoEvent *mono_event;
6655         static MonoClass *monoevent_klass;
6656
6657         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6658         if (!monoevent_klass)
6659                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6660         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6661         mono_event->klass = klass;
6662         mono_event->event = event;
6663         res = (MonoReflectionEvent*)mono_event;
6664         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6665 }
6666
6667 /**
6668  * mono_get_reflection_missing_object:
6669  * @domain: Domain where the object lives
6670  *
6671  * Returns the System.Reflection.Missing.Value singleton object
6672  * (of type System.Reflection.Missing).
6673  *
6674  * Used as the value for ParameterInfo.DefaultValue when Optional
6675  * is present
6676  */
6677 static MonoObject *
6678 mono_get_reflection_missing_object (MonoDomain *domain)
6679 {
6680         MonoObject *obj;
6681         static MonoClassField *missing_value_field = NULL;
6682         
6683         if (!missing_value_field) {
6684                 MonoClass *missing_klass;
6685                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6686                 mono_class_init (missing_klass);
6687                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6688                 g_assert (missing_value_field);
6689         }
6690         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6691         g_assert (obj);
6692         return obj;
6693 }
6694
6695 static MonoObject*
6696 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6697 {
6698         if (!*dbnull)
6699                 *dbnull = mono_get_dbnull_object (domain);
6700         return *dbnull;
6701 }
6702
6703 static MonoObject*
6704 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6705 {
6706         if (!*reflection_missing)
6707                 *reflection_missing = mono_get_reflection_missing_object (domain);
6708         return *reflection_missing;
6709 }
6710
6711 /*
6712  * mono_param_get_objects:
6713  * @domain: an app domain
6714  * @method: a method
6715  *
6716  * Return an System.Reflection.ParameterInfo array object representing the parameters
6717  * in the method @method.
6718  */
6719 MonoArray*
6720 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6721 {
6722         static MonoClass *System_Reflection_ParameterInfo;
6723         static MonoClass *System_Reflection_ParameterInfo_array;
6724         MonoError error;
6725         MonoArray *res = NULL;
6726         MonoReflectionMethod *member = NULL;
6727         MonoReflectionParameter *param = NULL;
6728         char **names, **blobs = NULL;
6729         guint32 *types = NULL;
6730         MonoType *type = NULL;
6731         MonoObject *dbnull = NULL;
6732         MonoObject *missing = NULL;
6733         MonoMarshalSpec **mspecs;
6734         MonoMethodSignature *sig;
6735         MonoVTable *pinfo_vtable;
6736         int i;
6737
6738         if (!System_Reflection_ParameterInfo_array) {
6739                 MonoClass *klass;
6740
6741                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6742                 mono_memory_barrier ();
6743                 System_Reflection_ParameterInfo = klass; 
6744         
6745                 klass = mono_array_class_get (klass, 1);
6746                 mono_memory_barrier ();
6747                 System_Reflection_ParameterInfo_array = klass;
6748         }
6749
6750         sig = mono_method_signature_checked (method, &error);
6751         if (!mono_error_ok (&error))
6752                 mono_error_raise_exception (&error);
6753
6754         if (!sig->param_count)
6755                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6756
6757         /* Note: the cache is based on the address of the signature into the method
6758          * since we already cache MethodInfos with the method as keys.
6759          */
6760         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6761
6762         member = mono_method_get_object (domain, method, refclass);
6763         names = g_new (char *, sig->param_count);
6764         mono_method_get_param_names (method, (const char **) names);
6765
6766         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6767         mono_method_get_marshal_info (method, mspecs);
6768
6769         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6770         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6771         for (i = 0; i < sig->param_count; ++i) {
6772                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6773                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6774                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6775                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6776                 param->PositionImpl = i;
6777                 param->AttrsImpl = sig->params [i]->attrs;
6778
6779                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6780                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6781                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6782                         else
6783                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6784                 } else {
6785
6786                         if (!blobs) {
6787                                 blobs = g_new0 (char *, sig->param_count);
6788                                 types = g_new0 (guint32, sig->param_count);
6789                                 get_default_param_value_blobs (method, blobs, types); 
6790                         }
6791
6792                         /* Build MonoType for the type from the Constant Table */
6793                         if (!type)
6794                                 type = g_new0 (MonoType, 1);
6795                         type->type = types [i];
6796                         type->data.klass = NULL;
6797                         if (types [i] == MONO_TYPE_CLASS)
6798                                 type->data.klass = mono_defaults.object_class;
6799                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6800                                 /* For enums, types [i] contains the base type */
6801
6802                                         type->type = MONO_TYPE_VALUETYPE;
6803                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6804                         } else
6805                                 type->data.klass = mono_class_from_mono_type (type);
6806
6807                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6808
6809                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6810                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6811                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6812                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6813                                 else
6814                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6815                         }
6816                         
6817                 }
6818
6819                 if (mspecs [i + 1])
6820                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6821                 
6822                 mono_array_setref (res, i, param);
6823         }
6824         g_free (names);
6825         g_free (blobs);
6826         g_free (types);
6827         g_free (type);
6828
6829         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6830                 if (mspecs [i])
6831                         mono_metadata_free_marshal_spec (mspecs [i]);
6832         g_free (mspecs);
6833         
6834         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6835 }
6836
6837 MonoArray*
6838 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6839 {
6840         return mono_param_get_objects_internal (domain, method, NULL);
6841 }
6842
6843 /*
6844  * mono_method_body_get_object:
6845  * @domain: an app domain
6846  * @method: a method
6847  *
6848  * Return an System.Reflection.MethodBody object representing the method @method.
6849  */
6850 MonoReflectionMethodBody*
6851 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6852 {
6853         static MonoClass *System_Reflection_MethodBody = NULL;
6854         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6855         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6856         MonoReflectionMethodBody *ret;
6857         MonoMethodHeader *header;
6858         MonoImage *image;
6859         guint32 method_rva, local_var_sig_token;
6860     char *ptr;
6861         unsigned char format, flags;
6862         int i;
6863
6864         /* for compatibility with .net */
6865     if (method->dynamic)
6866         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6867
6868         if (!System_Reflection_MethodBody)
6869                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6870         if (!System_Reflection_LocalVariableInfo)
6871                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6872         if (!System_Reflection_ExceptionHandlingClause)
6873                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6874
6875         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6876
6877         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6878                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6879             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6880             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6881                 return NULL;
6882
6883         image = method->klass->image;
6884         header = mono_method_get_header (method);
6885
6886         if (!image->dynamic) {
6887                 /* Obtain local vars signature token */
6888                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6889                 ptr = mono_image_rva_map (image, method_rva);
6890                 flags = *(const unsigned char *) ptr;
6891                 format = flags & METHOD_HEADER_FORMAT_MASK;
6892                 switch (format){
6893                 case METHOD_HEADER_TINY_FORMAT:
6894                         local_var_sig_token = 0;
6895                         break;
6896                 case METHOD_HEADER_FAT_FORMAT:
6897                         ptr += 2;
6898                         ptr += 2;
6899                         ptr += 4;
6900                         local_var_sig_token = read32 (ptr);
6901                         break;
6902                 default:
6903                         g_assert_not_reached ();
6904                 }
6905         } else
6906                 local_var_sig_token = 0; //FIXME
6907
6908         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6909
6910         ret->init_locals = header->init_locals;
6911         ret->max_stack = header->max_stack;
6912         ret->local_var_sig_token = local_var_sig_token;
6913         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6914         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6915
6916         /* Locals */
6917         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6918         for (i = 0; i < header->num_locals; ++i) {
6919                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6920                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6921                 info->is_pinned = header->locals [i]->pinned;
6922                 info->local_index = i;
6923                 mono_array_setref (ret->locals, i, info);
6924         }
6925
6926         /* Exceptions */
6927         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6928         for (i = 0; i < header->num_clauses; ++i) {
6929                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6930                 MonoExceptionClause *clause = &header->clauses [i];
6931
6932                 info->flags = clause->flags;
6933                 info->try_offset = clause->try_offset;
6934                 info->try_length = clause->try_len;
6935                 info->handler_offset = clause->handler_offset;
6936                 info->handler_length = clause->handler_len;
6937                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6938                         info->filter_offset = clause->data.filter_offset;
6939                 else if (clause->data.catch_class)
6940                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6941
6942                 mono_array_setref (ret->clauses, i, info);
6943         }
6944
6945         mono_metadata_free_mh (header);
6946         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6947         return ret;
6948 }
6949
6950 /**
6951  * mono_get_dbnull_object:
6952  * @domain: Domain where the object lives
6953  *
6954  * Returns the System.DBNull.Value singleton object
6955  *
6956  * Used as the value for ParameterInfo.DefaultValue 
6957  */
6958 MonoObject *
6959 mono_get_dbnull_object (MonoDomain *domain)
6960 {
6961         MonoObject *obj;
6962         static MonoClassField *dbnull_value_field = NULL;
6963         
6964         if (!dbnull_value_field) {
6965                 MonoClass *dbnull_klass;
6966                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6967                 mono_class_init (dbnull_klass);
6968                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6969                 g_assert (dbnull_value_field);
6970         }
6971         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
6972         g_assert (obj);
6973         return obj;
6974 }
6975
6976 static void
6977 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6978 {
6979         guint32 param_index, i, lastp, crow = 0;
6980         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6981         gint32 idx;
6982
6983         MonoClass *klass = method->klass;
6984         MonoImage *image = klass->image;
6985         MonoMethodSignature *methodsig = mono_method_signature (method);
6986
6987         MonoTableInfo *constt;
6988         MonoTableInfo *methodt;
6989         MonoTableInfo *paramt;
6990
6991         if (!methodsig->param_count)
6992                 return;
6993
6994         mono_class_init (klass);
6995
6996         if (klass->image->dynamic) {
6997                 MonoReflectionMethodAux *aux;
6998                 if (method->is_inflated)
6999                         method = ((MonoMethodInflated*)method)->declaring;
7000                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7001                 if (aux && aux->param_defaults) {
7002                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7003                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7004                 }
7005                 return;
7006         }
7007
7008         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7009         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7010         constt = &image->tables [MONO_TABLE_CONSTANT];
7011
7012         idx = mono_method_get_index (method) - 1;
7013         g_assert (idx != -1);
7014
7015         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7016         if (idx + 1 < methodt->rows)
7017                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7018         else
7019                 lastp = paramt->rows + 1;
7020
7021         for (i = param_index; i < lastp; ++i) {
7022                 guint32 paramseq;
7023
7024                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7025                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7026
7027                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7028                         continue;
7029
7030                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7031                 if (!crow) {
7032                         continue;
7033                 }
7034         
7035                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7036                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7037                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7038         }
7039
7040         return;
7041 }
7042
7043 MonoObject *
7044 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7045 {
7046         void *retval;
7047         MonoClass *klass;
7048         MonoObject *object;
7049         MonoType *basetype = type;
7050
7051         if (!blob)
7052                 return NULL;
7053         
7054         klass = mono_class_from_mono_type (type);
7055         if (klass->valuetype) {
7056                 object = mono_object_new (domain, klass);
7057                 retval = ((gchar *) object + sizeof (MonoObject));
7058                 if (klass->enumtype)
7059                         basetype = mono_class_enum_basetype (klass);
7060         } else {
7061                 retval = &object;
7062         }
7063                         
7064         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7065                 return object;
7066         else
7067                 return NULL;
7068 }
7069
7070 static int
7071 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7072         int found_sep;
7073         char *s;
7074         gboolean quoted = FALSE;
7075
7076         memset (assembly, 0, sizeof (MonoAssemblyName));
7077         assembly->culture = "";
7078         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7079
7080         if (*p == '"') {
7081                 quoted = TRUE;
7082                 p++;
7083         }
7084         assembly->name = p;
7085         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7086                 p++;
7087         if (quoted) {
7088                 if (*p != '"')
7089                         return 1;
7090                 *p = 0;
7091                 p++;
7092         }
7093         if (*p != ',')
7094                 return 1;
7095         *p = 0;
7096         /* Remove trailing whitespace */
7097         s = p - 1;
7098         while (*s && g_ascii_isspace (*s))
7099                 *s-- = 0;
7100         p ++;
7101         while (g_ascii_isspace (*p))
7102                 p++;
7103         while (*p) {
7104                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7105                         p += 8;
7106                         assembly->major = strtoul (p, &s, 10);
7107                         if (s == p || *s != '.')
7108                                 return 1;
7109                         p = ++s;
7110                         assembly->minor = strtoul (p, &s, 10);
7111                         if (s == p || *s != '.')
7112                                 return 1;
7113                         p = ++s;
7114                         assembly->build = strtoul (p, &s, 10);
7115                         if (s == p || *s != '.')
7116                                 return 1;
7117                         p = ++s;
7118                         assembly->revision = strtoul (p, &s, 10);
7119                         if (s == p)
7120                                 return 1;
7121                         p = s;
7122                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7123                         p += 8;
7124                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7125                                 assembly->culture = "";
7126                                 p += 7;
7127                         } else {
7128                                 assembly->culture = p;
7129                                 while (*p && *p != ',') {
7130                                         p++;
7131                                 }
7132                         }
7133                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7134                         p += 15;
7135                         if (strncmp (p, "null", 4) == 0) {
7136                                 p += 4;
7137                         } else {
7138                                 int len;
7139                                 gchar *start = p;
7140                                 while (*p && *p != ',') {
7141                                         p++;
7142                                 }
7143                                 len = (p - start + 1);
7144                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7145                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7146                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7147                         }
7148                 } else {
7149                         while (*p && *p != ',')
7150                                 p++;
7151                 }
7152                 found_sep = 0;
7153                 while (g_ascii_isspace (*p) || *p == ',') {
7154                         *p++ = 0;
7155                         found_sep = 1;
7156                         continue;
7157                 }
7158                 /* failed */
7159                 if (!found_sep)
7160                         return 1;
7161         }
7162
7163         return 0;
7164 }
7165
7166 /*
7167  * mono_reflection_parse_type:
7168  * @name: type name
7169  *
7170  * Parse a type name as accepted by the GetType () method and output the info
7171  * extracted in the info structure.
7172  * the name param will be mangled, so, make a copy before passing it to this function.
7173  * The fields in info will be valid until the memory pointed to by name is valid.
7174  *
7175  * See also mono_type_get_name () below.
7176  *
7177  * Returns: 0 on parse error.
7178  */
7179 static int
7180 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7181                              MonoTypeNameParse *info)
7182 {
7183         char *start, *p, *w, *temp, *last_point, *startn;
7184         int in_modifiers = 0;
7185         int isbyref = 0, rank, arity = 0, i;
7186
7187         start = p = w = name;
7188
7189         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7190         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7191         info->name = info->name_space = NULL;
7192         info->nested = NULL;
7193         info->modifiers = NULL;
7194         info->type_arguments = NULL;
7195
7196         /* last_point separates the namespace from the name */
7197         last_point = NULL;
7198         /* Skips spaces */
7199         while (*p == ' ') p++, start++, w++, name++;
7200
7201         while (*p) {
7202                 switch (*p) {
7203                 case '+':
7204                         *p = 0; /* NULL terminate the name */
7205                         startn = p + 1;
7206                         info->nested = g_list_append (info->nested, startn);
7207                         /* we have parsed the nesting namespace + name */
7208                         if (info->name)
7209                                 break;
7210                         if (last_point) {
7211                                 info->name_space = start;
7212                                 *last_point = 0;
7213                                 info->name = last_point + 1;
7214                         } else {
7215                                 info->name_space = (char *)"";
7216                                 info->name = start;
7217                         }
7218                         break;
7219                 case '.':
7220                         last_point = p;
7221                         break;
7222                 case '\\':
7223                         ++p;
7224                         break;
7225                 case '&':
7226                 case '*':
7227                 case '[':
7228                 case ',':
7229                 case ']':
7230                         in_modifiers = 1;
7231                         break;
7232                 case '`':
7233                         ++p;
7234                         i = strtol (p, &temp, 10);
7235                         arity += i;
7236                         if (p == temp)
7237                                 return 0;
7238                         p = temp-1;
7239                         break;
7240                 default:
7241                         break;
7242                 }
7243                 if (in_modifiers)
7244                         break;
7245                 // *w++ = *p++;
7246                 p++;
7247         }
7248         
7249         if (!info->name) {
7250                 if (last_point) {
7251                         info->name_space = start;
7252                         *last_point = 0;
7253                         info->name = last_point + 1;
7254                 } else {
7255                         info->name_space = (char *)"";
7256                         info->name = start;
7257                 }
7258         }
7259         while (*p) {
7260                 switch (*p) {
7261                 case '&':
7262                         if (isbyref) /* only one level allowed by the spec */
7263                                 return 0;
7264                         isbyref = 1;
7265                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7266                         *p++ = 0;
7267                         break;
7268                 case '*':
7269                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7270                         *p++ = 0;
7271                         break;
7272                 case '[':
7273                         if (arity != 0) {
7274                                 *p++ = 0;
7275                                 info->type_arguments = g_ptr_array_new ();
7276                                 for (i = 0; i < arity; i++) {
7277                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7278                                         gboolean fqname = FALSE;
7279
7280                                         g_ptr_array_add (info->type_arguments, subinfo);
7281
7282                                         if (*p == '[') {
7283                                                 p++;
7284                                                 fqname = TRUE;
7285                                         }
7286
7287                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7288                                                 return 0;
7289
7290                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7291                                         if (fqname && (*p != ']')) {
7292                                                 char *aname;
7293
7294                                                 if (*p != ',')
7295                                                         return 0;
7296                                                 *p++ = 0;
7297
7298                                                 aname = p;
7299                                                 while (*p && (*p != ']'))
7300                                                         p++;
7301
7302                                                 if (*p != ']')
7303                                                         return 0;
7304
7305                                                 *p++ = 0;
7306                                                 while (*aname) {
7307                                                         if (g_ascii_isspace (*aname)) {
7308                                                                 ++aname;
7309                                                                 continue;
7310                                                         }
7311                                                         break;
7312                                                 }
7313                                                 if (!*aname ||
7314                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7315                                                         return 0;
7316                                         } else if (fqname && (*p == ']')) {
7317                                                 *p++ = 0;
7318                                         }
7319
7320                                         if (i + 1 < arity) {
7321                                                 if (*p != ',')
7322                                                         return 0;
7323                                         } else {
7324                                                 if (*p != ']')
7325                                                         return 0;
7326                                         }
7327                                         *p++ = 0;
7328                                 }
7329
7330                                 arity = 0;
7331                                 break;
7332                         }
7333                         rank = 1;
7334                         *p++ = 0;
7335                         while (*p) {
7336                                 if (*p == ']')
7337                                         break;
7338                                 if (*p == ',')
7339                                         rank++;
7340                                 else if (*p == '*') /* '*' means unknown lower bound */
7341                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7342                                 else
7343                                         return 0;
7344                                 ++p;
7345                         }
7346                         if (*p++ != ']')
7347                                 return 0;
7348                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7349                         break;
7350                 case ']':
7351                         if (is_recursed)
7352                                 goto end;
7353                         return 0;
7354                 case ',':
7355                         if (is_recursed)
7356                                 goto end;
7357                         *p++ = 0;
7358                         while (*p) {
7359                                 if (g_ascii_isspace (*p)) {
7360                                         ++p;
7361                                         continue;
7362                                 }
7363                                 break;
7364                         }
7365                         if (!*p)
7366                                 return 0; /* missing assembly name */
7367                         if (!assembly_name_to_aname (&info->assembly, p))
7368                                 return 0;
7369                         break;
7370                 default:
7371                         return 0;
7372                 }
7373                 if (info->assembly.name)
7374                         break;
7375         }
7376         // *w = 0; /* terminate class name */
7377  end:
7378         if (!info->name || !*info->name)
7379                 return 0;
7380         if (endptr)
7381                 *endptr = p;
7382         /* add other consistency checks */
7383         return 1;
7384 }
7385
7386 int
7387 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7388 {
7389         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7390 }
7391
7392 static MonoType*
7393 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7394 {
7395         gboolean type_resolve = FALSE;
7396         MonoType *type;
7397         MonoImage *rootimage = image;
7398
7399         if (info->assembly.name) {
7400                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7401                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7402                         /* 
7403                          * This could happen in the AOT compiler case when the search hook is not
7404                          * installed.
7405                          */
7406                         assembly = image->assembly;
7407                 if (!assembly) {
7408                         /* then we must load the assembly ourselve - see #60439 */
7409                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7410                         if (!assembly)
7411                                 return NULL;
7412                 }
7413                 image = assembly->image;
7414         } else if (!image) {
7415                 image = mono_defaults.corlib;
7416         }
7417
7418         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7419         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7420                 image = mono_defaults.corlib;
7421                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7422         }
7423
7424         return type;
7425 }
7426
7427 static MonoType*
7428 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7429 {
7430         MonoClass *klass;
7431         GList *mod;
7432         int modval;
7433         gboolean bounded = FALSE;
7434         
7435         if (!image)
7436                 image = mono_defaults.corlib;
7437
7438         if (ignorecase)
7439                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7440         else
7441                 klass = mono_class_from_name (image, info->name_space, info->name);
7442         if (!klass)
7443                 return NULL;
7444         for (mod = info->nested; mod; mod = mod->next) {
7445                 gpointer iter = NULL;
7446                 MonoClass *parent;
7447
7448                 parent = klass;
7449                 mono_class_init (parent);
7450
7451                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7452                         if (ignorecase) {
7453                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7454                                         break;
7455                         } else {
7456                                 if (strcmp (klass->name, mod->data) == 0)
7457                                         break;
7458                         }
7459                 }
7460                 if (!klass)
7461                         break;
7462         }
7463         if (!klass)
7464                 return NULL;
7465
7466         if (info->type_arguments) {
7467                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7468                 MonoReflectionType *the_type;
7469                 MonoType *instance;
7470                 int i;
7471
7472                 for (i = 0; i < info->type_arguments->len; i++) {
7473                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7474
7475                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7476                         if (!type_args [i]) {
7477                                 g_free (type_args);
7478                                 return NULL;
7479                         }
7480                 }
7481
7482                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7483
7484                 instance = mono_reflection_bind_generic_parameters (
7485                         the_type, info->type_arguments->len, type_args);
7486
7487                 g_free (type_args);
7488                 if (!instance)
7489                         return NULL;
7490
7491                 klass = mono_class_from_mono_type (instance);
7492         }
7493
7494         for (mod = info->modifiers; mod; mod = mod->next) {
7495                 modval = GPOINTER_TO_UINT (mod->data);
7496                 if (!modval) { /* byref: must be last modifier */
7497                         return &klass->this_arg;
7498                 } else if (modval == -1) {
7499                         klass = mono_ptr_class_get (&klass->byval_arg);
7500                 } else if (modval == -2) {
7501                         bounded = TRUE;
7502                 } else { /* array rank */
7503                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7504                 }
7505         }
7506
7507         return &klass->byval_arg;
7508 }
7509
7510 /*
7511  * mono_reflection_get_type:
7512  * @image: a metadata context
7513  * @info: type description structure
7514  * @ignorecase: flag for case-insensitive string compares
7515  * @type_resolve: whenever type resolve was already tried
7516  *
7517  * Build a MonoType from the type description in @info.
7518  * 
7519  */
7520
7521 MonoType*
7522 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7523         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7524 }
7525
7526 static MonoType*
7527 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7528 {
7529         MonoReflectionAssemblyBuilder *abuilder;
7530         MonoType *type;
7531         int i;
7532
7533         g_assert (assembly->dynamic);
7534         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7535
7536         /* Enumerate all modules */
7537
7538         type = NULL;
7539         if (abuilder->modules) {
7540                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7541                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7542                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7543                         if (type)
7544                                 break;
7545                 }
7546         }
7547
7548         if (!type && abuilder->loaded_modules) {
7549                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7550                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7551                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7552                         if (type)
7553                                 break;
7554                 }
7555         }
7556
7557         return type;
7558 }
7559         
7560 MonoType*
7561 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7562 {
7563         MonoType *type;
7564         MonoReflectionAssembly *assembly;
7565         GString *fullName;
7566         GList *mod;
7567
7568         if (image && image->dynamic)
7569                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7570         else
7571                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7572         if (type)
7573                 return type;
7574         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7575                 return NULL;
7576
7577         if (type_resolve) {
7578                 if (*type_resolve) 
7579                         return NULL;
7580                 else
7581                         *type_resolve = TRUE;
7582         }
7583         
7584         /* Reconstruct the type name */
7585         fullName = g_string_new ("");
7586         if (info->name_space && (info->name_space [0] != '\0'))
7587                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7588         else
7589                 g_string_printf (fullName, "%s", info->name);
7590         for (mod = info->nested; mod; mod = mod->next)
7591                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7592
7593         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7594         if (assembly) {
7595                 if (assembly->assembly->dynamic)
7596                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7597                 else
7598                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7599                                                                                                           info, ignorecase);
7600         }
7601         g_string_free (fullName, TRUE);
7602         return type;
7603 }
7604
7605 void
7606 mono_reflection_free_type_info (MonoTypeNameParse *info)
7607 {
7608         g_list_free (info->modifiers);
7609         g_list_free (info->nested);
7610
7611         if (info->type_arguments) {
7612                 int i;
7613
7614                 for (i = 0; i < info->type_arguments->len; i++) {
7615                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7616
7617                         mono_reflection_free_type_info (subinfo);
7618                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7619                         g_free (subinfo);
7620                 }
7621
7622                 g_ptr_array_free (info->type_arguments, TRUE);
7623         }
7624 }
7625
7626 /*
7627  * mono_reflection_type_from_name:
7628  * @name: type name.
7629  * @image: a metadata context (can be NULL).
7630  *
7631  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7632  * it defaults to get the type from @image or, if @image is NULL or loading
7633  * from it fails, uses corlib.
7634  * 
7635  */
7636 MonoType*
7637 mono_reflection_type_from_name (char *name, MonoImage *image)
7638 {
7639         MonoType *type = NULL;
7640         MonoTypeNameParse info;
7641         char *tmp;
7642
7643         /* Make a copy since parse_type modifies its argument */
7644         tmp = g_strdup (name);
7645         
7646         /*g_print ("requested type %s\n", str);*/
7647         if (mono_reflection_parse_type (tmp, &info)) {
7648                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7649         }
7650
7651         g_free (tmp);
7652         mono_reflection_free_type_info (&info);
7653         return type;
7654 }
7655
7656 /*
7657  * mono_reflection_get_token:
7658  *
7659  *   Return the metadata token of OBJ which should be an object
7660  * representing a metadata element.
7661  */
7662 guint32
7663 mono_reflection_get_token (MonoObject *obj)
7664 {
7665         MonoClass *klass;
7666         guint32 token = 0;
7667
7668         klass = obj->vtable->klass;
7669
7670         if (strcmp (klass->name, "MethodBuilder") == 0) {
7671                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7672
7673                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7674         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7675                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7676
7677                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7678         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7679                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7680
7681                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7682         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7683                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7684                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7685         } else if (strcmp (klass->name, "MonoType") == 0) {
7686                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7687                 MonoClass *mc = mono_class_from_mono_type (type);
7688                 if (!mono_class_init (mc))
7689                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7690
7691                 token = mc->type_token;
7692         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7693                    strcmp (klass->name, "MonoMethod") == 0 ||
7694                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7695                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7696                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7697                 if (m->method->is_inflated) {
7698                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7699                         return inflated->declaring->token;
7700                 } else {
7701                         token = m->method->token;
7702                 }
7703         } else if (strcmp (klass->name, "MonoField") == 0) {
7704                 MonoReflectionField *f = (MonoReflectionField*)obj;
7705
7706                 if (is_field_on_inst (f->field)) {
7707                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7708                         int field_index = f->field - dgclass->fields;
7709                         MonoObject *obj;
7710
7711                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7712                         obj = dgclass->field_objects [field_index];
7713                         return mono_reflection_get_token (obj);
7714                 }
7715                 token = mono_class_get_field_token (f->field);
7716         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7717                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7718
7719                 token = mono_class_get_property_token (p->property);
7720         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7721                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7722
7723                 token = mono_class_get_event_token (p->event);
7724         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7725                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7726                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7727                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7728
7729                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7730         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7731                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7732
7733                 token = m->token;
7734         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7735                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7736         } else {
7737                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7738                 MonoException *ex = mono_get_exception_not_implemented (msg);
7739                 g_free (msg);
7740                 mono_raise_exception (ex);
7741         }
7742
7743         return token;
7744 }
7745
7746 static void*
7747 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7748 {
7749         int slen, type = t->type;
7750         MonoClass *tklass = t->data.klass;
7751
7752 handle_enum:
7753         switch (type) {
7754         case MONO_TYPE_U1:
7755         case MONO_TYPE_I1:
7756         case MONO_TYPE_BOOLEAN: {
7757                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7758                 *bval = *p;
7759                 *end = p + 1;
7760                 return bval;
7761         }
7762         case MONO_TYPE_CHAR:
7763         case MONO_TYPE_U2:
7764         case MONO_TYPE_I2: {
7765                 guint16 *val = g_malloc (sizeof (guint16));
7766                 *val = read16 (p);
7767                 *end = p + 2;
7768                 return val;
7769         }
7770 #if SIZEOF_VOID_P == 4
7771         case MONO_TYPE_U:
7772         case MONO_TYPE_I:
7773 #endif
7774         case MONO_TYPE_R4:
7775         case MONO_TYPE_U4:
7776         case MONO_TYPE_I4: {
7777                 guint32 *val = g_malloc (sizeof (guint32));
7778                 *val = read32 (p);
7779                 *end = p + 4;
7780                 return val;
7781         }
7782 #if SIZEOF_VOID_P == 8
7783         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7784         case MONO_TYPE_I:
7785 #endif
7786         case MONO_TYPE_U8:
7787         case MONO_TYPE_I8: {
7788                 guint64 *val = g_malloc (sizeof (guint64));
7789                 *val = read64 (p);
7790                 *end = p + 8;
7791                 return val;
7792         }
7793         case MONO_TYPE_R8: {
7794                 double *val = g_malloc (sizeof (double));
7795                 readr8 (p, val);
7796                 *end = p + 8;
7797                 return val;
7798         }
7799         case MONO_TYPE_VALUETYPE:
7800                 if (t->data.klass->enumtype) {
7801                         type = mono_class_enum_basetype (t->data.klass)->type;
7802                         goto handle_enum;
7803                 } else {
7804                         MonoClass *k =  t->data.klass;
7805                         
7806                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7807                                 guint64 *val = g_malloc (sizeof (guint64));
7808                                 *val = read64 (p);
7809                                 *end = p + 8;
7810                                 return val;
7811                         }
7812                 }
7813                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7814                 break;
7815                 
7816         case MONO_TYPE_STRING:
7817                 if (*p == (char)0xFF) {
7818                         *end = p + 1;
7819                         return NULL;
7820                 }
7821                 slen = mono_metadata_decode_value (p, &p);
7822                 *end = p + slen;
7823                 return mono_string_new_len (mono_domain_get (), p, slen);
7824         case MONO_TYPE_CLASS: {
7825                 char *n;
7826                 MonoType *t;
7827                 if (*p == (char)0xFF) {
7828                         *end = p + 1;
7829                         return NULL;
7830                 }
7831 handle_type:
7832                 slen = mono_metadata_decode_value (p, &p);
7833                 n = g_memdup (p, slen + 1);
7834                 n [slen] = 0;
7835                 t = mono_reflection_type_from_name (n, image);
7836                 if (!t)
7837                         g_warning ("Cannot load type '%s'", n);
7838                 g_free (n);
7839                 *end = p + slen;
7840                 if (t)
7841                         return mono_type_get_object (mono_domain_get (), t);
7842                 else
7843                         return NULL;
7844         }
7845         case MONO_TYPE_OBJECT: {
7846                 char subt = *p++;
7847                 MonoObject *obj;
7848                 MonoClass *subc = NULL;
7849                 void *val;
7850
7851                 if (subt == 0x50) {
7852                         goto handle_type;
7853                 } else if (subt == 0x0E) {
7854                         type = MONO_TYPE_STRING;
7855                         goto handle_enum;
7856                 } else if (subt == 0x1D) {
7857                         MonoType simple_type = {{0}};
7858                         int etype = *p;
7859                         p ++;
7860
7861                         if (etype == 0x51)
7862                                 /* See Partition II, Appendix B3 */
7863                                 etype = MONO_TYPE_OBJECT;
7864                         type = MONO_TYPE_SZARRAY;
7865                         simple_type.type = etype;
7866                         tklass = mono_class_from_mono_type (&simple_type);
7867                         goto handle_enum;
7868                 } else if (subt == 0x55) {
7869                         char *n;
7870                         MonoType *t;
7871                         slen = mono_metadata_decode_value (p, &p);
7872                         n = g_memdup (p, slen + 1);
7873                         n [slen] = 0;
7874                         t = mono_reflection_type_from_name (n, image);
7875                         if (!t)
7876                                 g_error ("Cannot load type '%s'", n);
7877                         g_free (n);
7878                         p += slen;
7879                         subc = mono_class_from_mono_type (t);
7880                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7881                         MonoType simple_type = {{0}};
7882                         simple_type.type = subt;
7883                         subc = mono_class_from_mono_type (&simple_type);
7884                 } else {
7885                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7886                 }
7887                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7888                 obj = mono_object_new (mono_domain_get (), subc);
7889                 g_assert (!subc->has_references);
7890                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7891                 g_free (val);
7892                 return obj;
7893         }
7894         case MONO_TYPE_SZARRAY: {
7895                 MonoArray *arr;
7896                 guint32 i, alen, basetype;
7897                 alen = read32 (p);
7898                 p += 4;
7899                 if (alen == 0xffffffff) {
7900                         *end = p;
7901                         return NULL;
7902                 }
7903                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7904                 basetype = tklass->byval_arg.type;
7905                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7906                         basetype = mono_class_enum_basetype (tklass)->type;
7907                 switch (basetype)
7908                 {
7909                         case MONO_TYPE_U1:
7910                         case MONO_TYPE_I1:
7911                         case MONO_TYPE_BOOLEAN:
7912                                 for (i = 0; i < alen; i++) {
7913                                         MonoBoolean val = *p++;
7914                                         mono_array_set (arr, MonoBoolean, i, val);
7915                                 }
7916                                 break;
7917                         case MONO_TYPE_CHAR:
7918                         case MONO_TYPE_U2:
7919                         case MONO_TYPE_I2:
7920                                 for (i = 0; i < alen; i++) {
7921                                         guint16 val = read16 (p);
7922                                         mono_array_set (arr, guint16, i, val);
7923                                         p += 2;
7924                                 }
7925                                 break;
7926                         case MONO_TYPE_R4:
7927                         case MONO_TYPE_U4:
7928                         case MONO_TYPE_I4:
7929                                 for (i = 0; i < alen; i++) {
7930                                         guint32 val = read32 (p);
7931                                         mono_array_set (arr, guint32, i, val);
7932                                         p += 4;
7933                                 }
7934                                 break;
7935                         case MONO_TYPE_R8:
7936                                 for (i = 0; i < alen; i++) {
7937                                         double val;
7938                                         readr8 (p, &val);
7939                                         mono_array_set (arr, double, i, val);
7940                                         p += 8;
7941                                 }
7942                                 break;
7943                         case MONO_TYPE_U8:
7944                         case MONO_TYPE_I8:
7945                                 for (i = 0; i < alen; i++) {
7946                                         guint64 val = read64 (p);
7947                                         mono_array_set (arr, guint64, i, val);
7948                                         p += 8;
7949                                 }
7950                                 break;
7951                         case MONO_TYPE_CLASS:
7952                         case MONO_TYPE_OBJECT:
7953                         case MONO_TYPE_STRING:
7954                                 for (i = 0; i < alen; i++) {
7955                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7956                                         mono_array_setref (arr, i, item);
7957                                 }
7958                                 break;
7959                         default:
7960                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7961                 }
7962                 *end=p;
7963                 return arr;
7964         }
7965         default:
7966                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7967         }
7968         return NULL;
7969 }
7970
7971 static MonoObject*
7972 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7973 {
7974         static MonoClass *klass;
7975         static MonoMethod *ctor;
7976         MonoObject *retval;
7977         void *params [2], *unboxed;
7978
7979         if (!klass)
7980                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7981         if (!ctor)
7982                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7983         
7984         params [0] = mono_type_get_object (mono_domain_get (), t);
7985         params [1] = val;
7986         retval = mono_object_new (mono_domain_get (), klass);
7987         unboxed = mono_object_unbox (retval);
7988         mono_runtime_invoke (ctor, unboxed, params, NULL);
7989
7990         return retval;
7991 }
7992
7993 static MonoObject*
7994 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7995 {
7996         static MonoClass *klass;
7997         static MonoMethod *ctor;
7998         MonoObject *retval;
7999         void *unboxed, *params [2];
8000
8001         if (!klass)
8002                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8003         if (!ctor)
8004                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8005
8006         params [0] = minfo;
8007         params [1] = typedarg;
8008         retval = mono_object_new (mono_domain_get (), klass);
8009         unboxed = mono_object_unbox (retval);
8010         mono_runtime_invoke (ctor, unboxed, params, NULL);
8011
8012         return retval;
8013 }
8014
8015 static gboolean
8016 type_is_reference (MonoType *type)
8017 {
8018         switch (type->type) {
8019         case MONO_TYPE_BOOLEAN:
8020         case MONO_TYPE_CHAR:
8021         case MONO_TYPE_U:
8022         case MONO_TYPE_I:
8023         case MONO_TYPE_U1:
8024         case MONO_TYPE_I1:
8025         case MONO_TYPE_U2:
8026         case MONO_TYPE_I2:
8027         case MONO_TYPE_U4:
8028         case MONO_TYPE_I4:
8029         case MONO_TYPE_U8:
8030         case MONO_TYPE_I8:
8031         case MONO_TYPE_R8:
8032         case MONO_TYPE_R4:
8033         case MONO_TYPE_VALUETYPE:
8034                 return FALSE;
8035         default:
8036                 return TRUE;
8037         }
8038 }
8039
8040 static void
8041 free_param_data (MonoMethodSignature *sig, void **params) {
8042         int i;
8043         for (i = 0; i < sig->param_count; ++i) {
8044                 if (!type_is_reference (sig->params [i]))
8045                         g_free (params [i]);
8046         }
8047 }
8048
8049 /*
8050  * Find the field index in the metadata FieldDef table.
8051  */
8052 static guint32
8053 find_field_index (MonoClass *klass, MonoClassField *field) {
8054         int i;
8055
8056         for (i = 0; i < klass->field.count; ++i) {
8057                 if (field == &klass->fields [i])
8058                         return klass->field.first + 1 + i;
8059         }
8060         return 0;
8061 }
8062
8063 /*
8064  * Find the property index in the metadata Property table.
8065  */
8066 static guint32
8067 find_property_index (MonoClass *klass, MonoProperty *property) {
8068         int i;
8069
8070         for (i = 0; i < klass->ext->property.count; ++i) {
8071                 if (property == &klass->ext->properties [i])
8072                         return klass->ext->property.first + 1 + i;
8073         }
8074         return 0;
8075 }
8076
8077 /*
8078  * Find the event index in the metadata Event table.
8079  */
8080 static guint32
8081 find_event_index (MonoClass *klass, MonoEvent *event) {
8082         int i;
8083
8084         for (i = 0; i < klass->ext->event.count; ++i) {
8085                 if (event == &klass->ext->events [i])
8086                         return klass->ext->event.first + 1 + i;
8087         }
8088         return 0;
8089 }
8090
8091 static MonoObject*
8092 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8093 {
8094         const char *p = (const char*)data;
8095         const char *named;
8096         guint32 i, j, num_named;
8097         MonoObject *attr;
8098         void *params_buf [32];
8099         void **params;
8100         MonoMethodSignature *sig;
8101
8102         mono_error_init (error);
8103
8104         mono_class_init (method->klass);
8105
8106         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8107                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8108                 return NULL;
8109         }
8110
8111         if (len == 0) {
8112                 attr = mono_object_new (mono_domain_get (), method->klass);
8113                 mono_runtime_invoke (method, attr, NULL, NULL);
8114                 return attr;
8115         }
8116
8117         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8118                 return NULL;
8119
8120         /*g_print ("got attr %s\n", method->klass->name);*/
8121
8122         sig = mono_method_signature (method);
8123         if (sig->param_count < 32)
8124                 params = params_buf;
8125         else
8126                 /* Allocate using GC so it gets GC tracking */
8127                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8128
8129         /* skip prolog */
8130         p += 2;
8131         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8132                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8133         }
8134
8135         named = p;
8136         attr = mono_object_new (mono_domain_get (), method->klass);
8137         mono_runtime_invoke (method, attr, params, NULL);
8138         free_param_data (method->signature, params);
8139         num_named = read16 (named);
8140         named += 2;
8141         for (j = 0; j < num_named; j++) {
8142                 gint name_len;
8143                 char *name, named_type, data_type;
8144                 named_type = *named++;
8145                 data_type = *named++; /* type of data */
8146                 if (data_type == MONO_TYPE_SZARRAY)
8147                         data_type = *named++;
8148                 if (data_type == MONO_TYPE_ENUM) {
8149                         gint type_len;
8150                         char *type_name;
8151                         type_len = mono_metadata_decode_blob_size (named, &named);
8152                         type_name = g_malloc (type_len + 1);
8153                         memcpy (type_name, named, type_len);
8154                         type_name [type_len] = 0;
8155                         named += type_len;
8156                         /* FIXME: lookup the type and check type consistency */
8157                         g_free (type_name);
8158                 }
8159                 name_len = mono_metadata_decode_blob_size (named, &named);
8160                 name = g_malloc (name_len + 1);
8161                 memcpy (name, named, name_len);
8162                 name [name_len] = 0;
8163                 named += name_len;
8164                 if (named_type == 0x53) {
8165                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8166                         void *val = load_cattr_value (image, field->type, named, &named);
8167                         mono_field_set_value (attr, field, val);
8168                         if (!type_is_reference (field->type))
8169                                 g_free (val);
8170                 } else if (named_type == 0x54) {
8171                         MonoProperty *prop;
8172                         void *pparams [1];
8173                         MonoType *prop_type;
8174
8175                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8176                         /* can we have more that 1 arg in a custom attr named property? */
8177                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8178                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8179                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8180                         mono_property_set_value (prop, attr, pparams, NULL);
8181                         if (!type_is_reference (prop_type))
8182                                 g_free (pparams [0]);
8183                 }
8184                 g_free (name);
8185         }
8186
8187         if (params != params_buf)
8188                 mono_gc_free_fixed (params);
8189
8190         return attr;
8191 }
8192         
8193 /*
8194  * mono_reflection_create_custom_attr_data_args:
8195  *
8196  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8197  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8198  * NAMED_ARG_INFO will contain information about the named arguments.
8199  */
8200 void
8201 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)
8202 {
8203         MonoArray *typedargs, *namedargs;
8204         MonoClass *attrklass;
8205         MonoDomain *domain;
8206         const char *p = (const char*)data;
8207         const char *named;
8208         guint32 i, j, num_named;
8209         CattrNamedArg *arginfo = NULL;
8210
8211         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8212                 return;
8213
8214         mono_class_init (method->klass);
8215
8216         *typed_args = NULL;
8217         *named_args = NULL;
8218         *named_arg_info = NULL;
8219         
8220         domain = mono_domain_get ();
8221
8222         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8223                 return;
8224
8225         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8226         
8227         /* skip prolog */
8228         p += 2;
8229         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8230                 MonoObject *obj;
8231                 void *val;
8232
8233                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8234                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8235                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8236                 mono_array_setref (typedargs, i, obj);
8237
8238                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8239                         g_free (val);
8240         }
8241
8242         named = p;
8243         num_named = read16 (named);
8244         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8245         named += 2;
8246         attrklass = method->klass;
8247
8248         arginfo = g_new0 (CattrNamedArg, num_named);
8249         *named_arg_info = arginfo;
8250
8251         for (j = 0; j < num_named; j++) {
8252                 gint name_len;
8253                 char *name, named_type, data_type;
8254                 named_type = *named++;
8255                 data_type = *named++; /* type of data */
8256                 if (data_type == MONO_TYPE_SZARRAY)
8257                         data_type = *named++;
8258                 if (data_type == MONO_TYPE_ENUM) {
8259                         gint type_len;
8260                         char *type_name;
8261                         type_len = mono_metadata_decode_blob_size (named, &named);
8262                         type_name = g_malloc (type_len + 1);
8263                         memcpy (type_name, named, type_len);
8264                         type_name [type_len] = 0;
8265                         named += type_len;
8266                         /* FIXME: lookup the type and check type consistency */
8267                         g_free (type_name);
8268                 }
8269                 name_len = mono_metadata_decode_blob_size (named, &named);
8270                 name = g_malloc (name_len + 1);
8271                 memcpy (name, named, name_len);
8272                 name [name_len] = 0;
8273                 named += name_len;
8274                 if (named_type == 0x53) {
8275                         MonoObject *obj;
8276                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8277                         void *val;
8278
8279                         arginfo [j].type = field->type;
8280                         arginfo [j].field = field;
8281
8282                         val = load_cattr_value (image, field->type, named, &named);
8283                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8284                         mono_array_setref (namedargs, j, obj);
8285                         if (!type_is_reference (field->type))
8286                                 g_free (val);
8287                 } else if (named_type == 0x54) {
8288                         MonoObject *obj;
8289                         MonoType *prop_type;
8290                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8291                         void *val;
8292
8293                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8294                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8295
8296                         arginfo [j].type = prop_type;
8297                         arginfo [j].prop = prop;
8298
8299                         val = load_cattr_value (image, prop_type, named, &named);
8300                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8301                         mono_array_setref (namedargs, j, obj);
8302                         if (!type_is_reference (prop_type))
8303                                 g_free (val);
8304                 }
8305                 g_free (name);
8306         }
8307
8308         *typed_args = typedargs;
8309         *named_args = namedargs;
8310 }
8311
8312 void
8313 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8314 {
8315         MonoDomain *domain;
8316         MonoArray *typedargs, *namedargs;
8317         MonoImage *image;
8318         MonoMethod *method;
8319         CattrNamedArg *arginfo;
8320         int i;
8321
8322         *ctor_args = NULL;
8323         *named_args = NULL;
8324
8325         if (len == 0)
8326                 return;
8327
8328         image = assembly->assembly->image;
8329         method = ref_method->method;
8330         domain = mono_object_domain (ref_method);
8331
8332         if (!mono_class_init (method->klass))
8333                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8334
8335         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8336         if (mono_loader_get_last_error ())
8337                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8338
8339         if (!typedargs || !namedargs)
8340                 return;
8341
8342         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8343                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8344                 MonoObject *typedarg;
8345
8346                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8347                 mono_array_setref (typedargs, i, typedarg);
8348         }
8349
8350         for (i = 0; i < mono_array_length (namedargs); ++i) {
8351                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8352                 MonoObject *typedarg, *namedarg, *minfo;
8353
8354                 if (arginfo [i].prop)
8355                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8356                 else
8357                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8358
8359                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8360                 namedarg = create_cattr_named_arg (minfo, typedarg);
8361
8362                 mono_array_setref (namedargs, i, namedarg);
8363         }
8364
8365         *ctor_args = typedargs;
8366         *named_args = namedargs;
8367 }
8368
8369 static MonoObject*
8370 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8371 {
8372         static MonoMethod *ctor;
8373         MonoDomain *domain;
8374         MonoObject *attr;
8375         void *params [4];
8376
8377         g_assert (image->assembly);
8378
8379         if (!ctor)
8380                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8381
8382         domain = mono_domain_get ();
8383         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8384         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8385         params [1] = mono_assembly_get_object (domain, image->assembly);
8386         params [2] = (gpointer)&cattr->data;
8387         params [3] = &cattr->data_size;
8388         mono_runtime_invoke (ctor, attr, params, NULL);
8389         return attr;
8390 }
8391
8392 static MonoArray*
8393 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8394 {
8395         MonoArray *result;
8396         MonoObject *attr;
8397         int i, n;
8398
8399         mono_error_init (error);
8400
8401         n = 0;
8402         for (i = 0; i < cinfo->num_attrs; ++i) {
8403                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8404                         n ++;
8405         }
8406
8407         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8408         n = 0;
8409         for (i = 0; i < cinfo->num_attrs; ++i) {
8410                 if (!cinfo->attrs [i].ctor)
8411                         /* The cattr type is not finished yet */
8412                         /* We should include the type name but cinfo doesn't contain it */
8413                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8414                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8415                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8416                         if (!mono_error_ok (error))
8417                                 return result;
8418                         mono_array_setref (result, n, attr);
8419                         n ++;
8420                 }
8421         }
8422         return result;
8423 }
8424
8425 MonoArray*
8426 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8427 {
8428         MonoError error;
8429
8430         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8431 }
8432
8433 static MonoArray*
8434 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8435 {
8436         MonoArray *result;
8437         MonoObject *attr;
8438         int i;
8439         
8440         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8441         for (i = 0; i < cinfo->num_attrs; ++i) {
8442                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8443                 mono_array_setref (result, i, attr);
8444         }
8445         return result;
8446 }
8447
8448 /**
8449  * mono_custom_attrs_from_index:
8450  *
8451  * Returns: NULL if no attributes are found or if a loading error occurs.
8452  */
8453 MonoCustomAttrInfo*
8454 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8455 {
8456         guint32 mtoken, i, len;
8457         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8458         MonoTableInfo *ca;
8459         MonoCustomAttrInfo *ainfo;
8460         GList *tmp, *list = NULL;
8461         const char *data;
8462
8463         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8464
8465         i = mono_metadata_custom_attrs_from_index (image, idx);
8466         if (!i)
8467                 return NULL;
8468         i --;
8469         while (i < ca->rows) {
8470                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8471                         break;
8472                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8473                 ++i;
8474         }
8475         len = g_list_length (list);
8476         if (!len)
8477                 return NULL;
8478         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8479         ainfo->num_attrs = len;
8480         ainfo->image = image;
8481         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8482                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8483                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8484                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8485                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8486                         mtoken |= MONO_TOKEN_METHOD_DEF;
8487                         break;
8488                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8489                         mtoken |= MONO_TOKEN_MEMBER_REF;
8490                         break;
8491                 default:
8492                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8493                         break;
8494                 }
8495                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8496                 if (!ainfo->attrs [i].ctor) {
8497                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8498                         g_list_free (list);
8499                         g_free (ainfo);
8500                         return NULL;
8501                 }
8502
8503                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8504                         /*FIXME raising an exception here doesn't make any sense*/
8505                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8506                         g_list_free (list);
8507                         g_free (ainfo);
8508                         return NULL;
8509                 }
8510                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8511                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8512                 ainfo->attrs [i].data = (guchar*)data;
8513         }
8514         g_list_free (list);
8515
8516         return ainfo;
8517 }
8518
8519 MonoCustomAttrInfo*
8520 mono_custom_attrs_from_method (MonoMethod *method)
8521 {
8522         guint32 idx;
8523
8524         /*
8525          * An instantiated method has the same cattrs as the generic method definition.
8526          *
8527          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8528          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8529          */
8530         if (method->is_inflated)
8531                 method = ((MonoMethodInflated *) method)->declaring;
8532         
8533         if (method->dynamic || method->klass->image->dynamic)
8534                 return lookup_custom_attr (method->klass->image, method);
8535
8536         if (!method->token)
8537                 /* Synthetic methods */
8538                 return NULL;
8539
8540         idx = mono_method_get_index (method);
8541         idx <<= MONO_CUSTOM_ATTR_BITS;
8542         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8543         return mono_custom_attrs_from_index (method->klass->image, idx);
8544 }
8545
8546 MonoCustomAttrInfo*
8547 mono_custom_attrs_from_class (MonoClass *klass)
8548 {
8549         guint32 idx;
8550
8551         if (klass->generic_class)
8552                 klass = klass->generic_class->container_class;
8553
8554         if (klass->image->dynamic)
8555                 return lookup_custom_attr (klass->image, klass);
8556
8557         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8558                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8559                 idx <<= MONO_CUSTOM_ATTR_BITS;
8560                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8561         } else {
8562                 idx = mono_metadata_token_index (klass->type_token);
8563                 idx <<= MONO_CUSTOM_ATTR_BITS;
8564                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8565         }
8566         return mono_custom_attrs_from_index (klass->image, idx);
8567 }
8568
8569 MonoCustomAttrInfo*
8570 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8571 {
8572         guint32 idx;
8573         
8574         if (assembly->image->dynamic)
8575                 return lookup_custom_attr (assembly->image, assembly);
8576         idx = 1; /* there is only one assembly */
8577         idx <<= MONO_CUSTOM_ATTR_BITS;
8578         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8579         return mono_custom_attrs_from_index (assembly->image, idx);
8580 }
8581
8582 static MonoCustomAttrInfo*
8583 mono_custom_attrs_from_module (MonoImage *image)
8584 {
8585         guint32 idx;
8586         
8587         if (image->dynamic)
8588                 return lookup_custom_attr (image, image);
8589         idx = 1; /* there is only one module */
8590         idx <<= MONO_CUSTOM_ATTR_BITS;
8591         idx |= MONO_CUSTOM_ATTR_MODULE;
8592         return mono_custom_attrs_from_index (image, idx);
8593 }
8594
8595 MonoCustomAttrInfo*
8596 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8597 {
8598         guint32 idx;
8599         
8600         if (klass->image->dynamic) {
8601                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8602                 return lookup_custom_attr (klass->image, property);
8603         }
8604         idx = find_property_index (klass, property);
8605         idx <<= MONO_CUSTOM_ATTR_BITS;
8606         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8607         return mono_custom_attrs_from_index (klass->image, idx);
8608 }
8609
8610 MonoCustomAttrInfo*
8611 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8612 {
8613         guint32 idx;
8614         
8615         if (klass->image->dynamic) {
8616                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8617                 return lookup_custom_attr (klass->image, event);
8618         }
8619         idx = find_event_index (klass, event);
8620         idx <<= MONO_CUSTOM_ATTR_BITS;
8621         idx |= MONO_CUSTOM_ATTR_EVENT;
8622         return mono_custom_attrs_from_index (klass->image, idx);
8623 }
8624
8625 MonoCustomAttrInfo*
8626 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8627 {
8628         guint32 idx;
8629         if (klass->image->dynamic) {
8630                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8631                 return lookup_custom_attr (klass->image, field);
8632         }
8633         idx = find_field_index (klass, field);
8634         idx <<= MONO_CUSTOM_ATTR_BITS;
8635         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8636         return mono_custom_attrs_from_index (klass->image, idx);
8637 }
8638
8639 MonoCustomAttrInfo*
8640 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8641 {
8642         MonoTableInfo *ca;
8643         guint32 i, idx, method_index;
8644         guint32 param_list, param_last, param_pos, found;
8645         MonoImage *image;
8646         MonoReflectionMethodAux *aux;
8647
8648         /*
8649          * An instantiated method has the same cattrs as the generic method definition.
8650          *
8651          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8652          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8653          */
8654         if (method->is_inflated)
8655                 method = ((MonoMethodInflated *) method)->declaring;
8656
8657         if (method->klass->image->dynamic) {
8658                 MonoCustomAttrInfo *res, *ainfo;
8659                 int size;
8660
8661                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8662                 if (!aux || !aux->param_cattr)
8663                         return NULL;
8664
8665                 /* Need to copy since it will be freed later */
8666                 ainfo = aux->param_cattr [param];
8667                 if (!ainfo)
8668                         return NULL;
8669                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8670                 res = g_malloc0 (size);
8671                 memcpy (res, ainfo, size);
8672                 return res;
8673         }
8674
8675         image = method->klass->image;
8676         method_index = mono_method_get_index (method);
8677         if (!method_index)
8678                 return NULL;
8679         ca = &image->tables [MONO_TABLE_METHOD];
8680
8681         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8682         if (method_index == ca->rows) {
8683                 ca = &image->tables [MONO_TABLE_PARAM];
8684                 param_last = ca->rows + 1;
8685         } else {
8686                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8687                 ca = &image->tables [MONO_TABLE_PARAM];
8688         }
8689         found = FALSE;
8690         for (i = param_list; i < param_last; ++i) {
8691                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8692                 if (param_pos == param) {
8693                         found = TRUE;
8694                         break;
8695                 }
8696         }
8697         if (!found)
8698                 return NULL;
8699         idx = i;
8700         idx <<= MONO_CUSTOM_ATTR_BITS;
8701         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8702         return mono_custom_attrs_from_index (image, idx);
8703 }
8704
8705 gboolean
8706 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8707 {
8708         int i;
8709         MonoClass *klass;
8710         for (i = 0; i < ainfo->num_attrs; ++i) {
8711                 klass = ainfo->attrs [i].ctor->klass;
8712                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8713                         return TRUE;
8714         }
8715         return FALSE;
8716 }
8717
8718 MonoObject*
8719 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8720 {
8721         int i, attr_index;
8722         MonoClass *klass;
8723         MonoArray *attrs;
8724
8725         attr_index = -1;
8726         for (i = 0; i < ainfo->num_attrs; ++i) {
8727                 klass = ainfo->attrs [i].ctor->klass;
8728                 if (mono_class_has_parent (klass, attr_klass)) {
8729                         attr_index = i;
8730                         break;
8731                 }
8732         }
8733         if (attr_index == -1)
8734                 return NULL;
8735
8736         attrs = mono_custom_attrs_construct (ainfo);
8737         if (attrs)
8738                 return mono_array_get (attrs, MonoObject*, attr_index);
8739         else
8740                 return NULL;
8741 }
8742
8743 /*
8744  * mono_reflection_get_custom_attrs_info:
8745  * @obj: a reflection object handle
8746  *
8747  * Return the custom attribute info for attributes defined for the
8748  * reflection handle @obj. The objects.
8749  *
8750  * FIXME this function leaks like a sieve for SRE objects.
8751  */
8752 MonoCustomAttrInfo*
8753 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8754 {
8755         MonoClass *klass;
8756         MonoCustomAttrInfo *cinfo = NULL;
8757         
8758         klass = obj->vtable->klass;
8759         if (klass == mono_defaults.monotype_class) {
8760                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8761                 klass = mono_class_from_mono_type (type);
8762                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8763                 cinfo = mono_custom_attrs_from_class (klass);
8764         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8765                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8766                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8767         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8768                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8769                 cinfo = mono_custom_attrs_from_module (module->image);
8770         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8771                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8772                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8773         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8774                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8775                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8776         } else if (strcmp ("MonoField", klass->name) == 0) {
8777                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8778                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8779         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8780                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8781                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8782         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8783                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8784                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8785         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8786                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8787                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8788                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8789                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8790                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8791                 } else if (is_sr_mono_property (member_class)) {
8792                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8793                         MonoMethod *method;
8794                         if (!(method = prop->property->get))
8795                                 method = prop->property->set;
8796                         g_assert (method);
8797
8798                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8799                 } 
8800 #ifndef DISABLE_REFLECTION_EMIT
8801                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8802                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8803                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8804                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8805                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8806                         MonoMethod *method = NULL;
8807                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8808                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8809                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8810                                 method = ((MonoReflectionMethod *)c->cb)->method;
8811                         else
8812                                 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));
8813
8814                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8815                 } 
8816 #endif
8817                 else {
8818                         char *type_name = mono_type_get_full_name (member_class);
8819                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8820                         MonoException *ex = mono_get_exception_not_supported  (msg);
8821                         g_free (type_name);
8822                         g_free (msg);
8823                         mono_raise_exception (ex);
8824                 }
8825         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8826                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8827                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8828         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8829                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8830                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8831         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8832                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8833                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8834         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8835                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8836                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8837         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8838                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8839                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8840         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8841                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8842                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8843         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8844                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8845                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8846         } else { /* handle other types here... */
8847                 g_error ("get custom attrs not yet supported for %s", klass->name);
8848         }
8849
8850         return cinfo;
8851 }
8852
8853 /*
8854  * mono_reflection_get_custom_attrs_by_type:
8855  * @obj: a reflection object handle
8856  *
8857  * Return an array with all the custom attributes defined of the
8858  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8859  * of that type are returned. The objects are fully build. Return NULL if a loading error
8860  * occurs.
8861  */
8862 MonoArray*
8863 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8864 {
8865         MonoArray *result;
8866         MonoCustomAttrInfo *cinfo;
8867
8868         mono_error_init (error);
8869
8870         cinfo = mono_reflection_get_custom_attrs_info (obj);
8871         if (cinfo) {
8872                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8873                 if (!cinfo->cached)
8874                         mono_custom_attrs_free (cinfo);
8875         } else {
8876                 if (mono_loader_get_last_error ())
8877                         return NULL;
8878                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8879         }
8880
8881         return result;
8882 }
8883
8884 /*
8885  * mono_reflection_get_custom_attrs:
8886  * @obj: a reflection object handle
8887  *
8888  * Return an array with all the custom attributes defined of the
8889  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8890  * occurs.
8891  */
8892 MonoArray*
8893 mono_reflection_get_custom_attrs (MonoObject *obj)
8894 {
8895         MonoError error;
8896
8897         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8898 }
8899
8900 /*
8901  * mono_reflection_get_custom_attrs_data:
8902  * @obj: a reflection obj handle
8903  *
8904  * Returns an array of System.Reflection.CustomAttributeData,
8905  * which include information about attributes reflected on
8906  * types loaded using the Reflection Only methods
8907  */
8908 MonoArray*
8909 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8910 {
8911         MonoArray *result;
8912         MonoCustomAttrInfo *cinfo;
8913
8914         cinfo = mono_reflection_get_custom_attrs_info (obj);
8915         if (cinfo) {
8916                 result = mono_custom_attrs_data_construct (cinfo);
8917                 if (!cinfo->cached)
8918                         mono_custom_attrs_free (cinfo);
8919         } else
8920                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8921
8922         return result;
8923 }
8924
8925 static MonoReflectionType*
8926 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8927 {
8928         static MonoMethod *method_get_underlying_system_type = NULL;
8929         MonoMethod *usertype_method;
8930
8931         if (!method_get_underlying_system_type)
8932                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8933         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8934         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8935 }
8936
8937
8938 static gboolean
8939 is_corlib_type (MonoClass *class)
8940 {
8941         return class->image == mono_defaults.corlib;
8942 }
8943
8944 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8945         static MonoClass *cached_class; \
8946         if (cached_class) \
8947                 return cached_class == _class; \
8948         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8949                 cached_class = _class; \
8950                 return TRUE; \
8951         } \
8952         return FALSE; \
8953 } while (0) \
8954
8955
8956 #ifndef DISABLE_REFLECTION_EMIT
8957 static gboolean
8958 is_sre_array (MonoClass *class)
8959 {
8960         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8961 }
8962
8963 static gboolean
8964 is_sre_byref (MonoClass *class)
8965 {
8966         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8967 }
8968
8969 static gboolean
8970 is_sre_pointer (MonoClass *class)
8971 {
8972         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8973 }
8974
8975 static gboolean
8976 is_sre_generic_instance (MonoClass *class)
8977 {
8978         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8979 }
8980
8981 static gboolean
8982 is_sre_type_builder (MonoClass *class)
8983 {
8984         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8985 }
8986
8987 static gboolean
8988 is_sre_method_builder (MonoClass *class)
8989 {
8990         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8991 }
8992
8993 static gboolean
8994 is_sre_ctor_builder (MonoClass *class)
8995 {
8996         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8997 }
8998
8999 static gboolean
9000 is_sre_field_builder (MonoClass *class)
9001 {
9002         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9003 }
9004
9005 static gboolean
9006 is_sre_method_on_tb_inst (MonoClass *class)
9007 {
9008         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9009 }
9010
9011 static gboolean
9012 is_sre_ctor_on_tb_inst (MonoClass *class)
9013 {
9014         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9015 }
9016
9017 MonoType*
9018 mono_reflection_type_get_handle (MonoReflectionType* ref)
9019 {
9020         MonoClass *class;
9021         if (!ref)
9022                 return NULL;
9023         if (ref->type)
9024                 return ref->type;
9025
9026         if (is_usertype (ref)) {
9027                 ref = mono_reflection_type_get_underlying_system_type (ref);
9028                 if (ref == NULL || is_usertype (ref))
9029                         return NULL;
9030                 if (ref->type)
9031                         return ref->type;
9032         }
9033
9034         class = mono_object_class (ref);
9035
9036         if (is_sre_array (class)) {
9037                 MonoType *res;
9038                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9039                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9040                 g_assert (base);
9041                 if (sre_array->rank == 0) //single dimentional array
9042                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9043                 else
9044                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9045                 sre_array->type.type = res;
9046                 return res;
9047         } else if (is_sre_byref (class)) {
9048                 MonoType *res;
9049                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9050                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9051                 g_assert (base);
9052                 res = &mono_class_from_mono_type (base)->this_arg;
9053                 sre_byref->type.type = res;
9054                 return res;
9055         } else if (is_sre_pointer (class)) {
9056                 MonoType *res;
9057                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9058                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9059                 g_assert (base);
9060                 res = &mono_ptr_class_get (base)->byval_arg;
9061                 sre_pointer->type.type = res;
9062                 return res;
9063         } else if (is_sre_generic_instance (class)) {
9064                 MonoType *res, **types;
9065                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9066                 int i, count;
9067
9068                 count = mono_array_length (gclass->type_arguments);
9069                 types = g_new0 (MonoType*, count);
9070                 for (i = 0; i < count; ++i) {
9071                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9072                         types [i] = mono_reflection_type_get_handle (t);
9073                         if (!types[i]) {
9074                                 g_free (types);
9075                                 return NULL;
9076                         }
9077                 }
9078
9079                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9080                 g_free (types);
9081                 g_assert (res);
9082                 gclass->type.type = res;
9083                 return res;
9084         }
9085
9086         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9087         return NULL;
9088 }
9089
9090
9091
9092 void
9093 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9094 {
9095         mono_reflection_type_get_handle (type);
9096 }
9097
9098 void
9099 mono_reflection_register_with_runtime (MonoReflectionType *type)
9100 {
9101         MonoType *res = mono_reflection_type_get_handle (type);
9102         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9103         MonoClass *class;
9104
9105         if (!res)
9106                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9107
9108         class = mono_class_from_mono_type (res);
9109
9110         mono_loader_lock (); /*same locking as mono_type_get_object*/
9111         mono_domain_lock (domain);
9112
9113         if (!class->image->dynamic) {
9114                 mono_class_setup_supertypes (class);
9115         } else {
9116                 if (!domain->type_hash)
9117                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9118                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9119                 mono_g_hash_table_insert (domain->type_hash, res, type);
9120         }
9121         mono_domain_unlock (domain);
9122         mono_loader_unlock ();
9123 }
9124
9125 /**
9126  * LOCKING: Assumes the loader lock is held.
9127  */
9128 static MonoMethodSignature*
9129 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9130         MonoMethodSignature *sig;
9131         int count, i;
9132
9133         count = parameters? mono_array_length (parameters): 0;
9134
9135         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9136         sig->param_count = count;
9137         sig->sentinelpos = -1; /* FIXME */
9138         for (i = 0; i < count; ++i)
9139                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9140         return sig;
9141 }
9142
9143 /**
9144  * LOCKING: Assumes the loader lock is held.
9145  */
9146 static MonoMethodSignature*
9147 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9148         MonoMethodSignature *sig;
9149
9150         sig = parameters_to_signature (image, ctor->parameters);
9151         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9152         sig->ret = &mono_defaults.void_class->byval_arg;
9153         return sig;
9154 }
9155
9156 /**
9157  * LOCKING: Assumes the loader lock is held.
9158  */
9159 static MonoMethodSignature*
9160 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9161         MonoMethodSignature *sig;
9162
9163         sig = parameters_to_signature (image, method->parameters);
9164         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9165         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9166         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9167         return sig;
9168 }
9169
9170 static MonoMethodSignature*
9171 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9172         MonoMethodSignature *sig;
9173
9174         sig = parameters_to_signature (NULL, method->parameters);
9175         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9176         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9177         sig->generic_param_count = 0;
9178         return sig;
9179 }
9180
9181 static void
9182 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9183 {
9184         MonoClass *klass = mono_object_class (prop);
9185         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9186                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9187                 *name = mono_string_to_utf8 (pb->name);
9188                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9189         } else {
9190                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9191                 *name = g_strdup (p->property->name);
9192                 if (p->property->get)
9193                         *type = mono_method_signature (p->property->get)->ret;
9194                 else
9195                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9196         }
9197 }
9198
9199 static void
9200 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9201 {
9202         MonoClass *klass = mono_object_class (field);
9203         if (strcmp (klass->name, "FieldBuilder") == 0) {
9204                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9205                 *name = mono_string_to_utf8 (fb->name);
9206                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9207         } else {
9208                 MonoReflectionField *f = (MonoReflectionField *)field;
9209                 *name = g_strdup (mono_field_get_name (f->field));
9210                 *type = f->field->type;
9211         }
9212 }
9213
9214 #else /* DISABLE_REFLECTION_EMIT */
9215
9216 void
9217 mono_reflection_register_with_runtime (MonoReflectionType *type)
9218 {
9219         /* This is empty */
9220 }
9221
9222 static gboolean
9223 is_sre_type_builder (MonoClass *class)
9224 {
9225         return FALSE;
9226 }
9227
9228 static gboolean
9229 is_sre_generic_instance (MonoClass *class)
9230 {
9231         return FALSE;
9232 }
9233
9234 static void
9235 init_type_builder_generics (MonoObject *type)
9236 {
9237 }
9238
9239 #endif /* !DISABLE_REFLECTION_EMIT */
9240
9241
9242 static gboolean
9243 is_sr_mono_field (MonoClass *class)
9244 {
9245         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9246 }
9247
9248 static gboolean
9249 is_sr_mono_property (MonoClass *class)
9250 {
9251         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9252 }
9253
9254 static gboolean
9255 is_sr_mono_method (MonoClass *class)
9256 {
9257         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9258 }
9259
9260 static gboolean
9261 is_sr_mono_cmethod (MonoClass *class)
9262 {
9263         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9264 }
9265
9266 static gboolean
9267 is_sr_mono_generic_method (MonoClass *class)
9268 {
9269         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9270 }
9271
9272 static gboolean
9273 is_sr_mono_generic_cmethod (MonoClass *class)
9274 {
9275         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9276 }
9277
9278 gboolean
9279 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9280 {
9281         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9282 }
9283
9284 static gboolean
9285 is_usertype (MonoReflectionType *ref)
9286 {
9287         MonoClass *class = mono_object_class (ref);
9288         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9289 }
9290
9291 static MonoReflectionType*
9292 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9293 {
9294         if (!type || type->type)
9295                 return type;
9296
9297         if (is_usertype (type)) {
9298                 type = mono_reflection_type_get_underlying_system_type (type);
9299                 if (is_usertype (type))
9300                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9301         }
9302
9303         return type;
9304 }
9305 /*
9306  * Encode a value in a custom attribute stream of bytes.
9307  * The value to encode is either supplied as an object in argument val
9308  * (valuetypes are boxed), or as a pointer to the data in the
9309  * argument argval.
9310  * @type represents the type of the value
9311  * @buffer is the start of the buffer
9312  * @p the current position in the buffer
9313  * @buflen contains the size of the buffer and is used to return the new buffer size
9314  * if this needs to be realloced.
9315  * @retbuffer and @retp return the start and the position of the buffer
9316  */
9317 static void
9318 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9319 {
9320         MonoTypeEnum simple_type;
9321         
9322         if ((p-buffer) + 10 >= *buflen) {
9323                 char *newbuf;
9324                 *buflen *= 2;
9325                 newbuf = g_realloc (buffer, *buflen);
9326                 p = newbuf + (p-buffer);
9327                 buffer = newbuf;
9328         }
9329         if (!argval)
9330                 argval = ((char*)arg + sizeof (MonoObject));
9331         simple_type = type->type;
9332 handle_enum:
9333         switch (simple_type) {
9334         case MONO_TYPE_BOOLEAN:
9335         case MONO_TYPE_U1:
9336         case MONO_TYPE_I1:
9337                 *p++ = *argval;
9338                 break;
9339         case MONO_TYPE_CHAR:
9340         case MONO_TYPE_U2:
9341         case MONO_TYPE_I2:
9342                 swap_with_size (p, argval, 2, 1);
9343                 p += 2;
9344                 break;
9345         case MONO_TYPE_U4:
9346         case MONO_TYPE_I4:
9347         case MONO_TYPE_R4:
9348                 swap_with_size (p, argval, 4, 1);
9349                 p += 4;
9350                 break;
9351         case MONO_TYPE_R8:
9352 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9353                 p [0] = argval [4];
9354                 p [1] = argval [5];
9355                 p [2] = argval [6];
9356                 p [3] = argval [7];
9357                 p [4] = argval [0];
9358                 p [5] = argval [1];
9359                 p [6] = argval [2];
9360                 p [7] = argval [3];
9361 #else
9362                 swap_with_size (p, argval, 8, 1);
9363 #endif
9364                 p += 8;
9365                 break;
9366         case MONO_TYPE_U8:
9367         case MONO_TYPE_I8:
9368                 swap_with_size (p, argval, 8, 1);
9369                 p += 8;
9370                 break;
9371         case MONO_TYPE_VALUETYPE:
9372                 if (type->data.klass->enumtype) {
9373                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9374                         goto handle_enum;
9375                 } else {
9376                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9377                 }
9378                 break;
9379         case MONO_TYPE_STRING: {
9380                 char *str;
9381                 guint32 slen;
9382                 if (!arg) {
9383                         *p++ = 0xFF;
9384                         break;
9385                 }
9386                 str = mono_string_to_utf8 ((MonoString*)arg);
9387                 slen = strlen (str);
9388                 if ((p-buffer) + 10 + slen >= *buflen) {
9389                         char *newbuf;
9390                         *buflen *= 2;
9391                         *buflen += slen;
9392                         newbuf = g_realloc (buffer, *buflen);
9393                         p = newbuf + (p-buffer);
9394                         buffer = newbuf;
9395                 }
9396                 mono_metadata_encode_value (slen, p, &p);
9397                 memcpy (p, str, slen);
9398                 p += slen;
9399                 g_free (str);
9400                 break;
9401         }
9402         case MONO_TYPE_CLASS: {
9403                 char *str;
9404                 guint32 slen;
9405                 if (!arg) {
9406                         *p++ = 0xFF;
9407                         break;
9408                 }
9409 handle_type:
9410                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9411                 slen = strlen (str);
9412                 if ((p-buffer) + 10 + slen >= *buflen) {
9413                         char *newbuf;
9414                         *buflen *= 2;
9415                         *buflen += slen;
9416                         newbuf = g_realloc (buffer, *buflen);
9417                         p = newbuf + (p-buffer);
9418                         buffer = newbuf;
9419                 }
9420                 mono_metadata_encode_value (slen, p, &p);
9421                 memcpy (p, str, slen);
9422                 p += slen;
9423                 g_free (str);
9424                 break;
9425         }
9426         case MONO_TYPE_SZARRAY: {
9427                 int len, i;
9428                 MonoClass *eclass, *arg_eclass;
9429
9430                 if (!arg) {
9431                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9432                         break;
9433                 }
9434                 len = mono_array_length ((MonoArray*)arg);
9435                 *p++ = len & 0xff;
9436                 *p++ = (len >> 8) & 0xff;
9437                 *p++ = (len >> 16) & 0xff;
9438                 *p++ = (len >> 24) & 0xff;
9439                 *retp = p;
9440                 *retbuffer = buffer;
9441                 eclass = type->data.klass;
9442                 arg_eclass = mono_object_class (arg)->element_class;
9443
9444                 if (!eclass) {
9445                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9446                         eclass = mono_defaults.object_class;
9447                 }
9448                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9449                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9450                         int elsize = mono_class_array_element_size (arg_eclass);
9451                         for (i = 0; i < len; ++i) {
9452                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9453                                 elptr += elsize;
9454                         }
9455                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9456                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9457                         int elsize = mono_class_array_element_size (eclass);
9458                         for (i = 0; i < len; ++i) {
9459                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9460                                 elptr += elsize;
9461                         }
9462                 } else {
9463                         for (i = 0; i < len; ++i) {
9464                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9465                         }
9466                 }
9467                 break;
9468         }
9469         case MONO_TYPE_OBJECT: {
9470                 MonoClass *klass;
9471                 char *str;
9472                 guint32 slen;
9473
9474                 /*
9475                  * The parameter type is 'object' but the type of the actual
9476                  * argument is not. So we have to add type information to the blob
9477                  * too. This is completely undocumented in the spec.
9478                  */
9479
9480                 if (arg == NULL) {
9481                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9482                         *p++ = 0xFF;
9483                         break;
9484                 }
9485                 
9486                 klass = mono_object_class (arg);
9487
9488                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9489                         *p++ = 0x50;
9490                         goto handle_type;
9491                 } else if (klass->enumtype) {
9492                         *p++ = 0x55;
9493                 } else if (klass == mono_defaults.string_class) {
9494                         simple_type = MONO_TYPE_STRING;
9495                         *p++ = 0x0E;
9496                         goto handle_enum;
9497                 } else if (klass->rank == 1) {
9498                         *p++ = 0x1D;
9499                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9500                                 /* See Partition II, Appendix B3 */
9501                                 *p++ = 0x51;
9502                         else
9503                                 *p++ = klass->element_class->byval_arg.type;
9504                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9505                         break;
9506                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9507                         *p++ = simple_type = klass->byval_arg.type;
9508                         goto handle_enum;
9509                 } else {
9510                         g_error ("unhandled type in custom attr");
9511                 }
9512                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9513                 slen = strlen (str);
9514                 if ((p-buffer) + 10 + slen >= *buflen) {
9515                         char *newbuf;
9516                         *buflen *= 2;
9517                         *buflen += slen;
9518                         newbuf = g_realloc (buffer, *buflen);
9519                         p = newbuf + (p-buffer);
9520                         buffer = newbuf;
9521                 }
9522                 mono_metadata_encode_value (slen, p, &p);
9523                 memcpy (p, str, slen);
9524                 p += slen;
9525                 g_free (str);
9526                 simple_type = mono_class_enum_basetype (klass)->type;
9527                 goto handle_enum;
9528         }
9529         default:
9530                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9531         }
9532         *retp = p;
9533         *retbuffer = buffer;
9534 }
9535
9536 static void
9537 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9538 {
9539         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9540                 char *str = type_get_qualified_name (type, NULL);
9541                 int slen = strlen (str);
9542
9543                 *p++ = 0x55;
9544                 /*
9545                  * This seems to be optional...
9546                  * *p++ = 0x80;
9547                  */
9548                 mono_metadata_encode_value (slen, p, &p);
9549                 memcpy (p, str, slen);
9550                 p += slen;
9551                 g_free (str);
9552         } else if (type->type == MONO_TYPE_OBJECT) {
9553                 *p++ = 0x51;
9554         } else if (type->type == MONO_TYPE_CLASS) {
9555                 /* it should be a type: encode_cattr_value () has the check */
9556                 *p++ = 0x50;
9557         } else {
9558                 mono_metadata_encode_value (type->type, p, &p);
9559                 if (type->type == MONO_TYPE_SZARRAY)
9560                         /* See the examples in Partition VI, Annex B */
9561                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9562         }
9563
9564         *retp = p;
9565 }
9566
9567 #ifndef DISABLE_REFLECTION_EMIT
9568 static void
9569 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9570 {
9571         int len;
9572         /* Preallocate a large enough buffer */
9573         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9574                 char *str = type_get_qualified_name (type, NULL);
9575                 len = strlen (str);
9576                 g_free (str);
9577         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9578                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9579                 len = strlen (str);
9580                 g_free (str);
9581         } else {
9582                 len = 0;
9583         }
9584         len += strlen (name);
9585
9586         if ((p-buffer) + 20 + len >= *buflen) {
9587                 char *newbuf;
9588                 *buflen *= 2;
9589                 *buflen += len;
9590                 newbuf = g_realloc (buffer, *buflen);
9591                 p = newbuf + (p-buffer);
9592                 buffer = newbuf;
9593         }
9594
9595         encode_field_or_prop_type (type, p, &p);
9596
9597         len = strlen (name);
9598         mono_metadata_encode_value (len, p, &p);
9599         memcpy (p, name, len);
9600         p += len;
9601         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9602         *retp = p;
9603         *retbuffer = buffer;
9604 }
9605
9606 /*
9607  * mono_reflection_get_custom_attrs_blob:
9608  * @ctor: custom attribute constructor
9609  * @ctorArgs: arguments o the constructor
9610  * @properties:
9611  * @propValues:
9612  * @fields:
9613  * @fieldValues:
9614  * 
9615  * Creates the blob of data that needs to be saved in the metadata and that represents
9616  * the custom attributed described by @ctor, @ctorArgs etc.
9617  * Returns: a Byte array representing the blob of data.
9618  */
9619 MonoArray*
9620 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9621 {
9622         MonoArray *result;
9623         MonoMethodSignature *sig;
9624         MonoObject *arg;
9625         char *buffer, *p;
9626         guint32 buflen, i;
9627
9628         MONO_ARCH_SAVE_REGS;
9629
9630         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9631                 /* sig is freed later so allocate it in the heap */
9632                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9633         } else {
9634                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9635         }
9636
9637         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9638         buflen = 256;
9639         p = buffer = g_malloc (buflen);
9640         /* write the prolog */
9641         *p++ = 1;
9642         *p++ = 0;
9643         for (i = 0; i < sig->param_count; ++i) {
9644                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9645                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9646         }
9647         i = 0;
9648         if (properties)
9649                 i += mono_array_length (properties);
9650         if (fields)
9651                 i += mono_array_length (fields);
9652         *p++ = i & 0xff;
9653         *p++ = (i >> 8) & 0xff;
9654         if (properties) {
9655                 MonoObject *prop;
9656                 for (i = 0; i < mono_array_length (properties); ++i) {
9657                         MonoType *ptype;
9658                         char *pname;
9659
9660                         prop = mono_array_get (properties, gpointer, i);
9661                         get_prop_name_and_type (prop, &pname, &ptype);
9662                         *p++ = 0x54; /* PROPERTY signature */
9663                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9664                         g_free (pname);
9665                 }
9666         }
9667
9668         if (fields) {
9669                 MonoObject *field;
9670                 for (i = 0; i < mono_array_length (fields); ++i) {
9671                         MonoType *ftype;
9672                         char *fname;
9673
9674                         field = mono_array_get (fields, gpointer, i);
9675                         get_field_name_and_type (field, &fname, &ftype);
9676                         *p++ = 0x53; /* FIELD signature */
9677                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9678                         g_free (fname);
9679                 }
9680         }
9681
9682         g_assert (p - buffer <= buflen);
9683         buflen = p - buffer;
9684         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9685         p = mono_array_addr (result, char, 0);
9686         memcpy (p, buffer, buflen);
9687         g_free (buffer);
9688         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9689                 g_free (sig);
9690         return result;
9691 }
9692
9693 /*
9694  * mono_reflection_setup_internal_class:
9695  * @tb: a TypeBuilder object
9696  *
9697  * Creates a MonoClass that represents the TypeBuilder.
9698  * This is a trick that lets us simplify a lot of reflection code
9699  * (and will allow us to support Build and Run assemblies easier).
9700  */
9701 void
9702 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9703 {
9704         MonoError error;
9705         MonoClass *klass, *parent;
9706
9707         MONO_ARCH_SAVE_REGS;
9708
9709         RESOLVE_TYPE (tb->parent);
9710
9711         mono_loader_lock ();
9712
9713         if (tb->parent) {
9714                 /* check so we can compile corlib correctly */
9715                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9716                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9717                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9718                 } else {
9719                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9720                 }
9721         } else {
9722                 parent = NULL;
9723         }
9724         
9725         /* the type has already being created: it means we just have to change the parent */
9726         if (tb->type.type) {
9727                 klass = mono_class_from_mono_type (tb->type.type);
9728                 klass->parent = NULL;
9729                 /* fool mono_class_setup_parent */
9730                 klass->supertypes = NULL;
9731                 mono_class_setup_parent (klass, parent);
9732                 mono_class_setup_mono_type (klass);
9733                 mono_loader_unlock ();
9734                 return;
9735         }
9736
9737         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9738
9739         klass->image = &tb->module->dynamic_image->image;
9740
9741         klass->inited = 1; /* we lie to the runtime */
9742         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9743         if (!mono_error_ok (&error))
9744                 goto failure;
9745         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9746         if (!mono_error_ok (&error))
9747                 goto failure;
9748         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9749         klass->flags = tb->attrs;
9750         
9751         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9752
9753         klass->element_class = klass;
9754
9755         if (mono_class_get_ref_info (klass) == NULL) {
9756
9757                 mono_class_set_ref_info (klass, tb);
9758
9759                 /* Put into cache so mono_class_get () will find it.
9760                 Skip nested types as those should not be available on the global scope. */
9761                 if (!tb->nesting_type) {
9762                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9763                 } else {
9764                         klass->image->reflection_info_unregister_classes =
9765                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9766                 }
9767         } else {
9768                 g_assert (mono_class_get_ref_info (klass) == tb);
9769         }
9770
9771         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9772                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9773
9774         if (parent != NULL) {
9775                 mono_class_setup_parent (klass, parent);
9776         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9777                 const char *old_n = klass->name;
9778                 /* trick to get relative numbering right when compiling corlib */
9779                 klass->name = "BuildingObject";
9780                 mono_class_setup_parent (klass, mono_defaults.object_class);
9781                 klass->name = old_n;
9782         }
9783
9784         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9785                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9786                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9787                 klass->instance_size = sizeof (MonoObject);
9788                 klass->size_inited = 1;
9789                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9790         }
9791
9792         mono_class_setup_mono_type (klass);
9793
9794         mono_class_setup_supertypes (klass);
9795
9796         /*
9797          * FIXME: handle interfaces.
9798          */
9799
9800         tb->type.type = &klass->byval_arg;
9801
9802         if (tb->nesting_type) {
9803                 g_assert (tb->nesting_type->type);
9804                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9805         }
9806
9807         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9808
9809         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9810         
9811         mono_loader_unlock ();
9812         return;
9813
9814 failure:
9815         mono_loader_unlock ();
9816         mono_error_raise_exception (&error);
9817 }
9818
9819 /*
9820  * mono_reflection_setup_generic_class:
9821  * @tb: a TypeBuilder object
9822  *
9823  * Setup the generic class before adding the first generic parameter.
9824  */
9825 void
9826 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9827 {
9828 }
9829
9830 /*
9831  * mono_reflection_create_generic_class:
9832  * @tb: a TypeBuilder object
9833  *
9834  * Creates the generic class after all generic parameters have been added.
9835  */
9836 void
9837 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9838 {
9839         MonoClass *klass;
9840         int count, i;
9841
9842         MONO_ARCH_SAVE_REGS;
9843
9844         klass = mono_class_from_mono_type (tb->type.type);
9845
9846         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9847
9848         if (klass->generic_container || (count == 0))
9849                 return;
9850
9851         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9852
9853         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9854
9855         klass->generic_container->owner.klass = klass;
9856         klass->generic_container->type_argc = count;
9857         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9858
9859         klass->is_generic = 1;
9860
9861         for (i = 0; i < count; i++) {
9862                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9863                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9864                 klass->generic_container->type_params [i] = *param;
9865                 /*Make sure we are a diferent type instance */
9866                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9867                 klass->generic_container->type_params [i].info.pklass = NULL;
9868                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9869
9870                 g_assert (klass->generic_container->type_params [i].param.owner);
9871         }
9872
9873         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9874 }
9875
9876 /*
9877  * mono_reflection_create_internal_class:
9878  * @tb: a TypeBuilder object
9879  *
9880  * Actually create the MonoClass that is associated with the TypeBuilder.
9881  */
9882 void
9883 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9884 {
9885         MonoClass *klass;
9886
9887         MONO_ARCH_SAVE_REGS;
9888
9889         klass = mono_class_from_mono_type (tb->type.type);
9890
9891         mono_loader_lock ();
9892         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9893                 MonoReflectionFieldBuilder *fb;
9894                 MonoClass *ec;
9895                 MonoType *enum_basetype;
9896
9897                 g_assert (tb->fields != NULL);
9898                 g_assert (mono_array_length (tb->fields) >= 1);
9899
9900                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9901
9902                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9903                         mono_loader_unlock ();
9904                         return;
9905                 }
9906
9907                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9908                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9909                 if (!klass->element_class)
9910                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9911
9912                 /*
9913                  * get the element_class from the current corlib.
9914                  */
9915                 ec = default_class_from_mono_type (enum_basetype);
9916                 klass->instance_size = ec->instance_size;
9917                 klass->size_inited = 1;
9918                 /* 
9919                  * this is almost safe to do with enums and it's needed to be able
9920                  * to create objects of the enum type (for use in SetConstant).
9921                  */
9922                 /* FIXME: Does this mean enums can't have method overrides ? */
9923                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9924         }
9925         mono_loader_unlock ();
9926 }
9927
9928 static MonoMarshalSpec*
9929 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9930                                                                 MonoReflectionMarshal *minfo)
9931 {
9932         MonoMarshalSpec *res;
9933
9934         res = image_g_new0 (image, MonoMarshalSpec, 1);
9935         res->native = minfo->type;
9936
9937         switch (minfo->type) {
9938         case MONO_NATIVE_LPARRAY:
9939                 res->data.array_data.elem_type = minfo->eltype;
9940                 if (minfo->has_size) {
9941                         res->data.array_data.param_num = minfo->param_num;
9942                         res->data.array_data.num_elem = minfo->count;
9943                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9944                 }
9945                 else {
9946                         res->data.array_data.param_num = -1;
9947                         res->data.array_data.num_elem = -1;
9948                         res->data.array_data.elem_mult = -1;
9949                 }
9950                 break;
9951
9952         case MONO_NATIVE_BYVALTSTR:
9953         case MONO_NATIVE_BYVALARRAY:
9954                 res->data.array_data.num_elem = minfo->count;
9955                 break;
9956
9957         case MONO_NATIVE_CUSTOM:
9958                 if (minfo->marshaltyperef)
9959                         res->data.custom_data.custom_name =
9960                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9961                 if (minfo->mcookie)
9962                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9963                 break;
9964
9965         default:
9966                 break;
9967         }
9968
9969         return res;
9970 }
9971 #endif /* !DISABLE_REFLECTION_EMIT */
9972
9973 MonoReflectionMarshal*
9974 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9975                                                                                    MonoMarshalSpec *spec)
9976 {
9977         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9978         MonoReflectionMarshal *minfo;
9979         MonoType *mtype;
9980
9981         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9982                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9983                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9984                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9985         }
9986
9987         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9988         minfo->type = spec->native;
9989
9990         switch (minfo->type) {
9991         case MONO_NATIVE_LPARRAY:
9992                 minfo->eltype = spec->data.array_data.elem_type;
9993                 minfo->count = spec->data.array_data.num_elem;
9994                 minfo->param_num = spec->data.array_data.param_num;
9995                 break;
9996
9997         case MONO_NATIVE_BYVALTSTR:
9998         case MONO_NATIVE_BYVALARRAY:
9999                 minfo->count = spec->data.array_data.num_elem;
10000                 break;
10001
10002         case MONO_NATIVE_CUSTOM:
10003                 if (spec->data.custom_data.custom_name) {
10004                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10005                         if (mtype)
10006                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10007
10008                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10009                 }
10010                 if (spec->data.custom_data.cookie)
10011                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10012                 break;
10013
10014         default:
10015                 break;
10016         }
10017
10018         return minfo;
10019 }
10020
10021 #ifndef DISABLE_REFLECTION_EMIT
10022 static MonoMethod*
10023 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10024                                          ReflectionMethodBuilder *rmb,
10025                                          MonoMethodSignature *sig)
10026 {
10027         MonoError error;
10028         MonoMethod *m;
10029         MonoMethodWrapper *wrapperm;
10030         MonoMarshalSpec **specs;
10031         MonoReflectionMethodAux *method_aux;
10032         MonoImage *image;
10033         gboolean dynamic;
10034         int i;
10035
10036         mono_error_init (&error);
10037         /*
10038          * Methods created using a MethodBuilder should have their memory allocated
10039          * inside the image mempool, while dynamic methods should have their memory
10040          * malloc'd.
10041          */
10042         dynamic = rmb->refs != NULL;
10043         image = dynamic ? NULL : klass->image;
10044
10045         if (!dynamic)
10046                 g_assert (!klass->generic_class);
10047
10048         mono_loader_lock ();
10049
10050         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10051                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10052                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10053         else
10054                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10055
10056         wrapperm = (MonoMethodWrapper*)m;
10057
10058         m->dynamic = dynamic;
10059         m->slot = -1;
10060         m->flags = rmb->attrs;
10061         m->iflags = rmb->iattrs;
10062         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10063         g_assert (mono_error_ok (&error));
10064         m->klass = klass;
10065         m->signature = sig;
10066         m->sre_method = TRUE;
10067         m->skip_visibility = rmb->skip_visibility;
10068         if (rmb->table_idx)
10069                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10070
10071         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10072                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10073                         m->string_ctor = 1;
10074
10075                 m->signature->pinvoke = 1;
10076         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10077                 m->signature->pinvoke = 1;
10078
10079                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10080
10081                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10082                 g_assert (mono_error_ok (&error));
10083                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10084                 g_assert (mono_error_ok (&error));
10085                 
10086                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10087
10088                 if (klass->image->dynamic)
10089                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10090
10091                 mono_loader_unlock ();
10092
10093                 return m;
10094         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10095                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10096                 MonoMethodHeader *header;
10097                 guint32 code_size;
10098                 gint32 max_stack, i;
10099                 gint32 num_locals = 0;
10100                 gint32 num_clauses = 0;
10101                 guint8 *code;
10102
10103                 if (rmb->ilgen) {
10104                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10105                         code_size = rmb->ilgen->code_len;
10106                         max_stack = rmb->ilgen->max_stack;
10107                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10108                         if (rmb->ilgen->ex_handlers)
10109                                 num_clauses = method_count_clauses (rmb->ilgen);
10110                 } else {
10111                         if (rmb->code) {
10112                                 code = mono_array_addr (rmb->code, guint8, 0);
10113                                 code_size = mono_array_length (rmb->code);
10114                                 /* we probably need to run a verifier on the code... */
10115                                 max_stack = 8; 
10116                         }
10117                         else {
10118                                 code = NULL;
10119                                 code_size = 0;
10120                                 max_stack = 8;
10121                         }
10122                 }
10123
10124                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10125                 header->code_size = code_size;
10126                 header->code = image_g_malloc (image, code_size);
10127                 memcpy ((char*)header->code, code, code_size);
10128                 header->max_stack = max_stack;
10129                 header->init_locals = rmb->init_locals;
10130                 header->num_locals = num_locals;
10131
10132                 for (i = 0; i < num_locals; ++i) {
10133                         MonoReflectionLocalBuilder *lb = 
10134                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10135
10136                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10137                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10138                 }
10139
10140                 header->num_clauses = num_clauses;
10141                 if (num_clauses) {
10142                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10143                                  rmb->ilgen, num_clauses);
10144                 }
10145
10146                 wrapperm->header = header;
10147         }
10148
10149         if (rmb->generic_params) {
10150                 int count = mono_array_length (rmb->generic_params);
10151                 MonoGenericContainer *container = rmb->generic_container;
10152
10153                 g_assert (container);
10154
10155                 container->type_argc = count;
10156                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10157                 container->owner.method = m;
10158
10159                 m->is_generic = TRUE;
10160                 mono_method_set_generic_container (m, container);
10161
10162                 for (i = 0; i < count; i++) {
10163                         MonoReflectionGenericParam *gp =
10164                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10165                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10166                         container->type_params [i] = *param;
10167                 }
10168
10169                 /*
10170                  * The method signature might have pointers to generic parameters that belong to other methods.
10171                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10172                  * generic parameters.
10173                  */
10174                 for (i = 0; i < m->signature->param_count; ++i) {
10175                         MonoType *t = m->signature->params [i];
10176                         if (t->type == MONO_TYPE_MVAR) {
10177                                 MonoGenericParam *gparam =  t->data.generic_param;
10178                                 if (gparam->num < count) {
10179                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10180                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10181                                 }
10182
10183                         }
10184                 }
10185
10186                 if (klass->generic_container) {
10187                         container->parent = klass->generic_container;
10188                         container->context.class_inst = klass->generic_container->context.class_inst;
10189                 }
10190                 container->context.method_inst = mono_get_shared_generic_inst (container);
10191         }
10192
10193         if (rmb->refs) {
10194                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10195                 int i;
10196                 void **data;
10197
10198                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10199
10200                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10201                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10202                 for (i = 0; i < rmb->nrefs; ++i)
10203                         data [i + 1] = rmb->refs [i];
10204         }
10205
10206         method_aux = NULL;
10207
10208         /* Parameter info */
10209         if (rmb->pinfo) {
10210                 if (!method_aux)
10211                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10212                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10213                 for (i = 0; i <= m->signature->param_count; ++i) {
10214                         MonoReflectionParamBuilder *pb;
10215                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10216                                 if ((i > 0) && (pb->attrs)) {
10217                                         /* Make a copy since it might point to a shared type structure */
10218                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10219                                         m->signature->params [i - 1]->attrs = pb->attrs;
10220                                 }
10221
10222                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10223                                         MonoDynamicImage *assembly;
10224                                         guint32 idx, def_type, len;
10225                                         char *p;
10226                                         const char *p2;
10227
10228                                         if (!method_aux->param_defaults) {
10229                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10230                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10231                                         }
10232                                         assembly = (MonoDynamicImage*)klass->image;
10233                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10234                                         /* Copy the data from the blob since it might get realloc-ed */
10235                                         p = assembly->blob.data + idx;
10236                                         len = mono_metadata_decode_blob_size (p, &p2);
10237                                         len += p2 - p;
10238                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10239                                         method_aux->param_default_types [i] = def_type;
10240                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10241                                 }
10242
10243                                 if (pb->name) {
10244                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10245                                         g_assert (mono_error_ok (&error));
10246                                 }
10247                                 if (pb->cattrs) {
10248                                         if (!method_aux->param_cattr)
10249                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10250                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10251                                 }
10252                         }
10253                 }
10254         }
10255
10256         /* Parameter marshalling */
10257         specs = NULL;
10258         if (rmb->pinfo)         
10259                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10260                         MonoReflectionParamBuilder *pb;
10261                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10262                                 if (pb->marshal_info) {
10263                                         if (specs == NULL)
10264                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10265                                         specs [pb->position] = 
10266                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10267                                 }
10268                         }
10269                 }
10270         if (specs != NULL) {
10271                 if (!method_aux)
10272                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10273                 method_aux->param_marshall = specs;
10274         }
10275
10276         if (klass->image->dynamic && method_aux)
10277                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10278
10279         mono_loader_unlock ();
10280
10281         return m;
10282 }       
10283
10284 static MonoMethod*
10285 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10286 {
10287         ReflectionMethodBuilder rmb;
10288         MonoMethodSignature *sig;
10289
10290         mono_loader_lock ();
10291         sig = ctor_builder_to_signature (klass->image, mb);
10292         mono_loader_unlock ();
10293
10294         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10295
10296         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10297         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10298
10299         /* If we are in a generic class, we might be called multiple times from inflate_method */
10300         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10301                 /* ilgen is no longer needed */
10302                 mb->ilgen = NULL;
10303         }
10304
10305         return mb->mhandle;
10306 }
10307
10308 static MonoMethod*
10309 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10310 {
10311         ReflectionMethodBuilder rmb;
10312         MonoMethodSignature *sig;
10313
10314         mono_loader_lock ();
10315         sig = method_builder_to_signature (klass->image, mb);
10316         mono_loader_unlock ();
10317
10318         reflection_methodbuilder_from_method_builder (&rmb, mb);
10319
10320         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10321         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10322
10323         /* If we are in a generic class, we might be called multiple times from inflate_method */
10324         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10325                 /* ilgen is no longer needed */
10326                 mb->ilgen = NULL;
10327         }
10328         return mb->mhandle;
10329 }
10330
10331 static MonoClassField*
10332 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10333 {
10334         MonoClassField *field;
10335         MonoType *custom;
10336         MonoError error;
10337
10338         field = g_new0 (MonoClassField, 1);
10339
10340         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10341         g_assert (mono_error_ok (&error));
10342         if (fb->attrs || fb->modreq || fb->modopt) {
10343                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10344                 field->type->attrs = fb->attrs;
10345
10346                 g_assert (klass->image->dynamic);
10347                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10348                 g_free (field->type);
10349                 field->type = mono_metadata_type_dup (klass->image, custom);
10350                 g_free (custom);
10351         } else {
10352                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10353         }
10354         if (fb->offset != -1)
10355                 field->offset = fb->offset;
10356         field->parent = klass;
10357         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10358
10359         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10360
10361         return field;
10362 }
10363 #endif
10364
10365 MonoType*
10366 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10367 {
10368         MonoClass *klass;
10369         MonoReflectionTypeBuilder *tb = NULL;
10370         gboolean is_dynamic = FALSE;
10371         MonoDomain *domain;
10372         MonoClass *geninst;
10373
10374         mono_loader_lock ();
10375
10376         domain = mono_object_domain (type);
10377
10378         if (is_sre_type_builder (mono_object_class (type))) {
10379                 tb = (MonoReflectionTypeBuilder *) type;
10380
10381                 is_dynamic = TRUE;
10382         } else if (is_sre_generic_instance (mono_object_class (type))) {
10383                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10384                 MonoReflectionType *gtd = rgi->generic_type;
10385
10386                 if (is_sre_type_builder (mono_object_class (gtd))) {
10387                         tb = (MonoReflectionTypeBuilder *)gtd;
10388                         is_dynamic = TRUE;
10389                 }
10390         }
10391
10392         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10393         if (tb && tb->generic_container)
10394                 mono_reflection_create_generic_class (tb);
10395
10396         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10397         if (!klass->generic_container) {
10398                 mono_loader_unlock ();
10399                 return NULL;
10400         }
10401
10402         if (klass->wastypebuilder) {
10403                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10404
10405                 is_dynamic = TRUE;
10406         }
10407
10408         mono_loader_unlock ();
10409
10410         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10411
10412         return &geninst->byval_arg;
10413 }
10414
10415 MonoClass*
10416 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10417 {
10418         MonoGenericClass *gclass;
10419         MonoGenericInst *inst;
10420
10421         g_assert (klass->generic_container);
10422
10423         inst = mono_metadata_get_generic_inst (type_argc, types);
10424         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10425
10426         return mono_generic_class_get_class (gclass);
10427 }
10428
10429 MonoReflectionMethod*
10430 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10431 {
10432         MonoClass *klass;
10433         MonoMethod *method, *inflated;
10434         MonoMethodInflated *imethod;
10435         MonoGenericContext tmp_context;
10436         MonoGenericInst *ginst;
10437         MonoType **type_argv;
10438         int count, i;
10439
10440         MONO_ARCH_SAVE_REGS;
10441
10442         /*FIXME but this no longer should happen*/
10443         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10444 #ifndef DISABLE_REFLECTION_EMIT
10445                 MonoReflectionMethodBuilder *mb = NULL;
10446                 MonoReflectionTypeBuilder *tb;
10447                 MonoClass *klass;
10448
10449                 mb = (MonoReflectionMethodBuilder *) rmethod;
10450                 tb = (MonoReflectionTypeBuilder *) mb->type;
10451                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10452
10453                 method = methodbuilder_to_mono_method (klass, mb);
10454 #else
10455                 g_assert_not_reached ();
10456                 method = NULL;
10457 #endif
10458         } else {
10459                 method = rmethod->method;
10460         }
10461
10462         klass = method->klass;
10463
10464         if (method->is_inflated)
10465                 method = ((MonoMethodInflated *) method)->declaring;
10466
10467         count = mono_method_signature (method)->generic_param_count;
10468         if (count != mono_array_length (types))
10469                 return NULL;
10470
10471         type_argv = g_new0 (MonoType *, count);
10472         for (i = 0; i < count; i++) {
10473                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10474                 type_argv [i] = mono_reflection_type_get_handle (garg);
10475         }
10476         ginst = mono_metadata_get_generic_inst (count, type_argv);
10477         g_free (type_argv);
10478
10479         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10480         tmp_context.method_inst = ginst;
10481
10482         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10483         imethod = (MonoMethodInflated *) inflated;
10484
10485         /*FIXME but I think this is no longer necessary*/
10486         if (method->klass->image->dynamic) {
10487                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10488                 /*
10489                  * This table maps metadata structures representing inflated methods/fields
10490                  * to the reflection objects representing their generic definitions.
10491                  */
10492                 mono_loader_lock ();
10493                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10494                 mono_loader_unlock ();
10495         }
10496
10497         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10498                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10499         
10500         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10501 }
10502
10503 #ifndef DISABLE_REFLECTION_EMIT
10504
10505 static MonoMethod *
10506 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10507 {
10508         MonoMethodInflated *imethod;
10509         MonoGenericContext *context;
10510         int i;
10511
10512         /*
10513          * With generic code sharing the klass might not be inflated.
10514          * This can happen because classes inflated with their own
10515          * type arguments are "normalized" to the uninflated class.
10516          */
10517         if (!klass->generic_class)
10518                 return method;
10519
10520         context = mono_class_get_context (klass);
10521
10522         if (klass->method.count && klass->methods) {
10523                 /* Find the already created inflated method */
10524                 for (i = 0; i < klass->method.count; ++i) {
10525                         g_assert (klass->methods [i]->is_inflated);
10526                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10527                                 break;
10528                 }
10529                 g_assert (i < klass->method.count);
10530                 imethod = (MonoMethodInflated*)klass->methods [i];
10531         } else {
10532                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10533         }
10534
10535         if (method->is_generic && method->klass->image->dynamic) {
10536                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10537
10538                 mono_loader_lock ();
10539                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10540                 mono_loader_unlock ();
10541         }
10542         return (MonoMethod *) imethod;
10543 }
10544
10545 static MonoMethod *
10546 inflate_method (MonoReflectionType *type, MonoObject *obj)
10547 {
10548         MonoMethod *method;
10549         MonoClass *gklass;
10550
10551         MonoClass *type_class = mono_object_class (type);
10552
10553         if (is_sre_generic_instance (type_class)) {
10554                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10555                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10556         } else if (is_sre_type_builder (type_class)) {
10557                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10558         } else if (type->type) {
10559                 gklass = mono_class_from_mono_type (type->type);
10560                 gklass = mono_class_get_generic_type_definition (gklass);
10561         } else {
10562                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10563         }
10564
10565         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10566                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10567                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10568                 else
10569                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10570         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10571                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10572         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10573                 method = ((MonoReflectionMethod *) obj)->method;
10574         else {
10575                 method = NULL; /* prevent compiler warning */
10576                 g_error ("can't handle type %s", obj->vtable->klass->name);
10577         }
10578
10579         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10580 }
10581
10582 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10583 void
10584 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10585                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10586                                           MonoArray *events)
10587 {
10588         MonoGenericClass *gclass;
10589         MonoDynamicGenericClass *dgclass;
10590         MonoClass *klass, *gklass;
10591         MonoType *gtype;
10592         int i;
10593
10594         MONO_ARCH_SAVE_REGS;
10595
10596         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10597         klass = mono_class_from_mono_type (gtype);
10598         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10599         gclass = gtype->data.generic_class;
10600
10601         if (!gclass->is_dynamic)
10602                 return;
10603
10604         dgclass = (MonoDynamicGenericClass *) gclass;
10605
10606         if (dgclass->initialized)
10607                 return;
10608
10609         gklass = gclass->container_class;
10610         mono_class_init (gklass);
10611
10612         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10613         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10614         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10615
10616         dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
10617         dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
10618         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10619         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10620         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10621
10622         for (i = 0; i < dgclass->count_methods; i++) {
10623                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10624
10625                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10626         }
10627
10628         for (i = 0; i < dgclass->count_ctors; i++) {
10629                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10630
10631                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10632         }
10633
10634         for (i = 0; i < dgclass->count_fields; i++) {
10635                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10636                 MonoClassField *field, *inflated_field = NULL;
10637
10638                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10639                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10640                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10641                         field = ((MonoReflectionField *) obj)->field;
10642                 else {
10643                         field = NULL; /* prevent compiler warning */
10644                         g_assert_not_reached ();
10645                 }
10646
10647                 dgclass->fields [i] = *field;
10648                 dgclass->fields [i].parent = klass;
10649                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10650                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10651                 dgclass->field_generic_types [i] = field->type;
10652                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10653                 dgclass->field_objects [i] = obj;
10654
10655                 if (inflated_field) {
10656                         g_free (inflated_field);
10657                 } else {
10658                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10659                 }
10660         }
10661
10662         dgclass->initialized = TRUE;
10663 }
10664
10665 void
10666 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10667 {
10668         MonoDynamicGenericClass *dgclass;
10669         int i;
10670
10671         g_assert (gclass->is_dynamic);
10672
10673         dgclass = (MonoDynamicGenericClass *)gclass;
10674
10675         for (i = 0; i < dgclass->count_fields; ++i) {
10676                 MonoClassField *field = dgclass->fields + i;
10677                 mono_metadata_free_type (field->type);
10678                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10679         }
10680 }
10681
10682 static void
10683 fix_partial_generic_class (MonoClass *klass)
10684 {
10685         MonoClass *gklass = klass->generic_class->container_class;
10686         MonoDynamicGenericClass *dgclass;
10687         int i;
10688
10689         if (klass->wastypebuilder)
10690                 return;
10691
10692         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10693         if (klass->parent != gklass->parent) {
10694                 MonoError error;
10695                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10696                 if (mono_error_ok (&error)) {
10697                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10698                         mono_metadata_free_type (parent_type);
10699                         if (parent != klass->parent) {
10700                                 /*fool mono_class_setup_parent*/
10701                                 klass->supertypes = NULL;
10702                                 mono_class_setup_parent (klass, parent);
10703                         }
10704                 } else {
10705                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10706                         mono_error_cleanup (&error);
10707                         if (gklass->wastypebuilder)
10708                                 klass->wastypebuilder = TRUE;
10709                         return;
10710                 }
10711         }
10712
10713         if (!dgclass->initialized)
10714                 return;
10715
10716         if (klass->method.count != gklass->method.count) {
10717                 klass->method.count = gklass->method.count;
10718                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10719
10720                 for (i = 0; i < klass->method.count; i++) {
10721                         klass->methods [i] = mono_class_inflate_generic_method_full (
10722                                 gklass->methods [i], klass, mono_class_get_context (klass));
10723                 }
10724         }
10725
10726         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10727                 klass->interface_count = gklass->interface_count;
10728                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10729                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10730
10731                 for (i = 0; i < gklass->interface_count; ++i) {
10732                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10733                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10734                         mono_metadata_free_type (iface_type);
10735
10736                         ensure_runtime_vtable (klass->interfaces [i]);
10737                 }
10738                 klass->interfaces_inited = 1;
10739         }
10740
10741         if (klass->field.count != gklass->field.count) {
10742                 klass->field.count = gklass->field.count;
10743                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10744
10745                 for (i = 0; i < klass->field.count; i++) {
10746                         klass->fields [i] = gklass->fields [i];
10747                         klass->fields [i].parent = klass;
10748                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10749                 }
10750         }
10751
10752         /*We can only finish with this klass once it's parent has as well*/
10753         if (gklass->wastypebuilder)
10754                 klass->wastypebuilder = TRUE;
10755         return;
10756 }
10757
10758 static void
10759 ensure_generic_class_runtime_vtable (MonoClass *klass)
10760 {
10761         MonoClass *gklass = klass->generic_class->container_class;
10762
10763         ensure_runtime_vtable (gklass); 
10764
10765         fix_partial_generic_class (klass);
10766 }
10767
10768 static void
10769 ensure_runtime_vtable (MonoClass *klass)
10770 {
10771         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10772         int i, num, j;
10773
10774         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10775                 return;
10776         if (klass->parent)
10777                 ensure_runtime_vtable (klass->parent);
10778
10779         if (tb) {
10780                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10781                 num += tb->num_methods;
10782                 klass->method.count = num;
10783                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10784                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10785                 for (i = 0; i < num; ++i)
10786                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10787                 num = tb->num_methods;
10788                 j = i;
10789                 for (i = 0; i < num; ++i)
10790                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10791         
10792                 if (tb->interfaces) {
10793                         klass->interface_count = mono_array_length (tb->interfaces);
10794                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10795                         for (i = 0; i < klass->interface_count; ++i) {
10796                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10797                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10798                                 ensure_runtime_vtable (klass->interfaces [i]);
10799                         }
10800                         klass->interfaces_inited = 1;
10801                 }
10802         } else if (klass->generic_class){
10803                 ensure_generic_class_runtime_vtable (klass);
10804         }
10805
10806         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10807                 int slot_num = 0;
10808                 for (i = 0; i < klass->method.count; ++i) {
10809                         MonoMethod *im = klass->methods [i];
10810                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10811                                 im->slot = slot_num++;
10812                 }
10813                 
10814                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10815                 mono_class_setup_interface_offsets (klass);
10816                 mono_class_setup_interface_id (klass);
10817         }
10818
10819         /*
10820          * The generic vtable is needed even if image->run is not set since some
10821          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10822          * method->slot being defined.
10823          */
10824
10825         /* 
10826          * tb->methods could not be freed since it is used for determining 
10827          * overrides during dynamic vtable construction.
10828          */
10829 }
10830
10831 static MonoMethod*
10832 mono_reflection_method_get_handle (MonoObject *method)
10833 {
10834         MonoClass *class = mono_object_class (method);
10835         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10836                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10837                 return sr_method->method;
10838         }
10839         if (is_sre_method_builder (class)) {
10840                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10841                 return mb->mhandle;
10842         }
10843         if (is_sre_method_on_tb_inst (class)) {
10844                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10845                 MonoMethod *result;
10846                 /*FIXME move this to a proper method and unify with resolve_object*/
10847                 if (m->method_args) {
10848                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10849                 } else {
10850                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10851                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10852                         MonoMethod *mono_method;
10853
10854                         if (is_sre_method_builder (mono_object_class (m->mb)))
10855                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10856                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10857                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10858                         else
10859                                 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)));
10860
10861                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10862                 }
10863                 return result;
10864         }
10865
10866         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10867         return NULL;
10868 }
10869
10870 void
10871 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10872 {
10873         MonoReflectionTypeBuilder *tb;
10874         int i, onum;
10875
10876         *overrides = NULL;
10877         *num_overrides = 0;
10878
10879         g_assert (klass->image->dynamic);
10880
10881         if (!mono_class_get_ref_info (klass))
10882                 return;
10883
10884         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10885
10886         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10887
10888         onum = 0;
10889         if (tb->methods) {
10890                 for (i = 0; i < tb->num_methods; ++i) {
10891                         MonoReflectionMethodBuilder *mb = 
10892                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10893                         if (mb->override_method)
10894                                 onum ++;
10895                 }
10896         }
10897
10898         if (onum) {
10899                 *overrides = g_new0 (MonoMethod*, onum * 2);
10900
10901                 onum = 0;
10902                 for (i = 0; i < tb->num_methods; ++i) {
10903                         MonoReflectionMethodBuilder *mb = 
10904                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10905                         if (mb->override_method) {
10906                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10907                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10908
10909                                 g_assert (mb->mhandle);
10910
10911                                 onum ++;
10912                         }
10913                 }
10914         }
10915
10916         *num_overrides = onum;
10917 }
10918
10919 static void
10920 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10921 {
10922         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10923         MonoReflectionFieldBuilder *fb;
10924         MonoClassField *field;
10925         MonoImage *image = klass->image;
10926         const char *p, *p2;
10927         int i;
10928         guint32 len, idx, real_size = 0;
10929
10930         klass->field.count = tb->num_fields;
10931         klass->field.first = 0;
10932
10933         mono_error_init (error);
10934
10935         if (tb->class_size) {
10936                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10937                 klass->packing_size = tb->packing_size;
10938                 real_size = klass->instance_size + tb->class_size;
10939         }
10940
10941         if (!klass->field.count) {
10942                 klass->instance_size = MAX (klass->instance_size, real_size);
10943                 return;
10944         }
10945         
10946         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10947         mono_class_alloc_ext (klass);
10948         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10949         /*
10950         This is, guess what, a hack.
10951         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10952         On the static path no field class is resolved, only types are built. This is the right thing to do
10953         but we suck.
10954         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10955         */
10956         klass->size_inited = 1;
10957
10958         for (i = 0; i < klass->field.count; ++i) {
10959                 fb = mono_array_get (tb->fields, gpointer, i);
10960                 field = &klass->fields [i];
10961                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10962                 if (!mono_error_ok (error))
10963                         return;
10964                 if (fb->attrs) {
10965                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10966                         field->type->attrs = fb->attrs;
10967                 } else {
10968                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10969                 }
10970                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10971                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10972                 if (fb->offset != -1)
10973                         field->offset = fb->offset;
10974                 field->parent = klass;
10975                 fb->handle = field;
10976                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10977
10978                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10979                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10980                 }
10981                 if (fb->def_value) {
10982                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10983                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10984                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10985                         /* Copy the data from the blob since it might get realloc-ed */
10986                         p = assembly->blob.data + idx;
10987                         len = mono_metadata_decode_blob_size (p, &p2);
10988                         len += p2 - p;
10989                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10990                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10991                 }
10992         }
10993
10994         klass->instance_size = MAX (klass->instance_size, real_size);
10995         mono_class_layout_fields (klass);
10996 }
10997
10998 static void
10999 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11000 {
11001         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11002         MonoReflectionPropertyBuilder *pb;
11003         MonoImage *image = klass->image;
11004         MonoProperty *properties;
11005         int i;
11006
11007         mono_error_init (error);
11008
11009         if (!klass->ext)
11010                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11011
11012         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11013         klass->ext->property.first = 0;
11014
11015         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11016         klass->ext->properties = properties;
11017         for (i = 0; i < klass->ext->property.count; ++i) {
11018                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11019                 properties [i].parent = klass;
11020                 properties [i].attrs = pb->attrs;
11021                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11022                 if (!mono_error_ok (error))
11023                         return;
11024                 if (pb->get_method)
11025                         properties [i].get = pb->get_method->mhandle;
11026                 if (pb->set_method)
11027                         properties [i].set = pb->set_method->mhandle;
11028
11029                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11030                 if (pb->def_value) {
11031                         guint32 len, idx;
11032                         const char *p, *p2;
11033                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11034                         if (!klass->ext->prop_def_values)
11035                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11036                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11037                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11038                         /* Copy the data from the blob since it might get realloc-ed */
11039                         p = assembly->blob.data + idx;
11040                         len = mono_metadata_decode_blob_size (p, &p2);
11041                         len += p2 - p;
11042                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11043                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11044                 }
11045         }
11046 }
11047
11048 MonoReflectionEvent *
11049 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11050 {
11051         MonoEvent *event = g_new0 (MonoEvent, 1);
11052         MonoClass *klass;
11053
11054         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11055
11056         event->parent = klass;
11057         event->attrs = eb->attrs;
11058         event->name = mono_string_to_utf8 (eb->name);
11059         if (eb->add_method)
11060                 event->add = eb->add_method->mhandle;
11061         if (eb->remove_method)
11062                 event->remove = eb->remove_method->mhandle;
11063         if (eb->raise_method)
11064                 event->raise = eb->raise_method->mhandle;
11065
11066 #ifndef MONO_SMALL_CONFIG
11067         if (eb->other_methods) {
11068                 int j;
11069                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11070                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11071                         MonoReflectionMethodBuilder *mb = 
11072                                 mono_array_get (eb->other_methods,
11073                                                 MonoReflectionMethodBuilder*, j);
11074                         event->other [j] = mb->mhandle;
11075                 }
11076         }
11077 #endif
11078
11079         return mono_event_get_object (mono_object_domain (tb), klass, event);
11080 }
11081
11082 static void
11083 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11084 {
11085         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11086         MonoReflectionEventBuilder *eb;
11087         MonoImage *image = klass->image;
11088         MonoEvent *events;
11089         int i;
11090
11091         mono_error_init (error);
11092
11093         if (!klass->ext)
11094                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11095
11096         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11097         klass->ext->event.first = 0;
11098
11099         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11100         klass->ext->events = events;
11101         for (i = 0; i < klass->ext->event.count; ++i) {
11102                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11103                 events [i].parent = klass;
11104                 events [i].attrs = eb->attrs;
11105                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11106                 if (!mono_error_ok (error))
11107                         return;
11108                 if (eb->add_method)
11109                         events [i].add = eb->add_method->mhandle;
11110                 if (eb->remove_method)
11111                         events [i].remove = eb->remove_method->mhandle;
11112                 if (eb->raise_method)
11113                         events [i].raise = eb->raise_method->mhandle;
11114
11115 #ifndef MONO_SMALL_CONFIG
11116                 if (eb->other_methods) {
11117                         int j;
11118                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11119                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11120                                 MonoReflectionMethodBuilder *mb = 
11121                                         mono_array_get (eb->other_methods,
11122                                                                         MonoReflectionMethodBuilder*, j);
11123                                 events [i].other [j] = mb->mhandle;
11124                         }
11125                 }
11126 #endif
11127                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11128         }
11129 }
11130
11131 static gboolean
11132 remove_instantiations_of_and_ensure_contents (gpointer key,
11133                                                   gpointer value,
11134                                                   gpointer user_data)
11135 {
11136         MonoType *type = (MonoType*)key;
11137         MonoClass *klass = (MonoClass*)user_data;
11138
11139         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11140                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11141                 return TRUE;
11142         } else
11143                 return FALSE;
11144 }
11145
11146 static void
11147 check_array_for_usertypes (MonoArray *arr)
11148 {
11149         int i;
11150
11151         if (!arr)
11152                 return;
11153
11154         for (i = 0; i < mono_array_length (arr); ++i)
11155                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11156 }
11157
11158 MonoReflectionType*
11159 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11160 {
11161         MonoError error;
11162         MonoClass *klass;
11163         MonoDomain* domain;
11164         MonoReflectionType* res;
11165         int i, j;
11166
11167         MONO_ARCH_SAVE_REGS;
11168
11169         domain = mono_object_domain (tb);
11170         klass = mono_class_from_mono_type (tb->type.type);
11171
11172         /*
11173          * Check for user defined Type subclasses.
11174          */
11175         RESOLVE_TYPE (tb->parent);
11176         check_array_for_usertypes (tb->interfaces);
11177         if (tb->fields) {
11178                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11179                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11180                         if (fb) {
11181                                 RESOLVE_TYPE (fb->type);
11182                                 check_array_for_usertypes (fb->modreq);
11183                                 check_array_for_usertypes (fb->modopt);
11184                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11185                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11186                         }
11187                 }
11188         }
11189         if (tb->methods) {
11190                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11191                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11192                         if (mb) {
11193                                 RESOLVE_TYPE (mb->rtype);
11194                                 check_array_for_usertypes (mb->return_modreq);
11195                                 check_array_for_usertypes (mb->return_modopt);
11196                                 check_array_for_usertypes (mb->parameters);
11197                                 if (mb->param_modreq)
11198                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11199                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11200                                 if (mb->param_modopt)
11201                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11202                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11203                         }
11204                 }
11205         }
11206         if (tb->ctors) {
11207                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11208                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11209                         if (mb) {
11210                                 check_array_for_usertypes (mb->parameters);
11211                                 if (mb->param_modreq)
11212                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11213                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11214                                 if (mb->param_modopt)
11215                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11216                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11217                         }
11218                 }
11219         }
11220
11221         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11222
11223         /* 
11224          * we need to lock the domain because the lock will be taken inside
11225          * So, we need to keep the locking order correct.
11226          */
11227         mono_loader_lock ();
11228         mono_domain_lock (domain);
11229         if (klass->wastypebuilder) {
11230                 mono_domain_unlock (domain);
11231                 mono_loader_unlock ();
11232                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11233         }
11234         /*
11235          * Fields to set in klass:
11236          * the various flags: delegate/unicode/contextbound etc.
11237          */
11238         klass->flags = tb->attrs;
11239         klass->has_cctor = 1;
11240         klass->has_finalize = 1;
11241
11242         /* fool mono_class_setup_parent */
11243         klass->supertypes = NULL;
11244         mono_class_setup_parent (klass, klass->parent);
11245         mono_class_setup_mono_type (klass);
11246
11247 #if 0
11248         if (!((MonoDynamicImage*)klass->image)->run) {
11249                 if (klass->generic_container) {
11250                         /* FIXME: The code below can't handle generic classes */
11251                         klass->wastypebuilder = TRUE;
11252                         mono_loader_unlock ();
11253                         mono_domain_unlock (domain);
11254                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11255                 }
11256         }
11257 #endif
11258
11259         /* enums are done right away */
11260         if (!klass->enumtype)
11261                 ensure_runtime_vtable (klass);
11262
11263         if (tb->subtypes) {
11264                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11265                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11266                         mono_class_alloc_ext (klass);
11267                         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)));
11268                 }
11269         }
11270
11271         klass->nested_classes_inited = TRUE;
11272
11273         /* fields and object layout */
11274         if (klass->parent) {
11275                 if (!klass->parent->size_inited)
11276                         mono_class_init (klass->parent);
11277                 klass->instance_size = klass->parent->instance_size;
11278                 klass->sizes.class_size = 0;
11279                 klass->min_align = klass->parent->min_align;
11280                 /* if the type has no fields we won't call the field_setup
11281                  * routine which sets up klass->has_references.
11282                  */
11283                 klass->has_references |= klass->parent->has_references;
11284         } else {
11285                 klass->instance_size = sizeof (MonoObject);
11286                 klass->min_align = 1;
11287         }
11288
11289         /* FIXME: handle packing_size and instance_size */
11290         typebuilder_setup_fields (klass, &error);
11291         if (!mono_error_ok (&error))
11292                 goto failure;
11293         typebuilder_setup_properties (klass, &error);
11294         if (!mono_error_ok (&error))
11295                 goto failure;
11296
11297         typebuilder_setup_events (klass, &error);
11298         if (!mono_error_ok (&error))
11299                 goto failure;
11300
11301         klass->wastypebuilder = TRUE;
11302
11303         /* 
11304          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11305          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11306          * we want to return normal System.MonoType objects, so clear these out from the cache.
11307          *
11308          * Together with this we must ensure the contents of all instances to match the created type.
11309          */
11310         if (domain->type_hash && klass->generic_container)
11311                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11312
11313         mono_domain_unlock (domain);
11314         mono_loader_unlock ();
11315
11316         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11317                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11318                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11319         }
11320
11321         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11322         g_assert (res != (MonoReflectionType*)tb);
11323
11324         return res;
11325
11326 failure:
11327         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11328         klass->wastypebuilder = TRUE;
11329         mono_domain_unlock (domain);
11330         mono_loader_unlock ();
11331         mono_error_raise_exception (&error);
11332         return NULL;
11333 }
11334
11335 void
11336 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11337 {
11338         MonoGenericParamFull *param;
11339         MonoImage *image;
11340         MonoClass *pklass;
11341         MonoError error;
11342
11343         MONO_ARCH_SAVE_REGS;
11344
11345         image = &gparam->tbuilder->module->dynamic_image->image;
11346
11347         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11348
11349         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11350         g_assert (mono_error_ok (&error));
11351         param->param.num = gparam->index;
11352
11353         if (gparam->mbuilder) {
11354                 if (!gparam->mbuilder->generic_container) {
11355                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11356                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11357                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11358                         gparam->mbuilder->generic_container->is_method = TRUE;
11359                         /* 
11360                          * Cannot set owner.method, since the MonoMethod is not created yet.
11361                          * Set the image field instead, so type_in_image () works.
11362                          */
11363                         gparam->mbuilder->generic_container->image = klass->image;
11364                 }
11365                 param->param.owner = gparam->mbuilder->generic_container;
11366         } else if (gparam->tbuilder) {
11367                 if (!gparam->tbuilder->generic_container) {
11368                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11369                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11370                         gparam->tbuilder->generic_container->owner.klass = klass;
11371                 }
11372                 param->param.owner = gparam->tbuilder->generic_container;
11373         }
11374
11375         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11376
11377         gparam->type.type = &pklass->byval_arg;
11378
11379         mono_class_set_ref_info (pklass, gparam);
11380         mono_image_lock (image);
11381         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11382         mono_image_unlock (image);
11383 }
11384
11385 MonoArray *
11386 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11387 {
11388         MonoReflectionModuleBuilder *module = sig->module;
11389         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11390         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11391         guint32 buflen, i;
11392         MonoArray *result;
11393         SigBuffer buf;
11394
11395         check_array_for_usertypes (sig->arguments);
11396
11397         sigbuffer_init (&buf, 32);
11398
11399         sigbuffer_add_value (&buf, 0x07);
11400         sigbuffer_add_value (&buf, na);
11401         if (assembly != NULL){
11402                 for (i = 0; i < na; ++i) {
11403                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11404                         encode_reflection_type (assembly, type, &buf);
11405                 }
11406         }
11407
11408         buflen = buf.p - buf.buf;
11409         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11410         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11411         sigbuffer_free (&buf);
11412
11413         return result;
11414 }
11415
11416 MonoArray *
11417 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11418 {
11419         MonoDynamicImage *assembly = sig->module->dynamic_image;
11420         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11421         guint32 buflen, i;
11422         MonoArray *result;
11423         SigBuffer buf;
11424
11425         check_array_for_usertypes (sig->arguments);
11426
11427         sigbuffer_init (&buf, 32);
11428
11429         sigbuffer_add_value (&buf, 0x06);
11430         for (i = 0; i < na; ++i) {
11431                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11432                 encode_reflection_type (assembly, type, &buf);
11433         }
11434
11435         buflen = buf.p - buf.buf;
11436         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11437         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11438         sigbuffer_free (&buf);
11439
11440         return result;
11441 }
11442
11443 void 
11444 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11445 {
11446         ReflectionMethodBuilder rmb;
11447         MonoMethodSignature *sig;
11448         MonoClass *klass;
11449         GSList *l;
11450         int i;
11451
11452         sig = dynamic_method_to_signature (mb);
11453
11454         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11455
11456         /*
11457          * Resolve references.
11458          */
11459         /* 
11460          * Every second entry in the refs array is reserved for storing handle_class,
11461          * which is needed by the ldtoken implementation in the JIT.
11462          */
11463         rmb.nrefs = mb->nrefs;
11464         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11465         for (i = 0; i < mb->nrefs; i += 2) {
11466                 MonoClass *handle_class;
11467                 gpointer ref;
11468                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11469
11470                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11471                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11472                         /*
11473                          * The referenced DynamicMethod should already be created by the managed
11474                          * code, except in the case of circular references. In that case, we store
11475                          * method in the refs array, and fix it up later when the referenced 
11476                          * DynamicMethod is created.
11477                          */
11478                         if (method->mhandle) {
11479                                 ref = method->mhandle;
11480                         } else {
11481                                 /* FIXME: GC object stored in unmanaged memory */
11482                                 ref = method;
11483
11484                                 /* FIXME: GC object stored in unmanaged memory */
11485                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11486                         }
11487                         handle_class = mono_defaults.methodhandle_class;
11488                 } else {
11489                         MonoException *ex = NULL;
11490                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11491                         if (!ref)
11492                                 ex = mono_get_exception_type_load (NULL, NULL);
11493                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11494                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11495
11496                         if (ex) {
11497                                 g_free (rmb.refs);
11498                                 mono_raise_exception (ex);
11499                                 return;
11500                         }
11501                 }
11502
11503                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11504                 rmb.refs [i + 1] = handle_class;
11505         }               
11506
11507         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11508
11509         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11510
11511         /* Fix up refs entries pointing at us */
11512         for (l = mb->referenced_by; l; l = l->next) {
11513                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11514                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11515                 gpointer *data;
11516                 
11517                 g_assert (method->mhandle);
11518
11519                 data = (gpointer*)wrapper->method_data;
11520                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11521                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11522                                 data [i + 1] = mb->mhandle;
11523                 }
11524         }
11525         g_slist_free (mb->referenced_by);
11526
11527         g_free (rmb.refs);
11528
11529         /* ilgen is no longer needed */
11530         mb->ilgen = NULL;
11531 }
11532
11533 #endif /* DISABLE_REFLECTION_EMIT */
11534
11535 void
11536 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11537 {
11538         g_assert (mb);
11539
11540         if (mb->mhandle)
11541                 mono_runtime_free_method (
11542                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11543 }
11544
11545 /**
11546  * 
11547  * mono_reflection_is_valid_dynamic_token:
11548  * 
11549  * Returns TRUE if token is valid.
11550  * 
11551  */
11552 gboolean
11553 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11554 {
11555         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11556 }
11557
11558 MonoMethodSignature *
11559 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11560 {
11561         MonoMethodSignature *sig;
11562         g_assert (image->dynamic);
11563
11564         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11565         if (sig)
11566                 return sig;
11567
11568         return mono_method_signature (method);
11569 }
11570
11571 #ifndef DISABLE_REFLECTION_EMIT
11572
11573 /**
11574  * mono_reflection_lookup_dynamic_token:
11575  *
11576  * Finish the Builder object pointed to by TOKEN and return the corresponding
11577  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11578  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11579  * mapping table.
11580  *
11581  * LOCKING: Take the loader lock
11582  */
11583 gpointer
11584 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11585 {
11586         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11587         MonoObject *obj;
11588         MonoClass *klass;
11589
11590         mono_loader_lock ();
11591         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11592         mono_loader_unlock ();
11593         if (!obj) {
11594                 if (valid_token)
11595                         g_error ("Could not find required dynamic token 0x%08x", token);
11596                 else
11597                         return NULL;
11598         }
11599
11600         if (!handle_class)
11601                 handle_class = &klass;
11602         return resolve_object (image, obj, handle_class, context);
11603 }
11604
11605 /*
11606  * ensure_complete_type:
11607  *
11608  *   Ensure that KLASS is completed if it is a dynamic type, or references
11609  * dynamic types.
11610  */
11611 static void
11612 ensure_complete_type (MonoClass *klass)
11613 {
11614         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11615                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11616
11617                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11618
11619                 // Asserting here could break a lot of code
11620                 //g_assert (klass->wastypebuilder);
11621         }
11622
11623         if (klass->generic_class) {
11624                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11625                 int i;
11626
11627                 for (i = 0; i < inst->type_argc; ++i) {
11628                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11629                 }
11630         }
11631 }
11632
11633 static gpointer
11634 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11635 {
11636         gpointer result = NULL;
11637
11638         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11639                 result = mono_string_intern ((MonoString*)obj);
11640                 *handle_class = mono_defaults.string_class;
11641                 g_assert (result);
11642         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11643                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11644                 MonoClass *mc = mono_class_from_mono_type (type);
11645                 if (!mono_class_init (mc))
11646                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11647
11648                 if (context) {
11649                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11650                         result = mono_class_from_mono_type (inflated);
11651                         mono_metadata_free_type (inflated);
11652                 } else {
11653                         result = mono_class_from_mono_type (type);
11654                 }
11655                 *handle_class = mono_defaults.typehandle_class;
11656                 g_assert (result);
11657         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11658                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11659                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11660                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11661                 result = ((MonoReflectionMethod*)obj)->method;
11662                 if (context)
11663                         result = mono_class_inflate_generic_method (result, context);
11664                 *handle_class = mono_defaults.methodhandle_class;
11665                 g_assert (result);
11666         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11667                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11668                 result = mb->mhandle;
11669                 if (!result) {
11670                         /* Type is not yet created */
11671                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11672
11673                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11674
11675                         /*
11676                          * Hopefully this has been filled in by calling CreateType() on the
11677                          * TypeBuilder.
11678                          */
11679                         /*
11680                          * TODO: This won't work if the application finishes another 
11681                          * TypeBuilder instance instead of this one.
11682                          */
11683                         result = mb->mhandle;
11684                 }
11685                 if (context)
11686                         result = mono_class_inflate_generic_method (result, context);
11687                 *handle_class = mono_defaults.methodhandle_class;
11688         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11689                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11690
11691                 result = cb->mhandle;
11692                 if (!result) {
11693                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11694
11695                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11696                         result = cb->mhandle;
11697                 }
11698                 if (context)
11699                         result = mono_class_inflate_generic_method (result, context);
11700                 *handle_class = mono_defaults.methodhandle_class;
11701         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11702                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11703
11704                 ensure_complete_type (field->parent);
11705                 if (context) {
11706                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11707                         MonoClass *class = mono_class_from_mono_type (inflated);
11708                         MonoClassField *inflated_field;
11709                         gpointer iter = NULL;
11710                         mono_metadata_free_type (inflated);
11711                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11712                                 if (!strcmp (field->name, inflated_field->name))
11713                                         break;
11714                         }
11715                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11716                         result = inflated_field;
11717                 } else {
11718                         result = field;
11719                 }
11720                 *handle_class = mono_defaults.fieldhandle_class;
11721                 g_assert (result);
11722         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11723                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11724                 result = fb->handle;
11725
11726                 if (!result) {
11727                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11728
11729                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11730                         result = fb->handle;
11731                 }
11732
11733                 if (fb->handle && fb->handle->parent->generic_container) {
11734                         MonoClass *klass = fb->handle->parent;
11735                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11736                         MonoClass *inflated = mono_class_from_mono_type (type);
11737
11738                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11739                         g_assert (result);
11740                         mono_metadata_free_type (type);
11741                 }
11742                 *handle_class = mono_defaults.fieldhandle_class;
11743         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11744                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11745                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11746                 MonoClass *klass;
11747
11748                 klass = type->data.klass;
11749                 if (klass->wastypebuilder) {
11750                         /* Already created */
11751                         result = klass;
11752                 }
11753                 else {
11754                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11755                         result = type->data.klass;
11756                         g_assert (result);
11757                 }
11758                 *handle_class = mono_defaults.typehandle_class;
11759         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11760                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11761                 MonoMethodSignature *sig;
11762                 int nargs, i;
11763
11764                 if (helper->arguments)
11765                         nargs = mono_array_length (helper->arguments);
11766                 else
11767                         nargs = 0;
11768
11769                 sig = mono_metadata_signature_alloc (image, nargs);
11770                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11771                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11772
11773                 if (helper->unmanaged_call_conv) { /* unmanaged */
11774                         sig->call_convention = helper->unmanaged_call_conv - 1;
11775                         sig->pinvoke = TRUE;
11776                 } else if (helper->call_conv & 0x02) {
11777                         sig->call_convention = MONO_CALL_VARARG;
11778                 } else {
11779                         sig->call_convention = MONO_CALL_DEFAULT;
11780                 }
11781
11782                 sig->param_count = nargs;
11783                 /* TODO: Copy type ? */
11784                 sig->ret = helper->return_type->type;
11785                 for (i = 0; i < nargs; ++i)
11786                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11787
11788                 result = sig;
11789                 *handle_class = NULL;
11790         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11791                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11792                 /* Already created by the managed code */
11793                 g_assert (method->mhandle);
11794                 result = method->mhandle;
11795                 *handle_class = mono_defaults.methodhandle_class;
11796         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11797                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11798                 type = mono_class_inflate_generic_type (type, context);
11799                 result = mono_class_from_mono_type (type);
11800                 *handle_class = mono_defaults.typehandle_class;
11801                 g_assert (result);
11802                 mono_metadata_free_type (type);
11803         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11804                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11805                 type = mono_class_inflate_generic_type (type, context);
11806                 result = mono_class_from_mono_type (type);
11807                 *handle_class = mono_defaults.typehandle_class;
11808                 g_assert (result);
11809                 mono_metadata_free_type (type);
11810         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11811                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11812                 MonoClass *inflated;
11813                 MonoType *type;
11814                 MonoClassField *field;
11815
11816                 if (is_sre_field_builder (mono_object_class (f->fb)))
11817                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11818                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11819                         field = ((MonoReflectionField*)f->fb)->field;
11820                 else
11821                         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)));
11822
11823                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11824                 inflated = mono_class_from_mono_type (type);
11825
11826                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11827                 ensure_complete_type (field->parent);
11828                 g_assert (result);
11829                 mono_metadata_free_type (type);
11830                 *handle_class = mono_defaults.fieldhandle_class;
11831         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11832                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11833                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11834                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11835                 MonoMethod *method;
11836
11837                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11838                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11839                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11840                         method = ((MonoReflectionMethod *)c->cb)->method;
11841                 else
11842                         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)));
11843
11844                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11845                 *handle_class = mono_defaults.methodhandle_class;
11846                 mono_metadata_free_type (type);
11847         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11848                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11849                 if (m->method_args) {
11850                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11851                         if (context)
11852                                 result = mono_class_inflate_generic_method (result, context);
11853                 } else {
11854                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11855                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11856                         MonoMethod *method;
11857
11858                         if (is_sre_method_builder (mono_object_class (m->mb)))
11859                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11860                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11861                                 method = ((MonoReflectionMethod *)m->mb)->method;
11862                         else
11863                                 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)));
11864
11865                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11866                         mono_metadata_free_type (type);
11867                 }
11868                 *handle_class = mono_defaults.methodhandle_class;
11869         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11870                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11871                 MonoType *mtype;
11872                 MonoClass *klass;
11873                 MonoMethod *method;
11874                 gpointer iter;
11875                 char *name;
11876
11877                 mtype = mono_reflection_type_get_handle (m->parent);
11878                 klass = mono_class_from_mono_type (mtype);
11879
11880                 /* Find the method */
11881
11882                 name = mono_string_to_utf8 (m->name);
11883                 iter = NULL;
11884                 while ((method = mono_class_get_methods (klass, &iter))) {
11885                         if (!strcmp (method->name, name))
11886                                 break;
11887                 }
11888                 g_free (name);
11889
11890                 // FIXME:
11891                 g_assert (method);
11892                 // FIXME: Check parameters/return value etc. match
11893
11894                 result = method;
11895                 *handle_class = mono_defaults.methodhandle_class;
11896         } else if (is_sre_array (mono_object_get_class(obj)) ||
11897                                 is_sre_byref (mono_object_get_class(obj)) ||
11898                                 is_sre_pointer (mono_object_get_class(obj))) {
11899                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11900                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11901                 result = mono_class_from_mono_type (type);
11902                 *handle_class = mono_defaults.typehandle_class;
11903         } else {
11904                 g_print ("%s\n", obj->vtable->klass->name);
11905                 g_assert_not_reached ();
11906         }
11907         return result;
11908 }
11909
11910 #else /* DISABLE_REFLECTION_EMIT */
11911
11912 MonoArray*
11913 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11914 {
11915         g_assert_not_reached ();
11916         return NULL;
11917 }
11918
11919 void
11920 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11921 {
11922         g_assert_not_reached ();
11923 }
11924
11925 void
11926 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11927 {
11928         g_assert_not_reached ();
11929 }
11930
11931 void
11932 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11933 {
11934         g_assert_not_reached ();
11935 }
11936
11937 void
11938 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11939 {
11940         g_assert_not_reached ();
11941 }
11942
11943 void
11944 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11945 {
11946         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11947 }
11948
11949 void
11950 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11951 {
11952         g_assert_not_reached ();
11953 }
11954
11955 void
11956 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11957 {
11958         g_assert_not_reached ();
11959 }
11960
11961 MonoReflectionModule *
11962 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11963 {
11964         g_assert_not_reached ();
11965         return NULL;
11966 }
11967
11968 guint32
11969 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11970 {
11971         g_assert_not_reached ();
11972         return 0;
11973 }
11974
11975 guint32
11976 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11977 {
11978         g_assert_not_reached ();
11979         return 0;
11980 }
11981
11982 guint32
11983 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11984                                                  gboolean create_open_instance, gboolean register_token)
11985 {
11986         g_assert_not_reached ();
11987         return 0;
11988 }
11989
11990 void
11991 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11992 {
11993 }
11994
11995 void
11996 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11997                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11998                                           MonoArray *events)
11999 {
12000         g_assert_not_reached ();
12001 }
12002
12003 void
12004 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12005 {
12006         *overrides = NULL;
12007         *num_overrides = 0;
12008 }
12009
12010 MonoReflectionEvent *
12011 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12012 {
12013         g_assert_not_reached ();
12014         return NULL;
12015 }
12016
12017 MonoReflectionType*
12018 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12019 {
12020         g_assert_not_reached ();
12021         return NULL;
12022 }
12023
12024 void
12025 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12026 {
12027         g_assert_not_reached ();
12028 }
12029
12030 MonoArray *
12031 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12032 {
12033         g_assert_not_reached ();
12034         return NULL;
12035 }
12036
12037 MonoArray *
12038 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12039 {
12040         g_assert_not_reached ();
12041         return NULL;
12042 }
12043
12044 void 
12045 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12046 {
12047 }
12048
12049 gpointer
12050 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12051 {
12052         return NULL;
12053 }
12054
12055 MonoType*
12056 mono_reflection_type_get_handle (MonoReflectionType* ref)
12057 {
12058         if (!ref)
12059                 return NULL;
12060         return ref->type;
12061 }
12062
12063 void
12064 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12065 {
12066         g_assert_not_reached ();
12067 }
12068
12069 #endif /* DISABLE_REFLECTION_EMIT */
12070
12071 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12072 const static guint32 declsec_flags_map[] = {
12073         0x00000000,                                     /* empty */
12074         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12075         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12076         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12077         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12078         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12079         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12080         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12081         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12082         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12083         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12084         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12085         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12086         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12087         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12088         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12089         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12090         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12091         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12092 };
12093
12094 /*
12095  * Returns flags that includes all available security action associated to the handle.
12096  * @token: metadata token (either for a class or a method)
12097  * @image: image where resides the metadata.
12098  */
12099 static guint32
12100 mono_declsec_get_flags (MonoImage *image, guint32 token)
12101 {
12102         int index = mono_metadata_declsec_from_index (image, token);
12103         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12104         guint32 result = 0;
12105         guint32 action;
12106         int i;
12107
12108         /* HasSecurity can be present for other, not specially encoded, attributes,
12109            e.g. SuppressUnmanagedCodeSecurityAttribute */
12110         if (index < 0)
12111                 return 0;
12112
12113         for (i = index; i < t->rows; i++) {
12114                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12115
12116                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12117                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12118                         break;
12119
12120                 action = cols [MONO_DECL_SECURITY_ACTION];
12121                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12122                         result |= declsec_flags_map [action];
12123                 } else {
12124                         g_assert_not_reached ();
12125                 }
12126         }
12127         return result;
12128 }
12129
12130 /*
12131  * Get the security actions (in the form of flags) associated with the specified method.
12132  *
12133  * @method: The method for which we want the declarative security flags.
12134  * Return the declarative security flags for the method (only).
12135  *
12136  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12137  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12138  */
12139 guint32
12140 mono_declsec_flags_from_method (MonoMethod *method)
12141 {
12142         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12143                 /* FIXME: No cache (for the moment) */
12144                 guint32 idx = mono_method_get_index (method);
12145                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12146                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12147                 return mono_declsec_get_flags (method->klass->image, idx);
12148         }
12149         return 0;
12150 }
12151
12152 /*
12153  * Get the security actions (in the form of flags) associated with the specified class.
12154  *
12155  * @klass: The class for which we want the declarative security flags.
12156  * Return the declarative security flags for the class.
12157  *
12158  * Note: We cache the flags inside the MonoClass structure as this will get 
12159  *       called very often (at least for each method).
12160  */
12161 guint32
12162 mono_declsec_flags_from_class (MonoClass *klass)
12163 {
12164         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12165                 if (!klass->ext || !klass->ext->declsec_flags) {
12166                         guint32 idx;
12167
12168                         idx = mono_metadata_token_index (klass->type_token);
12169                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12170                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12171                         mono_loader_lock ();
12172                         mono_class_alloc_ext (klass);
12173                         mono_loader_unlock ();
12174                         /* we cache the flags on classes */
12175                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12176                 }
12177                 return klass->ext->declsec_flags;
12178         }
12179         return 0;
12180 }
12181
12182 /*
12183  * Get the security actions (in the form of flags) associated with the specified assembly.
12184  *
12185  * @assembly: The assembly for which we want the declarative security flags.
12186  * Return the declarative security flags for the assembly.
12187  */
12188 guint32
12189 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12190 {
12191         guint32 idx = 1; /* there is only one assembly */
12192         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12193         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12194         return mono_declsec_get_flags (assembly->image, idx);
12195 }
12196
12197
12198 /*
12199  * Fill actions for the specific index (which may either be an encoded class token or
12200  * an encoded method token) from the metadata image.
12201  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12202  */
12203 static MonoBoolean
12204 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12205         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12206 {
12207         MonoBoolean result = FALSE;
12208         MonoTableInfo *t;
12209         guint32 cols [MONO_DECL_SECURITY_SIZE];
12210         int index = mono_metadata_declsec_from_index (image, token);
12211         int i;
12212
12213         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12214         for (i = index; i < t->rows; i++) {
12215                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12216
12217                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12218                         return result;
12219
12220                 /* if present only replace (class) permissions with method permissions */
12221                 /* if empty accept either class or method permissions */
12222                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12223                         if (!actions->demand.blob) {
12224                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12225                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12226                                 actions->demand.blob = (char*) (blob + 2);
12227                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12228                                 result = TRUE;
12229                         }
12230                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12231                         if (!actions->noncasdemand.blob) {
12232                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12233                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12234                                 actions->noncasdemand.blob = (char*) (blob + 2);
12235                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12236                                 result = TRUE;
12237                         }
12238                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12239                         if (!actions->demandchoice.blob) {
12240                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12241                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12242                                 actions->demandchoice.blob = (char*) (blob + 2);
12243                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12244                                 result = TRUE;
12245                         }
12246                 }
12247         }
12248
12249         return result;
12250 }
12251
12252 static MonoBoolean
12253 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12254         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12255 {
12256         guint32 idx = mono_metadata_token_index (klass->type_token);
12257         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12258         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12259         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12260 }
12261
12262 static MonoBoolean
12263 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12264         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12265 {
12266         guint32 idx = mono_method_get_index (method);
12267         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12268         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12269         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12270 }
12271
12272 /*
12273  * Collect all actions (that requires to generate code in mini) assigned for
12274  * the specified method.
12275  * Note: Don't use the content of actions if the function return FALSE.
12276  */
12277 MonoBoolean
12278 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12279 {
12280         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12281                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12282         MonoBoolean result = FALSE;
12283         guint32 flags;
12284
12285         /* quick exit if no declarative security is present in the metadata */
12286         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12287                 return FALSE;
12288
12289         /* we want the original as the wrapper is "free" of the security informations */
12290         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12291                 method = mono_marshal_method_from_wrapper (method);
12292                 if (!method)
12293                         return FALSE;
12294         }
12295
12296         /* First we look for method-level attributes */
12297         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12298                 mono_class_init (method->klass);
12299                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12300
12301                 result = mono_declsec_get_method_demands_params (method, demands, 
12302                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12303         }
12304
12305         /* Here we use (or create) the class declarative cache to look for demands */
12306         flags = mono_declsec_flags_from_class (method->klass);
12307         if (flags & mask) {
12308                 if (!result) {
12309                         mono_class_init (method->klass);
12310                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12311                 }
12312                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12313                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12314         }
12315
12316         /* The boolean return value is used as a shortcut in case nothing needs to
12317            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12318         return result;
12319 }
12320
12321
12322 /*
12323  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12324  *
12325  * Note: Don't use the content of actions if the function return FALSE.
12326  */
12327 MonoBoolean
12328 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12329 {
12330         MonoBoolean result = FALSE;
12331         guint32 flags;
12332
12333         /* quick exit if no declarative security is present in the metadata */
12334         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12335                 return FALSE;
12336
12337         /* we want the original as the wrapper is "free" of the security informations */
12338         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12339                 method = mono_marshal_method_from_wrapper (method);
12340                 if (!method)
12341                         return FALSE;
12342         }
12343
12344         /* results are independant - zeroize both */
12345         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12346         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12347
12348         /* First we look for method-level attributes */
12349         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12350                 mono_class_init (method->klass);
12351
12352                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12353                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12354         }
12355
12356         /* Here we use (or create) the class declarative cache to look for demands */
12357         flags = mono_declsec_flags_from_class (method->klass);
12358         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12359                 mono_class_init (method->klass);
12360
12361                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12362                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12363         }
12364
12365         return result;
12366 }
12367
12368 /*
12369  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12370  *
12371  * @klass       The inherited class - this is the class that provides the security check (attributes)
12372  * @demans      
12373  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12374  * 
12375  * Note: Don't use the content of actions if the function return FALSE.
12376  */
12377 MonoBoolean
12378 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12379 {
12380         MonoBoolean result = FALSE;
12381         guint32 flags;
12382
12383         /* quick exit if no declarative security is present in the metadata */
12384         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12385                 return FALSE;
12386
12387         /* Here we use (or create) the class declarative cache to look for demands */
12388         flags = mono_declsec_flags_from_class (klass);
12389         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12390                 mono_class_init (klass);
12391                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12392
12393                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12394                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12395         }
12396
12397         return result;
12398 }
12399
12400 /*
12401  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12402  *
12403  * Note: Don't use the content of actions if the function return FALSE.
12404  */
12405 MonoBoolean
12406 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12407 {
12408         /* quick exit if no declarative security is present in the metadata */
12409         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12410                 return FALSE;
12411
12412         /* we want the original as the wrapper is "free" of the security informations */
12413         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12414                 method = mono_marshal_method_from_wrapper (method);
12415                 if (!method)
12416                         return FALSE;
12417         }
12418
12419         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12420                 mono_class_init (method->klass);
12421                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12422
12423                 return mono_declsec_get_method_demands_params (method, demands, 
12424                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12425         }
12426         return FALSE;
12427 }
12428
12429
12430 static MonoBoolean
12431 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12432 {
12433         guint32 cols [MONO_DECL_SECURITY_SIZE];
12434         MonoTableInfo *t;
12435         int i;
12436
12437         int index = mono_metadata_declsec_from_index (image, token);
12438         if (index == -1)
12439                 return FALSE;
12440
12441         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12442         for (i = index; i < t->rows; i++) {
12443                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12444
12445                 /* shortcut - index are ordered */
12446                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12447                         return FALSE;
12448
12449                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12450                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12451                         entry->blob = (char*) (metadata + 2);
12452                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12453                         return TRUE;
12454                 }
12455         }
12456
12457         return FALSE;
12458 }
12459
12460 MonoBoolean
12461 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12462 {
12463         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12464                 guint32 idx = mono_method_get_index (method);
12465                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12466                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12467                 return get_declsec_action (method->klass->image, idx, action, entry);
12468         }
12469         return FALSE;
12470 }
12471
12472 MonoBoolean
12473 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12474 {
12475         /* use cache */
12476         guint32 flags = mono_declsec_flags_from_class (klass);
12477         if (declsec_flags_map [action] & flags) {
12478                 guint32 idx = mono_metadata_token_index (klass->type_token);
12479                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12480                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12481                 return get_declsec_action (klass->image, idx, action, entry);
12482         }
12483         return FALSE;
12484 }
12485
12486 MonoBoolean
12487 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12488 {
12489         guint32 idx = 1; /* there is only one assembly */
12490         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12491         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12492
12493         return get_declsec_action (assembly->image, idx, action, entry);
12494 }
12495
12496 gboolean
12497 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12498 {
12499         MonoObject *res, *exc;
12500         void *params [1];
12501         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12502         static MonoMethod *method = NULL;
12503
12504         if (!System_Reflection_Emit_TypeBuilder) {
12505                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12506                 g_assert (System_Reflection_Emit_TypeBuilder);
12507         }
12508         if (method == NULL) {
12509                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12510                 g_assert (method);
12511         }
12512
12513         /* 
12514          * The result of mono_type_get_object () might be a System.MonoType but we
12515          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12516          */
12517         g_assert (mono_class_get_ref_info (klass));
12518         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12519
12520         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12521
12522         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12523         if (exc)
12524                 return FALSE;
12525         else
12526                 return *(MonoBoolean*)mono_object_unbox (res);
12527 }