Rewrite of core coder & decoder functions to fix several bugs and limitations, and...
[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  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internal.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internal.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46
47 static gboolean is_usertype (MonoReflectionType *ref);
48 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
49
50 typedef struct {
51         char *p;
52         char *buf;
53         char *end;
54 } SigBuffer;
55
56 #define TEXT_OFFSET 512
57 #define CLI_H_SIZE 136
58 #define FILE_ALIGN 512
59 #define VIRT_ALIGN 8192
60 #define START_TEXT_RVA  0x00002000
61
62 typedef struct {
63         MonoReflectionILGen *ilgen;
64         MonoReflectionType *rtype;
65         MonoArray *parameters;
66         MonoArray *generic_params;
67         MonoGenericContainer *generic_container;
68         MonoArray *pinfo;
69         MonoArray *opt_types;
70         guint32 attrs;
71         guint32 iattrs;
72         guint32 call_conv;
73         guint32 *table_idx; /* note: it's a pointer */
74         MonoArray *code;
75         MonoObject *type;
76         MonoString *name;
77         MonoBoolean init_locals;
78         MonoBoolean skip_visibility;
79         MonoArray *return_modreq;
80         MonoArray *return_modopt;
81         MonoArray *param_modreq;
82         MonoArray *param_modopt;
83         MonoArray *permissions;
84         MonoMethod *mhandle;
85         guint32 nrefs;
86         gpointer *refs;
87         /* for PInvoke */
88         int charset, extra_flags, native_cc;
89         MonoString *dll, *dllentry;
90 } ReflectionMethodBuilder;
91
92 typedef struct {
93         guint32 owner;
94         MonoReflectionGenericParam *gparam;
95 } GenericParamTableEntry;
96
97 const unsigned char table_sizes [MONO_TABLE_NUM] = {
98         MONO_MODULE_SIZE,
99         MONO_TYPEREF_SIZE,
100         MONO_TYPEDEF_SIZE,
101         0,
102         MONO_FIELD_SIZE,
103         0,
104         MONO_METHOD_SIZE,
105         0,
106         MONO_PARAM_SIZE,
107         MONO_INTERFACEIMPL_SIZE,
108         MONO_MEMBERREF_SIZE,    /* 0x0A */
109         MONO_CONSTANT_SIZE,
110         MONO_CUSTOM_ATTR_SIZE,
111         MONO_FIELD_MARSHAL_SIZE,
112         MONO_DECL_SECURITY_SIZE,
113         MONO_CLASS_LAYOUT_SIZE,
114         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
115         MONO_STAND_ALONE_SIGNATURE_SIZE,
116         MONO_EVENT_MAP_SIZE,
117         0,
118         MONO_EVENT_SIZE,
119         MONO_PROPERTY_MAP_SIZE,
120         0,
121         MONO_PROPERTY_SIZE,
122         MONO_METHOD_SEMA_SIZE,
123         MONO_METHODIMPL_SIZE,
124         MONO_MODULEREF_SIZE,    /* 0x1A */
125         MONO_TYPESPEC_SIZE,
126         MONO_IMPLMAP_SIZE,      
127         MONO_FIELD_RVA_SIZE,
128         0,
129         0,
130         MONO_ASSEMBLY_SIZE,     /* 0x20 */
131         MONO_ASSEMBLY_PROCESSOR_SIZE,
132         MONO_ASSEMBLYOS_SIZE,
133         MONO_ASSEMBLYREF_SIZE,
134         MONO_ASSEMBLYREFPROC_SIZE,
135         MONO_ASSEMBLYREFOS_SIZE,
136         MONO_FILE_SIZE,
137         MONO_EXP_TYPE_SIZE,
138         MONO_MANIFEST_SIZE,
139         MONO_NESTED_CLASS_SIZE,
140
141         MONO_GENERICPARAM_SIZE, /* 0x2A */
142         MONO_METHODSPEC_SIZE,
143         MONO_GENPARCONSTRAINT_SIZE
144
145 };
146
147 #ifndef DISABLE_REFLECTION_EMIT
148 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
149 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance);
150 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
151 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
152 static void    ensure_runtime_vtable (MonoClass *klass);
153 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
154 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
155 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
156 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
157 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
158 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
159 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
160 #endif
161
162 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
163 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
164 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
165 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
166 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
167 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
168 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
169 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
170 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
171 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
172 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
173 static gboolean is_sre_array (MonoClass *class);
174 static gboolean is_sre_byref (MonoClass *class);
175 static gboolean is_sre_pointer (MonoClass *class);
176 static gboolean is_sre_type_builder (MonoClass *class);
177 static gboolean is_sre_method_builder (MonoClass *class);
178 static gboolean is_sre_ctor_builder (MonoClass *class);
179 static gboolean is_sre_field_builder (MonoClass *class);
180 static gboolean is_sr_mono_method (MonoClass *class);
181 static gboolean is_sr_mono_cmethod (MonoClass *class);
182 static gboolean is_sr_mono_generic_method (MonoClass *class);
183 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
184 static gboolean is_sr_mono_field (MonoClass *class);
185 static gboolean is_sr_mono_property (MonoClass *class);
186 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
187 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
188
189 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
190 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
191 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
192
193 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
194 static void init_type_builder_generics (MonoObject *type);
195
196 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
197 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
198         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
199         __type = mono_reflection_type_resolve_user_types (__type);      \
200         mono_array_set (arr, MonoReflectionType*, index, __type);       \
201 } while (0)
202
203 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
204
205 void
206 mono_reflection_init (void)
207 {
208 }
209
210 static void
211 sigbuffer_init (SigBuffer *buf, int size)
212 {
213         buf->buf = g_malloc (size);
214         buf->p = buf->buf;
215         buf->end = buf->buf + size;
216 }
217
218 static void
219 sigbuffer_make_room (SigBuffer *buf, int size)
220 {
221         if (buf->end - buf->p < size) {
222                 int new_size = buf->end - buf->buf + size + 32;
223                 char *p = g_realloc (buf->buf, new_size);
224                 size = buf->p - buf->buf;
225                 buf->buf = p;
226                 buf->p = p + size;
227                 buf->end = buf->buf + new_size;
228         }
229 }
230
231 static void
232 sigbuffer_add_value (SigBuffer *buf, guint32 val)
233 {
234         sigbuffer_make_room (buf, 6);
235         mono_metadata_encode_value (val, buf->p, &buf->p);
236 }
237
238 static void
239 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
240 {
241         sigbuffer_make_room (buf, 1);
242         buf->p [0] = val;
243         buf->p++;
244 }
245
246 static void
247 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
248 {
249         sigbuffer_make_room (buf, size);
250         memcpy (buf->p, p, size);
251         buf->p += size;
252 }
253
254 static void
255 sigbuffer_free (SigBuffer *buf)
256 {
257         g_free (buf->buf);
258 }
259
260 #ifndef DISABLE_REFLECTION_EMIT
261 /**
262  * mp_g_alloc:
263  *
264  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
265  * from the C heap.
266  */
267 static gpointer
268 image_g_malloc (MonoImage *image, guint size)
269 {
270         if (image)
271                 return mono_image_alloc (image, size);
272         else
273                 return g_malloc (size);
274 }
275 #endif /* !DISABLE_REFLECTION_EMIT */
276
277 /**
278  * image_g_alloc0:
279  *
280  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
281  * from the C heap.
282  */
283 static gpointer
284 image_g_malloc0 (MonoImage *image, guint size)
285 {
286         if (image)
287                 return mono_image_alloc0 (image, size);
288         else
289                 return g_malloc0 (size);
290 }
291
292 #ifndef DISABLE_REFLECTION_EMIT
293 static char*
294 image_strdup (MonoImage *image, const char *s)
295 {
296         if (image)
297                 return mono_image_strdup (image, s);
298         else
299                 return g_strdup (s);
300 }
301 #endif
302
303 #define image_g_new(image,struct_type, n_structs)               \
304     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
305
306 #define image_g_new0(image,struct_type, n_structs)              \
307     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
308
309
310 static void
311 alloc_table (MonoDynamicTable *table, guint nrows)
312 {
313         table->rows = nrows;
314         g_assert (table->columns);
315         if (nrows + 1 >= table->alloc_rows) {
316                 while (nrows + 1 >= table->alloc_rows) {
317                         if (table->alloc_rows == 0)
318                                 table->alloc_rows = 16;
319                         else
320                                 table->alloc_rows *= 2;
321                 }
322
323                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
324         }
325 }
326
327 static void
328 make_room_in_stream (MonoDynamicStream *stream, int size)
329 {
330         if (size <= stream->alloc_size)
331                 return;
332         
333         while (stream->alloc_size <= size) {
334                 if (stream->alloc_size < 4096)
335                         stream->alloc_size = 4096;
336                 else
337                         stream->alloc_size *= 2;
338         }
339         
340         stream->data = g_realloc (stream->data, stream->alloc_size);
341 }
342
343 static guint32
344 string_heap_insert (MonoDynamicStream *sh, const char *str)
345 {
346         guint32 idx;
347         guint32 len;
348         gpointer oldkey, oldval;
349
350         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
351                 return GPOINTER_TO_UINT (oldval);
352
353         len = strlen (str) + 1;
354         idx = sh->index;
355         
356         make_room_in_stream (sh, idx + len);
357
358         /*
359          * We strdup the string even if we already copy them in sh->data
360          * so that the string pointers in the hash remain valid even if
361          * we need to realloc sh->data. We may want to avoid that later.
362          */
363         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
364         memcpy (sh->data + idx, str, len);
365         sh->index += len;
366         return idx;
367 }
368
369 static guint32
370 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
371 {
372         char *name = mono_string_to_utf8 (str);
373         guint32 idx;
374         idx = string_heap_insert (sh, name);
375         g_free (name);
376         return idx;
377 }
378
379 #ifndef DISABLE_REFLECTION_EMIT
380 static void
381 string_heap_init (MonoDynamicStream *sh)
382 {
383         sh->index = 0;
384         sh->alloc_size = 4096;
385         sh->data = g_malloc (4096);
386         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
387         string_heap_insert (sh, "");
388 }
389 #endif
390
391 static guint32
392 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
393 {
394         guint32 idx;
395         
396         make_room_in_stream (stream, stream->index + len);
397         memcpy (stream->data + stream->index, data, len);
398         idx = stream->index;
399         stream->index += len;
400         /* 
401          * align index? Not without adding an additional param that controls it since
402          * we may store a blob value in pieces.
403          */
404         return idx;
405 }
406
407 static guint32
408 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
409 {
410         guint32 idx;
411         
412         make_room_in_stream (stream, stream->index + len);
413         memset (stream->data + stream->index, 0, len);
414         idx = stream->index;
415         stream->index += len;
416         return idx;
417 }
418
419 static void
420 stream_data_align (MonoDynamicStream *stream)
421 {
422         char buf [4] = {0};
423         guint32 count = stream->index % 4;
424
425         /* we assume the stream data will be aligned */
426         if (count)
427                 mono_image_add_stream_data (stream, buf, 4 - count);
428 }
429
430 #ifndef DISABLE_REFLECTION_EMIT
431 static int
432 mono_blob_entry_hash (const char* str)
433 {
434         guint len, h;
435         const char *end;
436         len = mono_metadata_decode_blob_size (str, &str);
437         if (len > 0) {
438                 end = str + len;
439                 h = *str;
440                 for (str += 1; str < end; str++)
441                         h = (h << 5) - h + *str;
442                 return h;
443         } else {
444                 return 0;
445         }
446 }
447
448 static gboolean
449 mono_blob_entry_equal (const char *str1, const char *str2) {
450         int len, len2;
451         const char *end1;
452         const char *end2;
453         len = mono_metadata_decode_blob_size (str1, &end1);
454         len2 = mono_metadata_decode_blob_size (str2, &end2);
455         if (len != len2)
456                 return 0;
457         return memcmp (end1, end2, len) == 0;
458 }
459 #endif
460 static guint32
461 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
462 {
463         guint32 idx;
464         char *copy;
465         gpointer oldkey, oldval;
466
467         copy = g_malloc (s1+s2);
468         memcpy (copy, b1, s1);
469         memcpy (copy + s1, b2, s2);
470         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
471                 g_free (copy);
472                 idx = GPOINTER_TO_UINT (oldval);
473         } else {
474                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
475                 mono_image_add_stream_data (&assembly->blob, b2, s2);
476                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
477         }
478         return idx;
479 }
480
481 static guint32
482 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
483 {
484         char blob_size [8];
485         char *b = blob_size;
486         guint32 size = buf->p - buf->buf;
487         /* store length */
488         g_assert (size <= (buf->end - buf->buf));
489         mono_metadata_encode_value (size, b, &b);
490         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
491 }
492
493 /*
494  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
495  * dest may be misaligned.
496  */
497 static void
498 swap_with_size (char *dest, const char* val, int len, int nelem) {
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
500         int elem;
501
502         for (elem = 0; elem < nelem; ++elem) {
503                 switch (len) {
504                 case 1:
505                         *dest = *val;
506                         break;
507                 case 2:
508                         dest [0] = val [1];
509                         dest [1] = val [0];
510                         break;
511                 case 4:
512                         dest [0] = val [3];
513                         dest [1] = val [2];
514                         dest [2] = val [1];
515                         dest [3] = val [0];
516                         break;
517                 case 8:
518                         dest [0] = val [7];
519                         dest [1] = val [6];
520                         dest [2] = val [5];
521                         dest [3] = val [4];
522                         dest [4] = val [3];
523                         dest [5] = val [2];
524                         dest [6] = val [1];
525                         dest [7] = val [0];
526                         break;
527                 default:
528                         g_assert_not_reached ();
529                 }
530                 dest += len;
531                 val += len;
532         }
533 #else
534         memcpy (dest, val, len * nelem);
535 #endif
536 }
537
538 static guint32
539 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
540 {
541         char blob_size [64];
542         char *b = blob_size;
543         guint32 idx = 0, len;
544
545         len = str->length * 2;
546         mono_metadata_encode_value (len, b, &b);
547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
548         {
549                 char *swapped = g_malloc (2 * mono_string_length (str));
550                 const char *p = (const char*)mono_string_chars (str);
551
552                 swap_with_size (swapped, p, 2, mono_string_length (str));
553                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
554                 g_free (swapped);
555         }
556 #else
557         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
558 #endif
559         return idx;
560 }
561
562 #ifndef DISABLE_REFLECTION_EMIT
563 static MonoClass *
564 default_class_from_mono_type (MonoType *type)
565 {
566         switch (type->type) {
567         case MONO_TYPE_OBJECT:
568                 return mono_defaults.object_class;
569         case MONO_TYPE_VOID:
570                 return mono_defaults.void_class;
571         case MONO_TYPE_BOOLEAN:
572                 return mono_defaults.boolean_class;
573         case MONO_TYPE_CHAR:
574                 return mono_defaults.char_class;
575         case MONO_TYPE_I1:
576                 return mono_defaults.sbyte_class;
577         case MONO_TYPE_U1:
578                 return mono_defaults.byte_class;
579         case MONO_TYPE_I2:
580                 return mono_defaults.int16_class;
581         case MONO_TYPE_U2:
582                 return mono_defaults.uint16_class;
583         case MONO_TYPE_I4:
584                 return mono_defaults.int32_class;
585         case MONO_TYPE_U4:
586                 return mono_defaults.uint32_class;
587         case MONO_TYPE_I:
588                 return mono_defaults.int_class;
589         case MONO_TYPE_U:
590                 return mono_defaults.uint_class;
591         case MONO_TYPE_I8:
592                 return mono_defaults.int64_class;
593         case MONO_TYPE_U8:
594                 return mono_defaults.uint64_class;
595         case MONO_TYPE_R4:
596                 return mono_defaults.single_class;
597         case MONO_TYPE_R8:
598                 return mono_defaults.double_class;
599         case MONO_TYPE_STRING:
600                 return mono_defaults.string_class;
601         default:
602                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
603                 g_assert_not_reached ();
604         }
605         
606         return NULL;
607 }
608 #endif
609
610 /*
611  * mono_class_get_ref_info:
612  *
613  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
614  */
615 gpointer
616 mono_class_get_ref_info (MonoClass *klass)
617 {
618         if (klass->ref_info_handle == 0)
619                 return NULL;
620         else
621                 return mono_gchandle_get_target (klass->ref_info_handle);
622 }
623
624 void
625 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
626 {
627         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
628         g_assert (klass->ref_info_handle != 0);
629 }
630
631 void
632 mono_class_free_ref_info (MonoClass *klass)
633 {
634         if (klass->ref_info_handle) {
635                 mono_gchandle_free (klass->ref_info_handle);
636                 klass->ref_info_handle = 0;
637         }
638 }
639
640 static void
641 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
642 {
643         int i;
644         MonoGenericInst *class_inst;
645         MonoClass *klass;
646
647         g_assert (gclass);
648
649         class_inst = gclass->context.class_inst;
650
651         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
652         klass = gclass->container_class;
653         sigbuffer_add_value (buf, klass->byval_arg.type);
654         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
655
656         sigbuffer_add_value (buf, class_inst->type_argc);
657         for (i = 0; i < class_inst->type_argc; ++i)
658                 encode_type (assembly, class_inst->type_argv [i], buf);
659
660 }
661
662 static void
663 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
664 {
665         if (!type) {
666                 g_assert_not_reached ();
667                 return;
668         }
669                 
670         if (type->byref)
671                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
672
673         switch (type->type){
674         case MONO_TYPE_VOID:
675         case MONO_TYPE_BOOLEAN:
676         case MONO_TYPE_CHAR:
677         case MONO_TYPE_I1:
678         case MONO_TYPE_U1:
679         case MONO_TYPE_I2:
680         case MONO_TYPE_U2:
681         case MONO_TYPE_I4:
682         case MONO_TYPE_U4:
683         case MONO_TYPE_I8:
684         case MONO_TYPE_U8:
685         case MONO_TYPE_R4:
686         case MONO_TYPE_R8:
687         case MONO_TYPE_I:
688         case MONO_TYPE_U:
689         case MONO_TYPE_STRING:
690         case MONO_TYPE_OBJECT:
691         case MONO_TYPE_TYPEDBYREF:
692                 sigbuffer_add_value (buf, type->type);
693                 break;
694         case MONO_TYPE_PTR:
695                 sigbuffer_add_value (buf, type->type);
696                 encode_type (assembly, type->data.type, buf);
697                 break;
698         case MONO_TYPE_SZARRAY:
699                 sigbuffer_add_value (buf, type->type);
700                 encode_type (assembly, &type->data.klass->byval_arg, buf);
701                 break;
702         case MONO_TYPE_VALUETYPE:
703         case MONO_TYPE_CLASS: {
704                 MonoClass *k = mono_class_from_mono_type (type);
705
706                 if (k->generic_container) {
707                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
708                         encode_generic_class (assembly, gclass, buf);
709                 } else {
710                         /*
711                          * Make sure we use the correct type.
712                          */
713                         sigbuffer_add_value (buf, k->byval_arg.type);
714                         /*
715                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
716                          * otherwise two typerefs could point to the same type, leading to
717                          * verification errors.
718                          */
719                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
720                 }
721                 break;
722         }
723         case MONO_TYPE_ARRAY:
724                 sigbuffer_add_value (buf, type->type);
725                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
726                 sigbuffer_add_value (buf, type->data.array->rank);
727                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
728                 sigbuffer_add_value (buf, 0);
729                 break;
730         case MONO_TYPE_GENERICINST:
731                 encode_generic_class (assembly, type->data.generic_class, buf);
732                 break;
733         case MONO_TYPE_VAR:
734         case MONO_TYPE_MVAR:
735                 sigbuffer_add_value (buf, type->type);
736                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
737                 break;
738         default:
739                 g_error ("need to encode type %x", type->type);
740         }
741 }
742
743 static void
744 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
745 {
746         if (!type) {
747                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
748                 return;
749         }
750
751         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
752 }
753
754 static void
755 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
756 {
757         int i;
758
759         if (modreq) {
760                 for (i = 0; i < mono_array_length (modreq); ++i) {
761                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
762                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
763                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
764                 }
765         }
766         if (modopt) {
767                 for (i = 0; i < mono_array_length (modopt); ++i) {
768                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
769                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
770                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
771                 }
772         }
773 }
774
775 #ifndef DISABLE_REFLECTION_EMIT
776 static guint32
777 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
778 {
779         SigBuffer buf;
780         int i;
781         guint32 nparams =  sig->param_count;
782         guint32 idx;
783
784         if (!assembly->save)
785                 return 0;
786
787         sigbuffer_init (&buf, 32);
788         /*
789          * FIXME: vararg, explicit_this, differenc call_conv values...
790          */
791         idx = sig->call_convention;
792         if (sig->hasthis)
793                 idx |= 0x20; /* hasthis */
794         if (sig->generic_param_count)
795                 idx |= 0x10; /* generic */
796         sigbuffer_add_byte (&buf, idx);
797         if (sig->generic_param_count)
798                 sigbuffer_add_value (&buf, sig->generic_param_count);
799         sigbuffer_add_value (&buf, nparams);
800         encode_type (assembly, sig->ret, &buf);
801         for (i = 0; i < nparams; ++i) {
802                 if (i == sig->sentinelpos)
803                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
804                 encode_type (assembly, sig->params [i], &buf);
805         }
806         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807         sigbuffer_free (&buf);
808         return idx;
809 }
810 #endif
811
812 static guint32
813 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
814 {
815         /*
816          * FIXME: reuse code from method_encode_signature().
817          */
818         SigBuffer buf;
819         int i;
820         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
821         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
822         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
823         guint32 idx;
824
825         sigbuffer_init (&buf, 32);
826         /* LAMESPEC: all the call conv spec is foobared */
827         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
828         if (mb->call_conv & 2)
829                 idx |= 0x5; /* vararg */
830         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
831                 idx |= 0x20; /* hasthis */
832         if (ngparams)
833                 idx |= 0x10; /* generic */
834         sigbuffer_add_byte (&buf, idx);
835         if (ngparams)
836                 sigbuffer_add_value (&buf, ngparams);
837         sigbuffer_add_value (&buf, nparams + notypes);
838         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
839         encode_reflection_type (assembly, mb->rtype, &buf);
840         for (i = 0; i < nparams; ++i) {
841                 MonoArray *modreq = NULL;
842                 MonoArray *modopt = NULL;
843                 MonoReflectionType *pt;
844
845                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
846                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
847                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
848                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
849                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
850                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
851                 encode_reflection_type (assembly, pt, &buf);
852         }
853         if (notypes)
854                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
855         for (i = 0; i < notypes; ++i) {
856                 MonoReflectionType *pt;
857
858                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
859                 encode_reflection_type (assembly, pt, &buf);
860         }
861
862         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
863         sigbuffer_free (&buf);
864         return idx;
865 }
866
867 static guint32
868 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
869 {
870         MonoDynamicTable *table;
871         guint32 *values;
872         guint32 idx, sig_idx;
873         guint nl = mono_array_length (ilgen->locals);
874         SigBuffer buf;
875         int i;
876
877         sigbuffer_init (&buf, 32);
878         sigbuffer_add_value (&buf, 0x07);
879         sigbuffer_add_value (&buf, nl);
880         for (i = 0; i < nl; ++i) {
881                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
882                 
883                 if (lb->is_pinned)
884                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
885                 
886                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
887         }
888         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
889         sigbuffer_free (&buf);
890
891         if (assembly->standalonesig_cache == NULL)
892                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
893         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
894         if (idx)
895                 return idx;
896
897         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
898         idx = table->next_idx ++;
899         table->rows ++;
900         alloc_table (table, table->rows);
901         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
902
903         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
904
905         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
906
907         return idx;
908 }
909
910 static guint32
911 method_count_clauses (MonoReflectionILGen *ilgen)
912 {
913         guint32 num_clauses = 0;
914         int i;
915
916         MonoILExceptionInfo *ex_info;
917         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
918                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
919                 if (ex_info->handlers)
920                         num_clauses += mono_array_length (ex_info->handlers);
921                 else
922                         num_clauses++;
923         }
924
925         return num_clauses;
926 }
927
928 #ifndef DISABLE_REFLECTION_EMIT
929 static MonoExceptionClause*
930 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
931 {
932         MonoExceptionClause *clauses;
933         MonoExceptionClause *clause;
934         MonoILExceptionInfo *ex_info;
935         MonoILExceptionBlock *ex_block;
936         guint32 finally_start;
937         int i, j, clause_index;;
938
939         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
940
941         clause_index = 0;
942         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
943                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
944                 finally_start = ex_info->start + ex_info->len;
945                 if (!ex_info->handlers)
946                         continue;
947                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
948                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
949                         clause = &(clauses [clause_index]);
950
951                         clause->flags = ex_block->type;
952                         clause->try_offset = ex_info->start;
953
954                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
955                                 clause->try_len = finally_start - ex_info->start;
956                         else
957                                 clause->try_len = ex_info->len;
958                         clause->handler_offset = ex_block->start;
959                         clause->handler_len = ex_block->len;
960                         if (ex_block->extype) {
961                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
962                         } else {
963                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
964                                         clause->data.filter_offset = ex_block->filter_offset;
965                                 else
966                                         clause->data.filter_offset = 0;
967                         }
968                         finally_start = ex_block->start + ex_block->len;
969
970                         clause_index ++;
971                 }
972         }
973
974         return clauses;
975 }
976 #endif /* !DISABLE_REFLECTION_EMIT */
977
978 static guint32
979 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
980 {
981         char flags = 0;
982         guint32 idx;
983         guint32 code_size;
984         gint32 max_stack, i;
985         gint32 num_locals = 0;
986         gint32 num_exception = 0;
987         gint maybe_small;
988         guint32 fat_flags;
989         char fat_header [12];
990         guint32 int_value;
991         guint16 short_value;
992         guint32 local_sig = 0;
993         guint32 header_size = 12;
994         MonoArray *code;
995
996         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
997                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
998                 return 0;
999
1000         /*if (mb->name)
1001                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1002         if (mb->ilgen) {
1003                 code = mb->ilgen->code;
1004                 code_size = mb->ilgen->code_len;
1005                 max_stack = mb->ilgen->max_stack;
1006                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1007                 if (mb->ilgen->ex_handlers)
1008                         num_exception = method_count_clauses (mb->ilgen);
1009         } else {
1010                 code = mb->code;
1011                 if (code == NULL){
1012                         char *name = mono_string_to_utf8 (mb->name);
1013                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1014                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1015                         g_free (str);
1016                         g_free (name);
1017                         mono_raise_exception (exception);
1018                 }
1019
1020                 code_size = mono_array_length (code);
1021                 max_stack = 8; /* we probably need to run a verifier on the code... */
1022         }
1023
1024         stream_data_align (&assembly->code);
1025
1026         /* check for exceptions, maxstack, locals */
1027         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1028         if (maybe_small) {
1029                 if (code_size < 64 && !(code_size & 1)) {
1030                         flags = (code_size << 2) | 0x2;
1031                 } else if (code_size < 32 && (code_size & 1)) {
1032                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1033                 } else {
1034                         goto fat_header;
1035                 }
1036                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1037                 /* add to the fixup todo list */
1038                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1039                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1040                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1041                 return assembly->text_rva + idx;
1042         } 
1043 fat_header:
1044         if (num_locals)
1045                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1046         /* 
1047          * FIXME: need to set also the header size in fat_flags.
1048          * (and more sects and init locals flags)
1049          */
1050         fat_flags =  0x03;
1051         if (num_exception)
1052                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1053         if (mb->init_locals)
1054                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1055         fat_header [0] = fat_flags;
1056         fat_header [1] = (header_size / 4 ) << 4;
1057         short_value = GUINT16_TO_LE (max_stack);
1058         memcpy (fat_header + 2, &short_value, 2);
1059         int_value = GUINT32_TO_LE (code_size);
1060         memcpy (fat_header + 4, &int_value, 4);
1061         int_value = GUINT32_TO_LE (local_sig);
1062         memcpy (fat_header + 8, &int_value, 4);
1063         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1064         /* add to the fixup todo list */
1065         if (mb->ilgen && mb->ilgen->num_token_fixups)
1066                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1067         
1068         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1069         if (num_exception) {
1070                 unsigned char sheader [4];
1071                 MonoILExceptionInfo * ex_info;
1072                 MonoILExceptionBlock * ex_block;
1073                 int j;
1074
1075                 stream_data_align (&assembly->code);
1076                 /* always use fat format for now */
1077                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1078                 num_exception *= 6 * sizeof (guint32);
1079                 num_exception += 4; /* include the size of the header */
1080                 sheader [1] = num_exception & 0xff;
1081                 sheader [2] = (num_exception >> 8) & 0xff;
1082                 sheader [3] = (num_exception >> 16) & 0xff;
1083                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1084                 /* fat header, so we are already aligned */
1085                 /* reverse order */
1086                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1087                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1088                         if (ex_info->handlers) {
1089                                 int finally_start = ex_info->start + ex_info->len;
1090                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1091                                         guint32 val;
1092                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1093                                         /* the flags */
1094                                         val = GUINT32_TO_LE (ex_block->type);
1095                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1096                                         /* try offset */
1097                                         val = GUINT32_TO_LE (ex_info->start);
1098                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1099                                         /* need fault, too, probably */
1100                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1101                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1102                                         else
1103                                                 val = GUINT32_TO_LE (ex_info->len);
1104                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1105                                         /* handler offset */
1106                                         val = GUINT32_TO_LE (ex_block->start);
1107                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108                                         /* handler len */
1109                                         val = GUINT32_TO_LE (ex_block->len);
1110                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1111                                         finally_start = ex_block->start + ex_block->len;
1112                                         if (ex_block->extype) {
1113                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1114                                         } else {
1115                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1116                                                         val = ex_block->filter_offset;
1117                                                 else
1118                                                         val = 0;
1119                                         }
1120                                         val = GUINT32_TO_LE (val);
1121                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1122                                         /*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", 
1123                                                         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);*/
1124                                 }
1125                         } else {
1126                                 g_error ("No clauses for ex info block %d", i);
1127                         }
1128                 }
1129         }
1130         return assembly->text_rva + idx;
1131 }
1132
1133 static guint32
1134 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1135 {
1136         int i;
1137         MonoDynamicTable *table;
1138         guint32 *values;
1139         
1140         table = &assembly->tables [table_idx];
1141
1142         g_assert (col < table->columns);
1143
1144         values = table->values + table->columns;
1145         for (i = 1; i <= table->rows; ++i) {
1146                 if (values [col] == token)
1147                         return i;
1148                 values += table->columns;
1149         }
1150         return 0;
1151 }
1152
1153 /*
1154  * LOCKING: Acquires the loader lock. 
1155  */
1156 static MonoCustomAttrInfo*
1157 lookup_custom_attr (MonoImage *image, gpointer member)
1158 {
1159         MonoCustomAttrInfo* res;
1160
1161         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1162
1163         if (!res)
1164                 return NULL;
1165
1166         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1167         res->cached = 0;
1168         return res;
1169 }
1170
1171 static gboolean
1172 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1173 {
1174         /* FIXME: Need to do more checks */
1175         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1176                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1177
1178                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1179                         return FALSE;
1180         }
1181
1182         return TRUE;
1183 }
1184
1185 static MonoCustomAttrInfo*
1186 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1187 {
1188         int i, index, count, not_visible;
1189         MonoCustomAttrInfo *ainfo;
1190         MonoReflectionCustomAttr *cattr;
1191
1192         if (!cattrs)
1193                 return NULL;
1194         /* FIXME: check in assembly the Run flag is set */
1195
1196         count = mono_array_length (cattrs);
1197
1198         /* Skip nonpublic attributes since MS.NET seems to do the same */
1199         /* FIXME: This needs to be done more globally */
1200         not_visible = 0;
1201         for (i = 0; i < count; ++i) {
1202                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1203                 if (!custom_attr_visible (image, cattr))
1204                         not_visible ++;
1205         }
1206         count -= not_visible;
1207
1208         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1209
1210         ainfo->image = image;
1211         ainfo->num_attrs = count;
1212         ainfo->cached = alloc_img != NULL;
1213         index = 0;
1214         for (i = 0; i < count; ++i) {
1215                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1216                 if (custom_attr_visible (image, cattr)) {
1217                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1218                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1219                         ainfo->attrs [index].ctor = cattr->ctor->method;
1220                         ainfo->attrs [index].data = saved;
1221                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1222                         index ++;
1223                 }
1224         }
1225
1226         return ainfo;
1227 }
1228
1229 #ifndef DISABLE_REFLECTION_EMIT
1230 /*
1231  * LOCKING: Acquires the loader lock. 
1232  */
1233 static void
1234 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1235 {
1236         MonoCustomAttrInfo *ainfo, *tmp;
1237
1238         if (!cattrs || !mono_array_length (cattrs))
1239                 return;
1240
1241         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1242
1243         mono_loader_lock ();
1244         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1245         if (tmp)
1246                 mono_custom_attrs_free (tmp);
1247         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1248         mono_loader_unlock ();
1249
1250 }
1251 #endif
1252
1253 void
1254 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1255 {
1256         if (!ainfo->cached)
1257                 g_free (ainfo);
1258 }
1259
1260 /*
1261  * idx is the table index of the object
1262  * type is one of MONO_CUSTOM_ATTR_*
1263  */
1264 static void
1265 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1266 {
1267         MonoDynamicTable *table;
1268         MonoReflectionCustomAttr *cattr;
1269         guint32 *values;
1270         guint32 count, i, token;
1271         char blob_size [6];
1272         char *p = blob_size;
1273         
1274         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1275         if (!cattrs)
1276                 return;
1277         count = mono_array_length (cattrs);
1278         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1279         table->rows += count;
1280         alloc_table (table, table->rows);
1281         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1282         idx <<= MONO_CUSTOM_ATTR_BITS;
1283         idx |= type;
1284         for (i = 0; i < count; ++i) {
1285                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1286                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1287                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1288                 type = mono_metadata_token_index (token);
1289                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1290                 switch (mono_metadata_token_table (token)) {
1291                 case MONO_TABLE_METHOD:
1292                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1293                         /*
1294                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1295                          * method, not the one returned by mono_image_create_token ().
1296                          */
1297                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1298                         break;
1299                 case MONO_TABLE_MEMBERREF:
1300                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1301                         break;
1302                 default:
1303                         g_warning ("got wrong token in custom attr");
1304                         continue;
1305                 }
1306                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1307                 p = blob_size;
1308                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1309                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1310                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1311                 values += MONO_CUSTOM_ATTR_SIZE;
1312                 ++table->next_idx;
1313         }
1314 }
1315
1316 static void
1317 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1318 {
1319         MonoDynamicTable *table;
1320         guint32 *values;
1321         guint32 count, i, idx;
1322         MonoReflectionPermissionSet *perm;
1323
1324         if (!permissions)
1325                 return;
1326
1327         count = mono_array_length (permissions);
1328         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1329         table->rows += count;
1330         alloc_table (table, table->rows);
1331
1332         for (i = 0; i < mono_array_length (permissions); ++i) {
1333                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1334
1335                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1336
1337                 idx = mono_metadata_token_index (parent_token);
1338                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1339                 switch (mono_metadata_token_table (parent_token)) {
1340                 case MONO_TABLE_TYPEDEF:
1341                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1342                         break;
1343                 case MONO_TABLE_METHOD:
1344                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1345                         break;
1346                 case MONO_TABLE_ASSEMBLY:
1347                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1348                         break;
1349                 default:
1350                         g_assert_not_reached ();
1351                 }
1352
1353                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1354                 values [MONO_DECL_SECURITY_PARENT] = idx;
1355                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1356
1357                 ++table->next_idx;
1358         }
1359 }
1360
1361 /*
1362  * Fill in the MethodDef and ParamDef tables for a method.
1363  * This is used for both normal methods and constructors.
1364  */
1365 static void
1366 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1367 {
1368         MonoDynamicTable *table;
1369         guint32 *values;
1370         guint i, count;
1371
1372         /* room in this table is already allocated */
1373         table = &assembly->tables [MONO_TABLE_METHOD];
1374         *mb->table_idx = table->next_idx ++;
1375         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1376         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1377         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1378         values [MONO_METHOD_FLAGS] = mb->attrs;
1379         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1380         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1381         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1382         
1383         table = &assembly->tables [MONO_TABLE_PARAM];
1384         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1385
1386         mono_image_add_decl_security (assembly, 
1387                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1388
1389         if (mb->pinfo) {
1390                 MonoDynamicTable *mtable;
1391                 guint32 *mvalues;
1392                 
1393                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1394                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1395                 
1396                 count = 0;
1397                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1398                         if (mono_array_get (mb->pinfo, gpointer, i))
1399                                 count++;
1400                 }
1401                 table->rows += count;
1402                 alloc_table (table, table->rows);
1403                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1404                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1405                         MonoReflectionParamBuilder *pb;
1406                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1407                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1408                                 values [MONO_PARAM_SEQUENCE] = i;
1409                                 if (pb->name != NULL) {
1410                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1411                                 } else {
1412                                         values [MONO_PARAM_NAME] = 0;
1413                                 }
1414                                 values += MONO_PARAM_SIZE;
1415                                 if (pb->marshal_info) {
1416                                         mtable->rows++;
1417                                         alloc_table (mtable, mtable->rows);
1418                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1419                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1420                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1421                                 }
1422                                 pb->table_idx = table->next_idx++;
1423                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1424                                         guint32 field_type = 0;
1425                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1426                                         mtable->rows ++;
1427                                         alloc_table (mtable, mtable->rows);
1428                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1429                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1430                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1431                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1432                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1433                                 }
1434                         }
1435                 }
1436         }
1437 }
1438
1439 #ifndef DISABLE_REFLECTION_EMIT
1440 static void
1441 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1442 {
1443         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1444
1445         rmb->ilgen = mb->ilgen;
1446         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1447         rmb->parameters = mb->parameters;
1448         rmb->generic_params = mb->generic_params;
1449         rmb->generic_container = mb->generic_container;
1450         rmb->opt_types = NULL;
1451         rmb->pinfo = mb->pinfo;
1452         rmb->attrs = mb->attrs;
1453         rmb->iattrs = mb->iattrs;
1454         rmb->call_conv = mb->call_conv;
1455         rmb->code = mb->code;
1456         rmb->type = mb->type;
1457         rmb->name = mb->name;
1458         rmb->table_idx = &mb->table_idx;
1459         rmb->init_locals = mb->init_locals;
1460         rmb->skip_visibility = FALSE;
1461         rmb->return_modreq = mb->return_modreq;
1462         rmb->return_modopt = mb->return_modopt;
1463         rmb->param_modreq = mb->param_modreq;
1464         rmb->param_modopt = mb->param_modopt;
1465         rmb->permissions = mb->permissions;
1466         rmb->mhandle = mb->mhandle;
1467         rmb->nrefs = 0;
1468         rmb->refs = NULL;
1469
1470         if (mb->dll) {
1471                 rmb->charset = mb->charset;
1472                 rmb->extra_flags = mb->extra_flags;
1473                 rmb->native_cc = mb->native_cc;
1474                 rmb->dllentry = mb->dllentry;
1475                 rmb->dll = mb->dll;
1476         }
1477 }
1478
1479 static void
1480 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1481 {
1482         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1483
1484         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1485
1486         rmb->ilgen = mb->ilgen;
1487         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1488         rmb->parameters = mb->parameters;
1489         rmb->generic_params = NULL;
1490         rmb->generic_container = NULL;
1491         rmb->opt_types = NULL;
1492         rmb->pinfo = mb->pinfo;
1493         rmb->attrs = mb->attrs;
1494         rmb->iattrs = mb->iattrs;
1495         rmb->call_conv = mb->call_conv;
1496         rmb->code = NULL;
1497         rmb->type = mb->type;
1498         rmb->name = mono_string_new (mono_domain_get (), name);
1499         rmb->table_idx = &mb->table_idx;
1500         rmb->init_locals = mb->init_locals;
1501         rmb->skip_visibility = FALSE;
1502         rmb->return_modreq = NULL;
1503         rmb->return_modopt = NULL;
1504         rmb->param_modreq = mb->param_modreq;
1505         rmb->param_modopt = mb->param_modopt;
1506         rmb->permissions = mb->permissions;
1507         rmb->mhandle = mb->mhandle;
1508         rmb->nrefs = 0;
1509         rmb->refs = NULL;
1510 }
1511
1512 static void
1513 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1514 {
1515         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1516
1517         rmb->ilgen = mb->ilgen;
1518         rmb->rtype = mb->rtype;
1519         rmb->parameters = mb->parameters;
1520         rmb->generic_params = NULL;
1521         rmb->generic_container = NULL;
1522         rmb->opt_types = NULL;
1523         rmb->pinfo = NULL;
1524         rmb->attrs = mb->attrs;
1525         rmb->iattrs = 0;
1526         rmb->call_conv = mb->call_conv;
1527         rmb->code = NULL;
1528         rmb->type = (MonoObject *) mb->owner;
1529         rmb->name = mb->name;
1530         rmb->table_idx = NULL;
1531         rmb->init_locals = mb->init_locals;
1532         rmb->skip_visibility = mb->skip_visibility;
1533         rmb->return_modreq = NULL;
1534         rmb->return_modopt = NULL;
1535         rmb->param_modreq = NULL;
1536         rmb->param_modopt = NULL;
1537         rmb->permissions = NULL;
1538         rmb->mhandle = mb->mhandle;
1539         rmb->nrefs = 0;
1540         rmb->refs = NULL;
1541 }       
1542 #endif
1543
1544 static void
1545 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1546 {
1547         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1548         MonoDynamicTable *table;
1549         guint32 *values;
1550         guint32 tok;
1551         MonoReflectionMethod *m;
1552         int i;
1553
1554         if (!mb->override_methods)
1555                 return;
1556
1557         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1558                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1559
1560                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1561                 table->rows ++;
1562                 alloc_table (table, table->rows);
1563                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1564                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1565                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1566
1567                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1568                 switch (mono_metadata_token_table (tok)) {
1569                 case MONO_TABLE_MEMBERREF:
1570                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1571                         break;
1572                 case MONO_TABLE_METHOD:
1573                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1574                         break;
1575                 default:
1576                         g_assert_not_reached ();
1577                 }
1578                 values [MONO_METHODIMPL_DECLARATION] = tok;
1579         }
1580 }
1581
1582 #ifndef DISABLE_REFLECTION_EMIT
1583 static void
1584 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1585 {
1586         MonoDynamicTable *table;
1587         guint32 *values;
1588         ReflectionMethodBuilder rmb;
1589         int i;
1590
1591         reflection_methodbuilder_from_method_builder (&rmb, mb);
1592
1593         mono_image_basic_method (&rmb, assembly);
1594         mb->table_idx = *rmb.table_idx;
1595
1596         if (mb->dll) { /* It's a P/Invoke method */
1597                 guint32 moduleref;
1598                 /* map CharSet values to on-disk values */
1599                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1600                 int extra_flags = mb->extra_flags;
1601                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1602                 table->rows ++;
1603                 alloc_table (table, table->rows);
1604                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1605                 
1606                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1607                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1608                 if (mb->dllentry)
1609                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1610                 else
1611                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1612                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1613                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1614                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1615                         table->rows ++;
1616                         alloc_table (table, table->rows);
1617                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1618                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1619                 }
1620         }
1621
1622         if (mb->generic_params) {
1623                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1624                 table->rows += mono_array_length (mb->generic_params);
1625                 alloc_table (table, table->rows);
1626                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1627                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1628
1629                         mono_image_get_generic_param_info (
1630                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1631                 }
1632         }
1633
1634 }
1635
1636 static void
1637 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1638 {
1639         ReflectionMethodBuilder rmb;
1640
1641         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1642
1643         mono_image_basic_method (&rmb, assembly);
1644         mb->table_idx = *rmb.table_idx;
1645 }
1646 #endif
1647
1648 static char*
1649 type_get_fully_qualified_name (MonoType *type)
1650 {
1651         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1652 }
1653
1654 static char*
1655 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1656         MonoClass *klass;
1657         MonoAssembly *ta;
1658
1659         klass = mono_class_from_mono_type (type);
1660         if (!klass) 
1661                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1662         ta = klass->image->assembly;
1663         if (ta->dynamic || (ta == ass)) {
1664                 if (klass->generic_class || klass->generic_container)
1665                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1666                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1667                 else
1668                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1669         }
1670
1671         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1672 }
1673
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 /*field_image is the image to which the eventual custom mods have been encoded against*/
1676 static guint32
1677 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1678 {
1679         SigBuffer buf;
1680         guint32 idx, i, token;
1681
1682         if (!assembly->save)
1683                 return 0;
1684
1685         sigbuffer_init (&buf, 32);
1686         
1687         sigbuffer_add_value (&buf, 0x06);
1688         /* encode custom attributes before the type */
1689         if (type->num_mods) {
1690                 for (i = 0; i < type->num_mods; ++i) {
1691                         if (field_image) {
1692                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1693                                 g_assert (class);
1694                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1695                         } else {
1696                                 token = type->modifiers [i].token;
1697                         }
1698
1699                         if (type->modifiers [i].required)
1700                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1701                         else
1702                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1703
1704                         sigbuffer_add_value (&buf, token);
1705                 }
1706         }
1707         encode_type (assembly, type, &buf);
1708         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1709         sigbuffer_free (&buf);
1710         return idx;
1711 }
1712 #endif
1713
1714 static guint32
1715 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1716 {
1717         SigBuffer buf;
1718         guint32 idx;
1719         guint32 typespec = 0;
1720         MonoType *type;
1721         MonoClass *class;
1722
1723         init_type_builder_generics (fb->type);
1724
1725         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1726         class = mono_class_from_mono_type (type);
1727
1728         sigbuffer_init (&buf, 32);
1729         
1730         sigbuffer_add_value (&buf, 0x06);
1731         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1732         /* encode custom attributes before the type */
1733
1734         if (class->generic_container)
1735                 typespec = create_typespec (assembly, type);
1736
1737         if (typespec) {
1738                 MonoGenericClass *gclass;
1739                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1740                 encode_generic_class (assembly, gclass, &buf);
1741         } else {
1742                 encode_type (assembly, type, &buf);
1743         }
1744         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1745         sigbuffer_free (&buf);
1746         return idx;
1747 }
1748
1749 static guint32
1750 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1751         char blob_size [64];
1752         char *b = blob_size;
1753         char *p, *box_val;
1754         char* buf;
1755         guint32 idx = 0, len = 0, dummy = 0;
1756 #ifdef ARM_FPU_FPA
1757 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1758         guint32 fpa_double [2];
1759         guint32 *fpa_p;
1760 #endif
1761 #endif
1762         
1763         p = buf = g_malloc (64);
1764         if (!val) {
1765                 *ret_type = MONO_TYPE_CLASS;
1766                 len = 4;
1767                 box_val = (char*)&dummy;
1768         } else {
1769                 box_val = ((char*)val) + sizeof (MonoObject);
1770                 *ret_type = val->vtable->klass->byval_arg.type;
1771         }
1772 handle_enum:
1773         switch (*ret_type) {
1774         case MONO_TYPE_BOOLEAN:
1775         case MONO_TYPE_U1:
1776         case MONO_TYPE_I1:
1777                 len = 1;
1778                 break;
1779         case MONO_TYPE_CHAR:
1780         case MONO_TYPE_U2:
1781         case MONO_TYPE_I2:
1782                 len = 2;
1783                 break;
1784         case MONO_TYPE_U4:
1785         case MONO_TYPE_I4:
1786         case MONO_TYPE_R4:
1787                 len = 4;
1788                 break;
1789         case MONO_TYPE_U8:
1790         case MONO_TYPE_I8:
1791                 len = 8;
1792                 break;
1793         case MONO_TYPE_R8:
1794                 len = 8;
1795 #ifdef ARM_FPU_FPA
1796 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1797                 fpa_p = (guint32*)box_val;
1798                 fpa_double [0] = fpa_p [1];
1799                 fpa_double [1] = fpa_p [0];
1800                 box_val = (char*)fpa_double;
1801 #endif
1802 #endif
1803                 break;
1804         case MONO_TYPE_VALUETYPE: {
1805                 MonoClass *klass = val->vtable->klass;
1806                 
1807                 if (klass->enumtype) {
1808                         *ret_type = mono_class_enum_basetype (klass)->type;
1809                         goto handle_enum;
1810                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1811                         len = 8;
1812                 } else 
1813                         g_error ("we can't encode valuetypes, we should have never reached this line");
1814                 break;
1815         }
1816         case MONO_TYPE_CLASS:
1817                 break;
1818         case MONO_TYPE_STRING: {
1819                 MonoString *str = (MonoString*)val;
1820                 /* there is no signature */
1821                 len = str->length * 2;
1822                 mono_metadata_encode_value (len, b, &b);
1823 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1824                 {
1825                         char *swapped = g_malloc (2 * mono_string_length (str));
1826                         const char *p = (const char*)mono_string_chars (str);
1827
1828                         swap_with_size (swapped, p, 2, mono_string_length (str));
1829                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1830                         g_free (swapped);
1831                 }
1832 #else
1833                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1834 #endif
1835
1836                 g_free (buf);
1837                 return idx;
1838         }
1839         case MONO_TYPE_GENERICINST:
1840                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1841                 goto handle_enum;
1842         default:
1843                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1844         }
1845
1846         /* there is no signature */
1847         mono_metadata_encode_value (len, b, &b);
1848 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1849         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1850         swap_with_size (blob_size, box_val, len, 1);
1851         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1852 #else
1853         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1854 #endif
1855
1856         g_free (buf);
1857         return idx;
1858 }
1859
1860 static guint32
1861 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1862         char *str;
1863         SigBuffer buf;
1864         guint32 idx, len;
1865
1866         sigbuffer_init (&buf, 32);
1867
1868         sigbuffer_add_value (&buf, minfo->type);
1869
1870         switch (minfo->type) {
1871         case MONO_NATIVE_BYVALTSTR:
1872         case MONO_NATIVE_BYVALARRAY:
1873                 sigbuffer_add_value (&buf, minfo->count);
1874                 break;
1875         case MONO_NATIVE_LPARRAY:
1876                 if (minfo->eltype || minfo->has_size) {
1877                         sigbuffer_add_value (&buf, minfo->eltype);
1878                         if (minfo->has_size) {
1879                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1880                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1881
1882                                 /* LAMESPEC: ElemMult is undocumented */
1883                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1884                         }
1885                 }
1886                 break;
1887         case MONO_NATIVE_SAFEARRAY:
1888                 if (minfo->eltype)
1889                         sigbuffer_add_value (&buf, minfo->eltype);
1890                 break;
1891         case MONO_NATIVE_CUSTOM:
1892                 if (minfo->guid) {
1893                         str = mono_string_to_utf8 (minfo->guid);
1894                         len = strlen (str);
1895                         sigbuffer_add_value (&buf, len);
1896                         sigbuffer_add_mem (&buf, str, len);
1897                         g_free (str);
1898                 } else {
1899                         sigbuffer_add_value (&buf, 0);
1900                 }
1901                 /* native type name */
1902                 sigbuffer_add_value (&buf, 0);
1903                 /* custom marshaler type name */
1904                 if (minfo->marshaltype || minfo->marshaltyperef) {
1905                         if (minfo->marshaltyperef)
1906                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1907                         else
1908                                 str = mono_string_to_utf8 (minfo->marshaltype);
1909                         len = strlen (str);
1910                         sigbuffer_add_value (&buf, len);
1911                         sigbuffer_add_mem (&buf, str, len);
1912                         g_free (str);
1913                 } else {
1914                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1915                         sigbuffer_add_value (&buf, 0);
1916                 }
1917                 if (minfo->mcookie) {
1918                         str = mono_string_to_utf8 (minfo->mcookie);
1919                         len = strlen (str);
1920                         sigbuffer_add_value (&buf, len);
1921                         sigbuffer_add_mem (&buf, str, len);
1922                         g_free (str);
1923                 } else {
1924                         sigbuffer_add_value (&buf, 0);
1925                 }
1926                 break;
1927         default:
1928                 break;
1929         }
1930         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1931         sigbuffer_free (&buf);
1932         return idx;
1933 }
1934
1935 static void
1936 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1937 {
1938         MonoDynamicTable *table;
1939         guint32 *values;
1940
1941         /* maybe this fixup should be done in the C# code */
1942         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1943                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1944         table = &assembly->tables [MONO_TABLE_FIELD];
1945         fb->table_idx = table->next_idx ++;
1946         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1947         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1948         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1949         values [MONO_FIELD_FLAGS] = fb->attrs;
1950         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1951
1952         if (fb->offset != -1) {
1953                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1954                 table->rows ++;
1955                 alloc_table (table, table->rows);
1956                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1957                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1958                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1959         }
1960         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1961                 guint32 field_type = 0;
1962                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1963                 table->rows ++;
1964                 alloc_table (table, table->rows);
1965                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1966                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1967                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1968                 values [MONO_CONSTANT_TYPE] = field_type;
1969                 values [MONO_CONSTANT_PADDING] = 0;
1970         }
1971         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1972                 guint32 rva_idx;
1973                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1974                 table->rows ++;
1975                 alloc_table (table, table->rows);
1976                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1977                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1978                 /*
1979                  * We store it in the code section because it's simpler for now.
1980                  */
1981                 if (fb->rva_data) {
1982                         if (mono_array_length (fb->rva_data) >= 10)
1983                                 stream_data_align (&assembly->code);
1984                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1985                 } else
1986                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1987                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1988         }
1989         if (fb->marshal_info) {
1990                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1991                 table->rows ++;
1992                 alloc_table (table, table->rows);
1993                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1994                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1995                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1996         }
1997 }
1998
1999 static guint32
2000 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2001 {
2002         SigBuffer buf;
2003         guint32 nparams = 0;
2004         MonoReflectionMethodBuilder *mb = fb->get_method;
2005         MonoReflectionMethodBuilder *smb = fb->set_method;
2006         guint32 idx, i;
2007
2008         if (mb && mb->parameters)
2009                 nparams = mono_array_length (mb->parameters);
2010         if (!mb && smb && smb->parameters)
2011                 nparams = mono_array_length (smb->parameters) - 1;
2012         sigbuffer_init (&buf, 32);
2013         if (fb->call_conv & 0x20)
2014                 sigbuffer_add_byte (&buf, 0x28);
2015         else
2016                 sigbuffer_add_byte (&buf, 0x08);
2017         sigbuffer_add_value (&buf, nparams);
2018         if (mb) {
2019                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2020                 for (i = 0; i < nparams; ++i) {
2021                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2022                         encode_reflection_type (assembly, pt, &buf);
2023                 }
2024         } else if (smb && smb->parameters) {
2025                 /* the property type is the last param */
2026                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2027                 for (i = 0; i < nparams; ++i) {
2028                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2029                         encode_reflection_type (assembly, pt, &buf);
2030                 }
2031         } else {
2032                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2033         }
2034
2035         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2036         sigbuffer_free (&buf);
2037         return idx;
2038 }
2039
2040 static void
2041 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2042 {
2043         MonoDynamicTable *table;
2044         guint32 *values;
2045         guint num_methods = 0;
2046         guint32 semaidx;
2047
2048         /* 
2049          * we need to set things in the following tables:
2050          * PROPERTYMAP (info already filled in _get_type_info ())
2051          * PROPERTY    (rows already preallocated in _get_type_info ())
2052          * METHOD      (method info already done with the generic method code)
2053          * METHODSEMANTICS
2054          * CONSTANT
2055          */
2056         table = &assembly->tables [MONO_TABLE_PROPERTY];
2057         pb->table_idx = table->next_idx ++;
2058         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2059         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2060         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2061         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2062
2063         /* FIXME: we still don't handle 'other' methods */
2064         if (pb->get_method) num_methods ++;
2065         if (pb->set_method) num_methods ++;
2066
2067         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2068         table->rows += num_methods;
2069         alloc_table (table, table->rows);
2070
2071         if (pb->get_method) {
2072                 semaidx = table->next_idx ++;
2073                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2074                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2075                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2076                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2077         }
2078         if (pb->set_method) {
2079                 semaidx = table->next_idx ++;
2080                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2081                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2082                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2083                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2084         }
2085         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2086                 guint32 field_type = 0;
2087                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2088                 table->rows ++;
2089                 alloc_table (table, table->rows);
2090                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2091                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2092                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2093                 values [MONO_CONSTANT_TYPE] = field_type;
2094                 values [MONO_CONSTANT_PADDING] = 0;
2095         }
2096 }
2097
2098 static void
2099 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2100 {
2101         MonoDynamicTable *table;
2102         guint32 *values;
2103         guint num_methods = 0;
2104         guint32 semaidx;
2105
2106         /* 
2107          * we need to set things in the following tables:
2108          * EVENTMAP (info already filled in _get_type_info ())
2109          * EVENT    (rows already preallocated in _get_type_info ())
2110          * METHOD      (method info already done with the generic method code)
2111          * METHODSEMANTICS
2112          */
2113         table = &assembly->tables [MONO_TABLE_EVENT];
2114         eb->table_idx = table->next_idx ++;
2115         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2116         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2117         values [MONO_EVENT_FLAGS] = eb->attrs;
2118         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2119
2120         /*
2121          * FIXME: we still don't handle 'other' methods 
2122          */
2123         if (eb->add_method) num_methods ++;
2124         if (eb->remove_method) num_methods ++;
2125         if (eb->raise_method) num_methods ++;
2126
2127         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2128         table->rows += num_methods;
2129         alloc_table (table, table->rows);
2130
2131         if (eb->add_method) {
2132                 semaidx = table->next_idx ++;
2133                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2134                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2135                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2136                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2137         }
2138         if (eb->remove_method) {
2139                 semaidx = table->next_idx ++;
2140                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2141                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2142                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2143                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2144         }
2145         if (eb->raise_method) {
2146                 semaidx = table->next_idx ++;
2147                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2148                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2149                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2150                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2151         }
2152 }
2153
2154 static void
2155 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2156 {
2157         MonoDynamicTable *table;
2158         guint32 num_constraints, i;
2159         guint32 *values;
2160         guint32 table_idx;
2161
2162         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2163         num_constraints = gparam->iface_constraints ?
2164                 mono_array_length (gparam->iface_constraints) : 0;
2165         table->rows += num_constraints;
2166         if (gparam->base_type)
2167                 table->rows++;
2168         alloc_table (table, table->rows);
2169
2170         if (gparam->base_type) {
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 (gparam->base_type));
2177         }
2178
2179         for (i = 0; i < num_constraints; i++) {
2180                 MonoReflectionType *constraint = mono_array_get (
2181                         gparam->iface_constraints, gpointer, i);
2182
2183                 table_idx = table->next_idx ++;
2184                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2185
2186                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2187                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2188                         assembly, mono_reflection_type_get_handle (constraint));
2189         }
2190 }
2191
2192 static void
2193 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2194 {
2195         GenericParamTableEntry *entry;
2196
2197         /*
2198          * The GenericParam table must be sorted according to the `owner' field.
2199          * We need to do this sorting prior to writing the GenericParamConstraint
2200          * table, since we have to use the final GenericParam table indices there
2201          * and they must also be sorted.
2202          */
2203
2204         entry = g_new0 (GenericParamTableEntry, 1);
2205         entry->owner = owner;
2206         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2207         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam);
2208         entry->gparam = gparam;
2209         
2210         g_ptr_array_add (assembly->gen_params, entry);
2211 }
2212
2213 static void
2214 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2215 {
2216         MonoDynamicTable *table;
2217         MonoGenericParam *param;
2218         guint32 *values;
2219         guint32 table_idx;
2220
2221         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2222         table_idx = table->next_idx ++;
2223         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2224
2225         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2226
2227         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2228         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2229         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2230         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2231
2232         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2233
2234         encode_constraints (entry->gparam, table_idx, assembly);
2235 }
2236
2237 static guint32
2238 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2239 {
2240         MonoDynamicTable *table;
2241         guint32 token;
2242         guint32 *values;
2243         guint32 cols [MONO_ASSEMBLY_SIZE];
2244         const char *pubkey;
2245         guint32 publen;
2246
2247         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2248                 return token;
2249
2250         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2251                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2252                 token = table->next_idx ++;
2253                 table->rows ++;
2254                 alloc_table (table, table->rows);
2255                 values = table->values + token * MONO_MODULEREF_SIZE;
2256                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2257
2258                 token <<= MONO_RESOLTION_SCOPE_BITS;
2259                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2260                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2261
2262                 return token;
2263         }
2264         
2265         if (image->assembly->dynamic)
2266                 /* FIXME: */
2267                 memset (cols, 0, sizeof (cols));
2268         else {
2269                 /* image->assembly->image is the manifest module */
2270                 image = image->assembly->image;
2271                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2272         }
2273
2274         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2275         token = table->next_idx ++;
2276         table->rows ++;
2277         alloc_table (table, table->rows);
2278         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2279         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2280         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2281         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2282         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2283         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2284         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2285         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2286         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2287
2288         if (strcmp ("", image->assembly->aname.culture)) {
2289                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2290                                 image->assembly->aname.culture);
2291         }
2292
2293         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2294                 guchar pubtoken [9];
2295                 pubtoken [0] = 8;
2296                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2297                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2298         } else {
2299                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2300         }
2301         token <<= MONO_RESOLTION_SCOPE_BITS;
2302         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2303         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2304         return token;
2305 }
2306
2307 static guint32
2308 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2309 {
2310         MonoDynamicTable *table;
2311         guint32 *values;
2312         guint32 token;
2313         SigBuffer buf;
2314
2315         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2316                 return token;
2317
2318         sigbuffer_init (&buf, 32);
2319         switch (type->type) {
2320         case MONO_TYPE_FNPTR:
2321         case MONO_TYPE_PTR:
2322         case MONO_TYPE_SZARRAY:
2323         case MONO_TYPE_ARRAY:
2324         case MONO_TYPE_VAR:
2325         case MONO_TYPE_MVAR:
2326         case MONO_TYPE_GENERICINST:
2327                 encode_type (assembly, type, &buf);
2328                 break;
2329         case MONO_TYPE_CLASS:
2330         case MONO_TYPE_VALUETYPE: {
2331                 MonoClass *k = mono_class_from_mono_type (type);
2332                 if (!k || !k->generic_container) {
2333                         sigbuffer_free (&buf);
2334                         return 0;
2335                 }
2336                 encode_type (assembly, type, &buf);
2337                 break;
2338         }
2339         default:
2340                 sigbuffer_free (&buf);
2341                 return 0;
2342         }
2343
2344         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2345         if (assembly->save) {
2346                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2347                 alloc_table (table, table->rows + 1);
2348                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2349                 values [MONO_TYPESPEC_SIGNATURE] = token;
2350         }
2351         sigbuffer_free (&buf);
2352
2353         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2354         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2355         table->next_idx ++;
2356         return token;
2357 }
2358
2359 static guint32
2360 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2361 {
2362         MonoDynamicTable *table;
2363         guint32 *values;
2364         guint32 token, scope, enclosing;
2365         MonoClass *klass;
2366
2367         /* if the type requires a typespec, we must try that first*/
2368         if (try_typespec && (token = create_typespec (assembly, type)))
2369                 return token;
2370         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2371         if (token)
2372                 return token;
2373         klass = mono_class_from_mono_type (type);
2374         if (!klass)
2375                 klass = mono_class_from_mono_type (type);
2376
2377         /*
2378          * If it's in the same module and not a generic type parameter:
2379          */
2380         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2381                         (type->type != MONO_TYPE_MVAR)) {
2382                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2383                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2384                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2385                 return token;
2386         }
2387
2388         if (klass->nested_in) {
2389                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2390                 /* get the typeref idx of the enclosing type */
2391                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2392                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2393         } else {
2394                 scope = resolution_scope_from_image (assembly, klass->image);
2395         }
2396         table = &assembly->tables [MONO_TABLE_TYPEREF];
2397         if (assembly->save) {
2398                 alloc_table (table, table->rows + 1);
2399                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2400                 values [MONO_TYPEREF_SCOPE] = scope;
2401                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2402                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2403         }
2404         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2405         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2406         table->next_idx ++;
2407         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2408         return token;
2409 }
2410
2411 /*
2412  * Despite the name, we handle also TypeSpec (with the above helper).
2413  */
2414 static guint32
2415 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2416 {
2417         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2418 }
2419
2420 #ifndef DISABLE_REFLECTION_EMIT
2421 static guint32
2422 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2423 {
2424         MonoDynamicTable *table;
2425         guint32 *values;
2426         guint32 token, pclass;
2427
2428         switch (parent & MONO_TYPEDEFORREF_MASK) {
2429         case MONO_TYPEDEFORREF_TYPEREF:
2430                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2431                 break;
2432         case MONO_TYPEDEFORREF_TYPESPEC:
2433                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2434                 break;
2435         case MONO_TYPEDEFORREF_TYPEDEF:
2436                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2437                 break;
2438         default:
2439                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2440                 return 0;
2441         }
2442         /* extract the index */
2443         parent >>= MONO_TYPEDEFORREF_BITS;
2444
2445         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2446
2447         if (assembly->save) {
2448                 alloc_table (table, table->rows + 1);
2449                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2450                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2451                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2452                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2453         }
2454
2455         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2456         table->next_idx ++;
2457
2458         return token;
2459 }
2460
2461 /*
2462  * Insert a memberef row into the metadata: the token that point to the memberref
2463  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2464  * mono_image_get_fieldref_token()).
2465  * The sig param is an index to an already built signature.
2466  */
2467 static guint32
2468 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2469 {
2470         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2471         return mono_image_add_memberef_row (assembly, parent, name, sig);
2472 }
2473
2474
2475 static guint32
2476 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2477 {
2478         guint32 token;
2479         MonoMethodSignature *sig;
2480         
2481         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2482
2483         if (create_typespec) {
2484                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2485                 if (token)
2486                         return token;
2487         } 
2488
2489         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2490         if (token && !create_typespec)
2491                 return token;
2492
2493         g_assert (!method->is_inflated);
2494         if (!token) {
2495                 /*
2496                  * A methodref signature can't contain an unmanaged calling convention.
2497                  */
2498                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2499                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2500                         sig->call_convention = MONO_CALL_DEFAULT;
2501                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2502                         method->name,  method_encode_signature (assembly, sig));
2503                 g_free (sig);
2504                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2505         }
2506
2507         if (create_typespec) {
2508                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2509                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2510                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2511
2512                 if (assembly->save) {
2513                         guint32 *values;
2514
2515                         alloc_table (table, table->rows + 1);
2516                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2517                         values [MONO_METHODSPEC_METHOD] = token;
2518                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2519                 }
2520
2521                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2522                 table->next_idx ++;
2523                 /*methodspec and memberef tokens are diferent, */
2524                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2525                 return token;
2526         }
2527         return token;
2528 }
2529
2530 static guint32
2531 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2532 {
2533         guint32 token, parent, sig;
2534         ReflectionMethodBuilder rmb;
2535         char *name;
2536         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2537         
2538         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2539         if (token)
2540                 return token;
2541
2542         name = mono_string_to_utf8 (method->name);
2543         reflection_methodbuilder_from_method_builder (&rmb, method);
2544
2545         /*
2546          * A methodref signature can't contain an unmanaged calling convention.
2547          * Since some flags are encoded as part of call_conv, we need to check against it.
2548         */
2549         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2550                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2551
2552         sig = method_builder_encode_signature (assembly, &rmb);
2553
2554         if (tb->generic_params)
2555                 parent = create_generic_typespec (assembly, tb);
2556         else
2557                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2558
2559         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2560
2561         g_free (name);
2562         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2563         return token;
2564 }
2565
2566 static guint32
2567 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2568                                      const gchar *name, guint32 sig)
2569 {
2570         MonoDynamicTable *table;
2571         guint32 token;
2572         guint32 *values;
2573         
2574         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2575
2576         if (assembly->save) {
2577                 alloc_table (table, table->rows + 1);
2578                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2579                 values [MONO_MEMBERREF_CLASS] = original;
2580                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2581                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2582         }
2583
2584         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2585         table->next_idx ++;
2586
2587         return token;
2588 }
2589
2590 static guint32
2591 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2592 {
2593         SigBuffer buf;
2594         int i;
2595         guint32 nparams = mono_array_length (mb->generic_params);
2596         guint32 idx;
2597
2598         if (!assembly->save)
2599                 return 0;
2600
2601         sigbuffer_init (&buf, 32);
2602
2603         sigbuffer_add_value (&buf, 0xa);
2604         sigbuffer_add_value (&buf, nparams);
2605
2606         for (i = 0; i < nparams; i++) {
2607                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2608                 sigbuffer_add_value (&buf, i);
2609         }
2610
2611         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2612         sigbuffer_free (&buf);
2613         return idx;
2614 }
2615
2616 static guint32
2617 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2618 {
2619         MonoDynamicTable *table;
2620         guint32 *values;
2621         guint32 token, mtoken = 0;
2622
2623         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2624         if (token)
2625                 return token;
2626
2627         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2628
2629         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2630         switch (mono_metadata_token_table (mtoken)) {
2631         case MONO_TABLE_MEMBERREF:
2632                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2633                 break;
2634         case MONO_TABLE_METHOD:
2635                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2636                 break;
2637         default:
2638                 g_assert_not_reached ();
2639         }
2640
2641         if (assembly->save) {
2642                 alloc_table (table, table->rows + 1);
2643                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2644                 values [MONO_METHODSPEC_METHOD] = mtoken;
2645                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2646         }
2647
2648         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2649         table->next_idx ++;
2650
2651         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2652         return token;
2653 }
2654
2655 static guint32
2656 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2657 {
2658         guint32 token;
2659
2660         if (mb->generic_params && create_methodspec) 
2661                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2662
2663         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2664         if (token)
2665                 return token;
2666
2667         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2668         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2669         return token;
2670 }
2671
2672 static guint32
2673 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2674 {
2675         guint32 token, parent, sig;
2676         ReflectionMethodBuilder rmb;
2677         char *name;
2678         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2679         
2680         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2681         if (token)
2682                 return token;
2683
2684         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2685
2686         if (tb->generic_params)
2687                 parent = create_generic_typespec (assembly, tb);
2688         else
2689                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2690         
2691         name = mono_string_to_utf8 (rmb.name);
2692         sig = method_builder_encode_signature (assembly, &rmb);
2693
2694         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2695
2696         g_free (name);
2697         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2698         return token;
2699 }
2700 #endif
2701
2702 static gboolean
2703 is_field_on_inst (MonoClassField *field)
2704 {
2705         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2706 }
2707
2708 /*
2709  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2710  */
2711 static MonoType*
2712 get_field_on_inst_generic_type (MonoClassField *field)
2713 {
2714         MonoClass *class, *gtd;
2715         MonoDynamicGenericClass *dgclass;
2716         int field_index;
2717
2718         g_assert (is_field_on_inst (field));
2719
2720         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2721
2722         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2723                 field_index = field - dgclass->fields;
2724                 return dgclass->field_generic_types [field_index];              
2725         }
2726
2727         class = field->parent;
2728         gtd = class->generic_class->container_class;
2729
2730         if (field >= class->fields && field - class->fields < class->field.count) {
2731                 field_index = field - class->fields;
2732                 return gtd->fields [field_index].type;
2733         }
2734
2735         g_assert_not_reached ();
2736         return 0;
2737 }
2738
2739 #ifndef DISABLE_REFLECTION_EMIT
2740 static guint32
2741 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2742 {
2743         MonoType *type;
2744         guint32 token;
2745
2746         g_assert (field);
2747         g_assert (field->parent);
2748
2749         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2750         if (token)
2751                 return token;
2752
2753         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2754                 int index = field - field->parent->fields;
2755                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2756         } else {
2757                 if (is_field_on_inst (field))
2758                         type = get_field_on_inst_generic_type (field);
2759                 else
2760                         type = mono_field_get_type (field);
2761         }
2762         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2763                                                                                         mono_field_get_name (field),
2764                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2765         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2766         return token;
2767 }
2768
2769 static guint32
2770 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2771 {
2772         guint32 token;
2773         MonoClass *klass;
2774         MonoGenericClass *gclass;
2775         MonoDynamicGenericClass *dgclass;
2776         MonoType *type;
2777         char *name;
2778
2779         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2780         if (token)
2781                 return token;
2782         if (is_sre_field_builder (mono_object_class (f->fb))) {
2783                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2784                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2785                 klass = mono_class_from_mono_type (type);
2786                 gclass = type->data.generic_class;
2787                 g_assert (gclass->is_dynamic);
2788                 dgclass = (MonoDynamicGenericClass *) gclass;
2789
2790                 name = mono_string_to_utf8 (fb->name);
2791                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2792                                                                                                 field_encode_signature (assembly, fb));
2793                 g_free (name);          
2794         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2795                 guint32 sig;
2796                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2797
2798                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2799                 klass = mono_class_from_mono_type (type);
2800
2801                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2802                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2803         } else {
2804                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2805                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2806         }
2807
2808         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2809         return token;
2810 }
2811
2812 static guint32
2813 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2814 {
2815         guint32 sig, token;
2816         MonoClass *klass;
2817         MonoGenericClass *gclass;
2818         MonoType *type;
2819
2820         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2821
2822         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2823         if (token)
2824                 return token;
2825
2826         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2827                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2828                 MonoDynamicGenericClass *dgclass;
2829                 ReflectionMethodBuilder rmb;
2830                 char *name;
2831
2832                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2833                 klass = mono_class_from_mono_type (type);
2834
2835                 gclass = type->data.generic_class;
2836                 g_assert (gclass->is_dynamic);
2837                 dgclass = (MonoDynamicGenericClass *) gclass;
2838
2839                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2840
2841                 name = mono_string_to_utf8 (rmb.name);
2842
2843                 sig = method_builder_encode_signature (assembly, &rmb);
2844
2845                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2846                 g_free (name);
2847         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2848                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2849
2850                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2851                 klass = mono_class_from_mono_type (type);
2852
2853                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2854                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2855         } else {
2856                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2857                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2858         }
2859
2860
2861         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2862         return token;
2863 }
2864
2865 static MonoMethod*
2866 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2867 {
2868         MonoClass *klass;
2869         MonoGenericContext tmp_context;
2870         MonoType **type_argv;
2871         MonoGenericInst *ginst;
2872         MonoMethod *method, *inflated;
2873         int count, i;
2874
2875         init_type_builder_generics ((MonoObject*)m->inst);
2876
2877         method = inflate_method (m->inst, (MonoObject*)m->mb);
2878
2879         klass = method->klass;
2880
2881         if (m->method_args == NULL)
2882                 return method;
2883
2884         if (method->is_inflated)
2885                 method = ((MonoMethodInflated *) method)->declaring;
2886
2887         count = mono_array_length (m->method_args);
2888
2889         type_argv = g_new0 (MonoType *, count);
2890         for (i = 0; i < count; i++) {
2891                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2892                 type_argv [i] = mono_reflection_type_get_handle (garg);
2893         }
2894         ginst = mono_metadata_get_generic_inst (count, type_argv);
2895         g_free (type_argv);
2896
2897         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2898         tmp_context.method_inst = ginst;
2899
2900         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2901         return inflated;
2902 }
2903
2904 static guint32
2905 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2906 {
2907         guint32 sig, token = 0;
2908         MonoType *type;
2909         MonoClass *klass;
2910
2911         if (m->method_args) {
2912                 MonoMethod *inflated;
2913
2914                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2915                 if (create_methodspec)
2916                         token = mono_image_get_methodspec_token (assembly, inflated);
2917                 else
2918                         token = mono_image_get_inflated_method_token (assembly, inflated);
2919                 return token;
2920         }
2921
2922         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2923         if (token)
2924                 return token;
2925
2926         if (is_sre_method_builder (mono_object_class (m->mb))) {
2927                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2928                 MonoGenericClass *gclass;
2929                 ReflectionMethodBuilder rmb;
2930                 char *name;
2931
2932                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2933                 klass = mono_class_from_mono_type (type);
2934                 gclass = type->data.generic_class;
2935                 g_assert (gclass->is_dynamic);
2936
2937                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2938
2939                 name = mono_string_to_utf8 (rmb.name);
2940
2941                 sig = method_builder_encode_signature (assembly, &rmb);
2942
2943                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2944                 g_free (name);          
2945         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2946                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2947
2948                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2949                 klass = mono_class_from_mono_type (type);
2950
2951                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2952                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2953         } else {
2954                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2955                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2956         }
2957
2958         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2959         return token;
2960 }
2961
2962 static guint32
2963 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2964 {
2965         SigBuffer buf;
2966         int i;
2967         guint32 nparams = context->method_inst->type_argc;
2968         guint32 idx;
2969
2970         if (!assembly->save)
2971                 return 0;
2972
2973         sigbuffer_init (&buf, 32);
2974         /*
2975          * FIXME: vararg, explicit_this, differenc call_conv values...
2976          */
2977         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2978         sigbuffer_add_value (&buf, nparams);
2979
2980         for (i = 0; i < nparams; i++)
2981                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2982
2983         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2984         sigbuffer_free (&buf);
2985         return idx;
2986 }
2987
2988 static guint32
2989 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2990 {
2991         MonoDynamicTable *table;
2992         guint32 *values;
2993         guint32 token, mtoken = 0, sig;
2994         MonoMethodInflated *imethod;
2995         MonoMethod *declaring;
2996
2997         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2998
2999         g_assert (method->is_inflated);
3000         imethod = (MonoMethodInflated *) method;
3001         declaring = imethod->declaring;
3002
3003         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3004         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3005
3006         if (!mono_method_signature (declaring)->generic_param_count)
3007                 return mtoken;
3008
3009         switch (mono_metadata_token_table (mtoken)) {
3010         case MONO_TABLE_MEMBERREF:
3011                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3012                 break;
3013         case MONO_TABLE_METHOD:
3014                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3015                 break;
3016         default:
3017                 g_assert_not_reached ();
3018         }
3019
3020         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3021
3022         if (assembly->save) {
3023                 alloc_table (table, table->rows + 1);
3024                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3025                 values [MONO_METHODSPEC_METHOD] = mtoken;
3026                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3027         }
3028
3029         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3030         table->next_idx ++;
3031
3032         return token;
3033 }
3034
3035 static guint32
3036 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3037 {
3038         MonoMethodInflated *imethod;
3039         guint32 token;
3040         
3041         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3042         if (token)
3043                 return token;
3044
3045         g_assert (method->is_inflated);
3046         imethod = (MonoMethodInflated *) method;
3047
3048         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3049                 token = method_encode_methodspec (assembly, method);
3050         } else {
3051                 guint32 sig = method_encode_signature (
3052                         assembly, mono_method_signature (imethod->declaring));
3053                 token = mono_image_get_memberref_token (
3054                         assembly, &method->klass->byval_arg, method->name, sig);
3055         }
3056
3057         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3058         return token;
3059 }
3060
3061 static guint32
3062 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3063 {
3064         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3065         guint32 sig, token;
3066
3067         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3068         token = mono_image_get_memberref_token (
3069                 assembly, &m->klass->byval_arg, m->name, sig);
3070
3071         return token;
3072 }
3073
3074 static guint32
3075 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3076 {
3077         MonoDynamicTable *table;
3078         MonoClass *klass;
3079         MonoType *type;
3080         guint32 *values;
3081         guint32 token;
3082         SigBuffer buf;
3083         int count, i;
3084
3085         /*
3086          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3087          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3088          * Because of this, we must not insert it into the `typeref' hash table.
3089          */
3090         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3091         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3092         if (token)
3093                 return token;
3094
3095         sigbuffer_init (&buf, 32);
3096
3097         g_assert (tb->generic_params);
3098         klass = mono_class_from_mono_type (type);
3099
3100         if (tb->generic_container)
3101                 mono_reflection_create_generic_class (tb);
3102
3103         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3104         g_assert (klass->generic_container);
3105         sigbuffer_add_value (&buf, klass->byval_arg.type);
3106         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3107
3108         count = mono_array_length (tb->generic_params);
3109         sigbuffer_add_value (&buf, count);
3110         for (i = 0; i < count; i++) {
3111                 MonoReflectionGenericParam *gparam;
3112
3113                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3114
3115                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3116         }
3117
3118         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3119
3120         if (assembly->save) {
3121                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3122                 alloc_table (table, table->rows + 1);
3123                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3124                 values [MONO_TYPESPEC_SIGNATURE] = token;
3125         }
3126         sigbuffer_free (&buf);
3127
3128         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3129         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3130         table->next_idx ++;
3131         return token;
3132 }
3133
3134 /*
3135  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3136  */
3137 static MonoType*
3138 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3139 {
3140         int i, count, len, pos;
3141         MonoType *t;
3142
3143         count = 0;
3144         if (modreq)
3145                 count += mono_array_length (modreq);
3146         if (modopt)
3147                 count += mono_array_length (modopt);
3148
3149         if (count == 0)
3150                 return mono_metadata_type_dup (NULL, type);
3151
3152         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3153         t = g_malloc (len);
3154         memcpy (t, type, MONO_SIZEOF_TYPE);
3155
3156         t->num_mods = count;
3157         pos = 0;
3158         if (modreq) {
3159                 for (i = 0; i < mono_array_length (modreq); ++i) {
3160                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3161                         t->modifiers [pos].required = 1;
3162                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3163                         pos ++;
3164                 }
3165         }
3166         if (modopt) {
3167                 for (i = 0; i < mono_array_length (modopt); ++i) {
3168                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3169                         t->modifiers [pos].required = 0;
3170                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3171                         pos ++;
3172                 }
3173         }
3174
3175         return t;
3176 }
3177
3178 static void
3179 init_type_builder_generics (MonoObject *type)
3180 {
3181         MonoReflectionTypeBuilder *tb;
3182
3183         if (!is_sre_type_builder(mono_object_class (type)))
3184                 return;
3185         tb = (MonoReflectionTypeBuilder *)type;
3186
3187         if (tb && tb->generic_container)
3188                 mono_reflection_create_generic_class (tb);
3189 }
3190
3191 static guint32
3192 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3193 {
3194         MonoDynamicTable *table;
3195         MonoClass *klass;
3196         MonoType *custom = NULL, *type;
3197         guint32 *values;
3198         guint32 token, pclass, parent, sig;
3199         gchar *name;
3200
3201         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3202         if (token)
3203                 return token;
3204
3205         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3206         name = mono_string_to_utf8 (fb->name);
3207
3208         /*FIXME this is one more layer of ugliness due how types are created.*/
3209         init_type_builder_generics (fb->type);
3210
3211         /* fb->type does not include the custom modifiers */
3212         /* FIXME: We should do this in one place when a fieldbuilder is created */
3213         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3214         if (fb->modreq || fb->modopt)
3215                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3216
3217         sig = fieldref_encode_signature (assembly, NULL, type);
3218         g_free (custom);
3219
3220         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3221         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3222         
3223         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3224         parent >>= MONO_TYPEDEFORREF_BITS;
3225
3226         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3227
3228         if (assembly->save) {
3229                 alloc_table (table, table->rows + 1);
3230                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3231                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3232                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3233                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3234         }
3235
3236         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3237         table->next_idx ++;
3238         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3239         g_free (name);
3240         return token;
3241 }
3242
3243 static guint32
3244 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3245 {
3246         SigBuffer buf;
3247         guint32 nargs;
3248         guint32 size;
3249         guint32 i, idx;
3250
3251         if (!assembly->save)
3252                 return 0;
3253
3254         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3255         g_assert (helper->type == 2);
3256
3257         if (helper->arguments)
3258                 nargs = mono_array_length (helper->arguments);
3259         else
3260                 nargs = 0;
3261
3262         size = 10 + (nargs * 10);
3263         
3264         sigbuffer_init (&buf, 32);
3265
3266         /* Encode calling convention */
3267         /* Change Any to Standard */
3268         if ((helper->call_conv & 0x03) == 0x03)
3269                 helper->call_conv = 0x01;
3270         /* explicit_this implies has_this */
3271         if (helper->call_conv & 0x40)
3272                 helper->call_conv &= 0x20;
3273
3274         if (helper->call_conv == 0) { /* Unmanaged */
3275                 idx = helper->unmanaged_call_conv - 1;
3276         } else {
3277                 /* Managed */
3278                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3279                 if (helper->call_conv & 0x02) /* varargs */
3280                         idx += 0x05;
3281         }
3282
3283         sigbuffer_add_byte (&buf, idx);
3284         sigbuffer_add_value (&buf, nargs);
3285         encode_reflection_type (assembly, helper->return_type, &buf);
3286         for (i = 0; i < nargs; ++i) {
3287                 MonoArray *modreqs = NULL;
3288                 MonoArray *modopts = NULL;
3289                 MonoReflectionType *pt;
3290
3291                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3292                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3293                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3294                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3295
3296                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3297                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3298                 encode_reflection_type (assembly, pt, &buf);
3299         }
3300         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3301         sigbuffer_free (&buf);
3302
3303         return idx;
3304 }
3305
3306 static guint32 
3307 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3308 {
3309         guint32 idx;
3310         MonoDynamicTable *table;
3311         guint32 *values;
3312
3313         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3314         idx = table->next_idx ++;
3315         table->rows ++;
3316         alloc_table (table, table->rows);
3317         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3318
3319         values [MONO_STAND_ALONE_SIGNATURE] =
3320                 mono_reflection_encode_sighelper (assembly, helper);
3321
3322         return idx;
3323 }
3324
3325 static int
3326 reflection_cc_to_file (int call_conv) {
3327         switch (call_conv & 0x3) {
3328         case 0:
3329         case 1: return MONO_CALL_DEFAULT;
3330         case 2: return MONO_CALL_VARARG;
3331         default:
3332                 g_assert_not_reached ();
3333         }
3334         return 0;
3335 }
3336 #endif /* !DISABLE_REFLECTION_EMIT */
3337
3338 typedef struct {
3339         MonoType *parent;
3340         MonoMethodSignature *sig;
3341         char *name;
3342         guint32 token;
3343 } ArrayMethod;
3344
3345 #ifndef DISABLE_REFLECTION_EMIT
3346 static guint32
3347 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3348 {
3349         guint32 nparams, i;
3350         GList *tmp;
3351         char *name;
3352         MonoMethodSignature *sig;
3353         ArrayMethod *am;
3354         MonoType *mtype;
3355
3356         name = mono_string_to_utf8 (m->name);
3357         nparams = mono_array_length (m->parameters);
3358         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3359         sig->hasthis = 1;
3360         sig->sentinelpos = -1;
3361         sig->call_convention = reflection_cc_to_file (m->call_conv);
3362         sig->param_count = nparams;
3363         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3364         mtype = mono_reflection_type_get_handle (m->parent);
3365         for (i = 0; i < nparams; ++i)
3366                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3367
3368         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3369                 am = tmp->data;
3370                 if (strcmp (name, am->name) == 0 && 
3371                                 mono_metadata_type_equal (am->parent, mtype) &&
3372                                 mono_metadata_signature_equal (am->sig, sig)) {
3373                         g_free (name);
3374                         g_free (sig);
3375                         m->table_idx = am->token & 0xffffff;
3376                         return am->token;
3377                 }
3378         }
3379         am = g_new0 (ArrayMethod, 1);
3380         am->name = name;
3381         am->sig = sig;
3382         am->parent = mtype;
3383         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3384                 method_encode_signature (assembly, sig));
3385         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3386         m->table_idx = am->token & 0xffffff;
3387         return am->token;
3388 }
3389
3390 /*
3391  * Insert into the metadata tables all the info about the TypeBuilder tb.
3392  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3393  */
3394 static void
3395 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3396 {
3397         MonoDynamicTable *table;
3398         guint *values;
3399         int i, is_object = 0, is_system = 0;
3400         char *n;
3401
3402         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3403         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3404         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3405         n = mono_string_to_utf8 (tb->name);
3406         if (strcmp (n, "Object") == 0)
3407                 is_object++;
3408         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3409         g_free (n);
3410         n = mono_string_to_utf8 (tb->nspace);
3411         if (strcmp (n, "System") == 0)
3412                 is_system++;
3413         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3414         g_free (n);
3415         if (tb->parent && !(is_system && is_object) && 
3416                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3417                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3418         } else {
3419                 values [MONO_TYPEDEF_EXTENDS] = 0;
3420         }
3421         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3422         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3423
3424         /*
3425          * if we have explicitlayout or sequentiallayouts, output data in the
3426          * ClassLayout table.
3427          */
3428         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3429                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3430                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3431                 table->rows++;
3432                 alloc_table (table, table->rows);
3433                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3434                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3435                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3436                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3437         }
3438
3439         /* handle interfaces */
3440         if (tb->interfaces) {
3441                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3442                 i = table->rows;
3443                 table->rows += mono_array_length (tb->interfaces);
3444                 alloc_table (table, table->rows);
3445                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3446                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3447                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3448                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3449                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3450                         values += MONO_INTERFACEIMPL_SIZE;
3451                 }
3452         }
3453
3454         /* handle fields */
3455         if (tb->fields) {
3456                 table = &assembly->tables [MONO_TABLE_FIELD];
3457                 table->rows += tb->num_fields;
3458                 alloc_table (table, table->rows);
3459                 for (i = 0; i < tb->num_fields; ++i)
3460                         mono_image_get_field_info (
3461                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3462         }
3463
3464         /* handle constructors */
3465         if (tb->ctors) {
3466                 table = &assembly->tables [MONO_TABLE_METHOD];
3467                 table->rows += mono_array_length (tb->ctors);
3468                 alloc_table (table, table->rows);
3469                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3470                         mono_image_get_ctor_info (domain,
3471                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3472         }
3473
3474         /* handle methods */
3475         if (tb->methods) {
3476                 table = &assembly->tables [MONO_TABLE_METHOD];
3477                 table->rows += tb->num_methods;
3478                 alloc_table (table, table->rows);
3479                 for (i = 0; i < tb->num_methods; ++i)
3480                         mono_image_get_method_info (
3481                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3482         }
3483
3484         /* Do the same with properties etc.. */
3485         if (tb->events && mono_array_length (tb->events)) {
3486                 table = &assembly->tables [MONO_TABLE_EVENT];
3487                 table->rows += mono_array_length (tb->events);
3488                 alloc_table (table, table->rows);
3489                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3490                 table->rows ++;
3491                 alloc_table (table, table->rows);
3492                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3493                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3494                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3495                 for (i = 0; i < mono_array_length (tb->events); ++i)
3496                         mono_image_get_event_info (
3497                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3498         }
3499         if (tb->properties && mono_array_length (tb->properties)) {
3500                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3501                 table->rows += mono_array_length (tb->properties);
3502                 alloc_table (table, table->rows);
3503                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3504                 table->rows ++;
3505                 alloc_table (table, table->rows);
3506                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3507                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3508                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3509                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3510                         mono_image_get_property_info (
3511                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3512         }
3513
3514         /* handle generic parameters */
3515         if (tb->generic_params) {
3516                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3517                 table->rows += mono_array_length (tb->generic_params);
3518                 alloc_table (table, table->rows);
3519                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3520                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3521
3522                         mono_image_get_generic_param_info (
3523                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3524                 }
3525         }
3526
3527         mono_image_add_decl_security (assembly, 
3528                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3529
3530         if (tb->subtypes) {
3531                 MonoDynamicTable *ntable;
3532                 
3533                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3534                 ntable->rows += mono_array_length (tb->subtypes);
3535                 alloc_table (ntable, ntable->rows);
3536                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3537
3538                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3539                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3540
3541                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3542                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3543                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3544                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3545                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3546                                 ntable->next_idx, ntable->rows);*/
3547                         values += MONO_NESTED_CLASS_SIZE;
3548                         ntable->next_idx++;
3549                 }
3550         }
3551 }
3552 #endif
3553
3554 static void
3555 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3556 {
3557         int i;
3558
3559         mono_ptr_array_append (*types, type);
3560
3561         if (!type->subtypes)
3562                 return;
3563
3564         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3565                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3566                 collect_types (types, subtype);
3567         }
3568 }
3569
3570 static gint
3571 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3572 {
3573         if ((*type1)->table_idx < (*type2)->table_idx)
3574                 return -1;
3575         else
3576                 if ((*type1)->table_idx > (*type2)->table_idx)
3577                         return 1;
3578         else
3579                 return 0;
3580 }
3581
3582 static void
3583 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3584         int i;
3585
3586         if (!pinfo)
3587                 return;
3588         for (i = 0; i < mono_array_length (pinfo); ++i) {
3589                 MonoReflectionParamBuilder *pb;
3590                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3591                 if (!pb)
3592                         continue;
3593                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3594         }
3595 }
3596
3597 static void
3598 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3599         int i;
3600         
3601         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3602         if (tb->fields) {
3603                 for (i = 0; i < tb->num_fields; ++i) {
3604                         MonoReflectionFieldBuilder* fb;
3605                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3606                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3607                 }
3608         }
3609         if (tb->events) {
3610                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3611                         MonoReflectionEventBuilder* eb;
3612                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3613                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3614                 }
3615         }
3616         if (tb->properties) {
3617                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3618                         MonoReflectionPropertyBuilder* pb;
3619                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3620                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3621                 }
3622         }
3623         if (tb->ctors) {
3624                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3625                         MonoReflectionCtorBuilder* cb;
3626                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3627                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3628                         params_add_cattrs (assembly, cb->pinfo);
3629                 }
3630         }
3631
3632         if (tb->methods) {
3633                 for (i = 0; i < tb->num_methods; ++i) {
3634                         MonoReflectionMethodBuilder* mb;
3635                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3636                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3637                         params_add_cattrs (assembly, mb->pinfo);
3638                 }
3639         }
3640
3641         if (tb->subtypes) {
3642                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3643                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3644         }
3645 }
3646
3647 static void
3648 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3649 {
3650         int i;
3651         
3652         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3653
3654         if (moduleb->global_methods) {
3655                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3656                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3657                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3658                         params_add_cattrs (assembly, mb->pinfo);
3659                 }
3660         }
3661
3662         if (moduleb->global_fields) {
3663                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3664                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3665                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3666                 }
3667         }
3668         
3669         if (moduleb->types) {
3670                 for (i = 0; i < moduleb->num_types; ++i)
3671                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3672         }
3673 }
3674
3675 static void
3676 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3677 {
3678         MonoDynamicTable *table;
3679         guint32 *values;
3680         char blob_size [6];
3681         guchar hash [20];
3682         char *b = blob_size;
3683         char *dir, *path;
3684
3685         table = &assembly->tables [MONO_TABLE_FILE];
3686         table->rows++;
3687         alloc_table (table, table->rows);
3688         values = table->values + table->next_idx * MONO_FILE_SIZE;
3689         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3690         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3691         if (module->image->dynamic) {
3692                 /* This depends on the fact that the main module is emitted last */
3693                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3694                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3695         } else {
3696                 dir = NULL;
3697                 path = g_strdup (module->image->name);
3698         }
3699         mono_sha1_get_digest_from_file (path, hash);
3700         g_free (dir);
3701         g_free (path);
3702         mono_metadata_encode_value (20, b, &b);
3703         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3704         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3705         table->next_idx ++;
3706 }
3707
3708 static void
3709 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3710 {
3711         MonoDynamicTable *table;
3712         int i;
3713
3714         table = &assembly->tables [MONO_TABLE_MODULE];
3715         mb->table_idx = table->next_idx ++;
3716         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3717         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3718         i /= 16;
3719         ++i;
3720         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3721         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3722         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3723         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3724 }
3725
3726 static guint32
3727 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3728         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3729 {
3730         MonoDynamicTable *table;
3731         guint32 *values;
3732         guint32 visib, res;
3733
3734         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3735         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3736                 return 0;
3737
3738         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3739         table->rows++;
3740         alloc_table (table, table->rows);
3741         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3742
3743         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3744         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3745         if (klass->nested_in)
3746                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3747         else
3748                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3749         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3750         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3751
3752         res = table->next_idx;
3753
3754         table->next_idx ++;
3755
3756         /* Emit nested types */
3757         if (klass->ext && klass->ext->nested_classes) {
3758                 GList *tmp;
3759
3760                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3761                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3762         }
3763
3764         return res;
3765 }
3766
3767 static void
3768 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3769         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3770 {
3771         MonoClass *klass;
3772         guint32 idx, i;
3773
3774         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3775
3776         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3777
3778         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3779                                                                                                    parent_index, assembly);
3780
3781         /* 
3782          * Emit nested types
3783          * We need to do this ourselves since klass->nested_classes is not set up.
3784          */
3785         if (tb->subtypes) {
3786                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3787                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3788         }
3789 }
3790
3791 static void
3792 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3793         guint32 module_index, MonoDynamicImage *assembly)
3794 {
3795         MonoImage *image = module->image;
3796         MonoTableInfo  *t;
3797         guint32 i;
3798
3799         t = &image->tables [MONO_TABLE_TYPEDEF];
3800
3801         for (i = 0; i < t->rows; ++i) {
3802                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3803
3804                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3805                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3806         }
3807 }
3808
3809 static void
3810 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3811 {
3812         MonoDynamicTable *table;
3813         guint32 *values;
3814         guint32 scope, scope_idx, impl, current_idx;
3815         gboolean forwarder = TRUE;
3816         gpointer iter = NULL;
3817         MonoClass *nested;
3818
3819         if (klass->nested_in) {
3820                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3821                 forwarder = FALSE;
3822         } else {
3823                 scope = resolution_scope_from_image (assembly, klass->image);
3824                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3825                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3826                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3827         }
3828
3829         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3830
3831         table->rows++;
3832         alloc_table (table, table->rows);
3833         current_idx = table->next_idx;
3834         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3835
3836         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3837         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3838         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3839         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3840         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3841
3842         table->next_idx++;
3843
3844         while ((nested = mono_class_get_nested_types (klass, &iter)))
3845                 add_exported_type (assemblyb, assembly, nested, current_idx);
3846 }
3847
3848 static void
3849 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3850 {
3851         MonoClass *klass;
3852         int i;
3853
3854         if (!assemblyb->type_forwarders)
3855                 return;
3856
3857         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3858                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3859                 MonoType *type;
3860                 if (!t)
3861                         continue;
3862
3863                 type = mono_reflection_type_get_handle (t);
3864                 g_assert (type);
3865
3866                 klass = mono_class_from_mono_type (type);
3867
3868                 add_exported_type (assemblyb, assembly, klass, 0);
3869         }
3870 }
3871
3872 #define align_pointer(base,p)\
3873         do {\
3874                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3875                 if (__diff & 3)\
3876                         (p) += 4 - (__diff & 3);\
3877         } while (0)
3878
3879 static int
3880 compare_constants (const void *a, const void *b)
3881 {
3882         const guint32 *a_values = a;
3883         const guint32 *b_values = b;
3884         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3885 }
3886
3887 static int
3888 compare_semantics (const void *a, const void *b)
3889 {
3890         const guint32 *a_values = a;
3891         const guint32 *b_values = b;
3892         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3893         if (assoc)
3894                 return assoc;
3895         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3896 }
3897
3898 static int
3899 compare_custom_attrs (const void *a, const void *b)
3900 {
3901         const guint32 *a_values = a;
3902         const guint32 *b_values = b;
3903
3904         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3905 }
3906
3907 static int
3908 compare_field_marshal (const void *a, const void *b)
3909 {
3910         const guint32 *a_values = a;
3911         const guint32 *b_values = b;
3912
3913         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3914 }
3915
3916 static int
3917 compare_nested (const void *a, const void *b)
3918 {
3919         const guint32 *a_values = a;
3920         const guint32 *b_values = b;
3921
3922         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3923 }
3924
3925 static int
3926 compare_genericparam (const void *a, const void *b)
3927 {
3928         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3929         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3930
3931         if ((*b_entry)->owner == (*a_entry)->owner)
3932                 return 
3933                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3934                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3935         else
3936                 return (*a_entry)->owner - (*b_entry)->owner;
3937 }
3938
3939 static int
3940 compare_declsecurity_attrs (const void *a, const void *b)
3941 {
3942         const guint32 *a_values = a;
3943         const guint32 *b_values = b;
3944
3945         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3946 }
3947
3948 static int
3949 compare_interface_impl (const void *a, const void *b)
3950 {
3951         const guint32 *a_values = a;
3952         const guint32 *b_values = b;
3953
3954         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3955         if (klass)
3956                 return klass;
3957
3958         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3959 }
3960
3961 static void
3962 pad_heap (MonoDynamicStream *sh)
3963 {
3964         if (sh->index & 3) {
3965                 int sz = 4 - (sh->index & 3);
3966                 memset (sh->data + sh->index, 0, sz);
3967                 sh->index += sz;
3968         }
3969 }
3970
3971 struct StreamDesc {
3972         const char *name;
3973         MonoDynamicStream *stream;
3974 };
3975
3976 /*
3977  * build_compressed_metadata() fills in the blob of data that represents the 
3978  * raw metadata as it will be saved in the PE file. The five streams are output 
3979  * and the metadata tables are comnpressed from the guint32 array representation, 
3980  * to the compressed on-disk format.
3981  */
3982 static void
3983 build_compressed_metadata (MonoDynamicImage *assembly)
3984 {
3985         MonoDynamicTable *table;
3986         int i;
3987         guint64 valid_mask = 0;
3988         guint64 sorted_mask;
3989         guint32 heapt_size = 0;
3990         guint32 meta_size = 256; /* allow for header and other stuff */
3991         guint32 table_offset;
3992         guint32 ntables = 0;
3993         guint64 *int64val;
3994         guint32 *int32val;
3995         guint16 *int16val;
3996         MonoImage *meta;
3997         unsigned char *p;
3998         struct StreamDesc stream_desc [5];
3999
4000         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4001         for (i = 0; i < assembly->gen_params->len; i++){
4002                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4003                 write_generic_param_entry (assembly, entry);
4004         }
4005
4006         stream_desc [0].name  = "#~";
4007         stream_desc [0].stream = &assembly->tstream;
4008         stream_desc [1].name  = "#Strings";
4009         stream_desc [1].stream = &assembly->sheap;
4010         stream_desc [2].name  = "#US";
4011         stream_desc [2].stream = &assembly->us;
4012         stream_desc [3].name  = "#Blob";
4013         stream_desc [3].stream = &assembly->blob;
4014         stream_desc [4].name  = "#GUID";
4015         stream_desc [4].stream = &assembly->guid;
4016         
4017         /* tables that are sorted */
4018         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4019                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4020                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4021                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4022                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4023                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4024                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4025         
4026         /* Compute table sizes */
4027         /* the MonoImage has already been created in mono_image_basic_init() */
4028         meta = &assembly->image;
4029
4030         /* sizes should be multiple of 4 */
4031         pad_heap (&assembly->blob);
4032         pad_heap (&assembly->guid);
4033         pad_heap (&assembly->sheap);
4034         pad_heap (&assembly->us);
4035
4036         /* Setup the info used by compute_sizes () */
4037         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4038         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4039         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4040
4041         meta_size += assembly->blob.index;
4042         meta_size += assembly->guid.index;
4043         meta_size += assembly->sheap.index;
4044         meta_size += assembly->us.index;
4045
4046         for (i=0; i < MONO_TABLE_NUM; ++i)
4047                 meta->tables [i].rows = assembly->tables [i].rows;
4048         
4049         for (i = 0; i < MONO_TABLE_NUM; i++){
4050                 if (meta->tables [i].rows == 0)
4051                         continue;
4052                 valid_mask |= (guint64)1 << i;
4053                 ntables ++;
4054                 meta->tables [i].row_size = mono_metadata_compute_size (
4055                         meta, i, &meta->tables [i].size_bitfield);
4056                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4057         }
4058         heapt_size += 24; /* #~ header size */
4059         heapt_size += ntables * 4;
4060         /* make multiple of 4 */
4061         heapt_size += 3;
4062         heapt_size &= ~3;
4063         meta_size += heapt_size;
4064         meta->raw_metadata = g_malloc0 (meta_size);
4065         p = (unsigned char*)meta->raw_metadata;
4066         /* the metadata signature */
4067         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4068         /* version numbers and 4 bytes reserved */
4069         int16val = (guint16*)p;
4070         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4071         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4072         p += 8;
4073         /* version string */
4074         int32val = (guint32*)p;
4075         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4076         p += 4;
4077         memcpy (p, meta->version, strlen (meta->version));
4078         p += GUINT32_FROM_LE (*int32val);
4079         align_pointer (meta->raw_metadata, p);
4080         int16val = (guint16*)p;
4081         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4082         *int16val = GUINT16_TO_LE (5); /* number of streams */
4083         p += 4;
4084
4085         /*
4086          * write the stream info.
4087          */
4088         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4089         table_offset += 3; table_offset &= ~3;
4090
4091         assembly->tstream.index = heapt_size;
4092         for (i = 0; i < 5; ++i) {
4093                 int32val = (guint32*)p;
4094                 stream_desc [i].stream->offset = table_offset;
4095                 *int32val++ = GUINT32_TO_LE (table_offset);
4096                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4097                 table_offset += GUINT32_FROM_LE (*int32val);
4098                 table_offset += 3; table_offset &= ~3;
4099                 p += 8;
4100                 strcpy ((char*)p, stream_desc [i].name);
4101                 p += strlen (stream_desc [i].name) + 1;
4102                 align_pointer (meta->raw_metadata, p);
4103         }
4104         /* 
4105          * now copy the data, the table stream header and contents goes first.
4106          */
4107         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4108         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4109         int32val = (guint32*)p;
4110         *int32val = GUINT32_TO_LE (0); /* reserved */
4111         p += 4;
4112
4113         *p++ = 2; /* version */
4114         *p++ = 0;
4115
4116         if (meta->idx_string_wide)
4117                 *p |= 0x01;
4118         if (meta->idx_guid_wide)
4119                 *p |= 0x02;
4120         if (meta->idx_blob_wide)
4121                 *p |= 0x04;
4122         ++p;
4123         *p++ = 1; /* reserved */
4124         int64val = (guint64*)p;
4125         *int64val++ = GUINT64_TO_LE (valid_mask);
4126         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4127         p += 16;
4128         int32val = (guint32*)p;
4129         for (i = 0; i < MONO_TABLE_NUM; i++){
4130                 if (meta->tables [i].rows == 0)
4131                         continue;
4132                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4133         }
4134         p = (unsigned char*)int32val;
4135
4136         /* sort the tables that still need sorting */
4137         table = &assembly->tables [MONO_TABLE_CONSTANT];
4138         if (table->rows)
4139                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4140         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4141         if (table->rows)
4142                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4143         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4144         if (table->rows)
4145                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4146         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4147         if (table->rows)
4148                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4149         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4150         if (table->rows)
4151                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4152         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4153         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4154         if (table->rows)
4155                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4156         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4157         if (table->rows)
4158                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4159
4160         /* compress the tables */
4161         for (i = 0; i < MONO_TABLE_NUM; i++){
4162                 int row, col;
4163                 guint32 *values;
4164                 guint32 bitfield = meta->tables [i].size_bitfield;
4165                 if (!meta->tables [i].rows)
4166                         continue;
4167                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4168                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4169                 meta->tables [i].base = (char*)p;
4170                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4171                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4172                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4173                                 switch (mono_metadata_table_size (bitfield, col)) {
4174                                 case 1:
4175                                         *p++ = values [col];
4176                                         break;
4177                                 case 2:
4178                                         *p++ = values [col] & 0xff;
4179                                         *p++ = (values [col] >> 8) & 0xff;
4180                                         break;
4181                                 case 4:
4182                                         *p++ = values [col] & 0xff;
4183                                         *p++ = (values [col] >> 8) & 0xff;
4184                                         *p++ = (values [col] >> 16) & 0xff;
4185                                         *p++ = (values [col] >> 24) & 0xff;
4186                                         break;
4187                                 default:
4188                                         g_assert_not_reached ();
4189                                 }
4190                         }
4191                 }
4192                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4193         }
4194         
4195         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4196         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4197         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4198         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4199         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4200
4201         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4202 }
4203
4204 /*
4205  * Some tables in metadata need to be sorted according to some criteria, but
4206  * when methods and fields are first created with reflection, they may be assigned a token
4207  * that doesn't correspond to the final token they will get assigned after the sorting.
4208  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4209  * with the reflection objects that represent them. Once all the tables are set up, the 
4210  * reflection objects will contains the correct table index. fixup_method() will fixup the
4211  * tokens for the method with ILGenerator @ilgen.
4212  */
4213 static void
4214 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4215 {
4216         guint32 code_idx = GPOINTER_TO_UINT (value);
4217         MonoReflectionILTokenInfo *iltoken;
4218         MonoReflectionFieldBuilder *field;
4219         MonoReflectionCtorBuilder *ctor;
4220         MonoReflectionMethodBuilder *method;
4221         MonoReflectionTypeBuilder *tb;
4222         MonoReflectionArrayMethod *am;
4223         guint32 i, idx = 0;
4224         unsigned char *target;
4225
4226         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4227                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4228                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4229                 switch (target [3]) {
4230                 case MONO_TABLE_FIELD:
4231                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4232                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4233                                 idx = field->table_idx;
4234                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4235                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4236                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4237                         } else {
4238                                 g_assert_not_reached ();
4239                         }
4240                         break;
4241                 case MONO_TABLE_METHOD:
4242                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4243                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4244                                 idx = method->table_idx;
4245                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4246                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4247                                 idx = ctor->table_idx;
4248                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4249                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4250                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4251                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4252                         } else {
4253                                 g_assert_not_reached ();
4254                         }
4255                         break;
4256                 case MONO_TABLE_TYPEDEF:
4257                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4258                                 g_assert_not_reached ();
4259                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4260                         idx = tb->table_idx;
4261                         break;
4262                 case MONO_TABLE_MEMBERREF:
4263                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4264                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4265                                 idx = am->table_idx;
4266                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4267                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4268                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4269                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4270                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4271                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4272                                 continue;
4273                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4274                                 continue;
4275                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4276                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4277                                 g_assert (is_field_on_inst (f));
4278                                 continue;
4279                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4280                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4281                                 continue;
4282                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4283                                 continue;
4284                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4285                                 continue;
4286                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4287                                 continue;
4288                         } else {
4289                                 g_assert_not_reached ();
4290                         }
4291                         break;
4292                 case MONO_TABLE_METHODSPEC:
4293                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4294                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4295                                 g_assert (mono_method_signature (m)->generic_param_count);
4296                                 continue;
4297                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4298                                 continue;
4299                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4300                                 continue;
4301                         } else {
4302                                 g_assert_not_reached ();
4303                         }
4304                         break;
4305                 default:
4306                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4307                 }
4308                 target [0] = idx & 0xff;
4309                 target [1] = (idx >> 8) & 0xff;
4310                 target [2] = (idx >> 16) & 0xff;
4311         }
4312 }
4313
4314 /*
4315  * fixup_cattrs:
4316  *
4317  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4318  * value is not known when the table is emitted.
4319  */
4320 static void
4321 fixup_cattrs (MonoDynamicImage *assembly)
4322 {
4323         MonoDynamicTable *table;
4324         guint32 *values;
4325         guint32 type, i, idx, token;
4326         MonoObject *ctor;
4327
4328         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4329
4330         for (i = 0; i < table->rows; ++i) {
4331                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4332
4333                 type = values [MONO_CUSTOM_ATTR_TYPE];
4334                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4335                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4336                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4337                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4338                         g_assert (ctor);
4339
4340                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4341                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4342                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4343                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4344                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4345                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4346                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4347                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4348                         }
4349                 }
4350         }
4351 }
4352
4353 static void
4354 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4355 {
4356         MonoDynamicTable *table;
4357         guint32 *values;
4358
4359         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4360         table->rows++;
4361         alloc_table (table, table->rows);
4362         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4363         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4364         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4365         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4366         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4367         table->next_idx++;
4368 }
4369
4370 static void
4371 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4372 {
4373         MonoDynamicTable *table;
4374         guint32 *values;
4375         char blob_size [6];
4376         guchar hash [20];
4377         char *b = blob_size;
4378         char *name, *sname;
4379         guint32 idx, offset;
4380
4381         if (rsrc->filename) {
4382                 name = mono_string_to_utf8 (rsrc->filename);
4383                 sname = g_path_get_basename (name);
4384         
4385                 table = &assembly->tables [MONO_TABLE_FILE];
4386                 table->rows++;
4387                 alloc_table (table, table->rows);
4388                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4389                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4390                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4391                 g_free (sname);
4392
4393                 mono_sha1_get_digest_from_file (name, hash);
4394                 mono_metadata_encode_value (20, b, &b);
4395                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4396                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4397                 g_free (name);
4398                 idx = table->next_idx++;
4399                 rsrc->offset = 0;
4400                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4401         } else {
4402                 char sizebuf [4];
4403                 char *data;
4404                 guint len;
4405                 if (rsrc->data) {
4406                         data = mono_array_addr (rsrc->data, char, 0);
4407                         len = mono_array_length (rsrc->data);
4408                 } else {
4409                         data = NULL;
4410                         len = 0;
4411                 }
4412                 offset = len;
4413                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4414                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4415                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4416                 mono_image_add_stream_data (&assembly->resources, data, len);
4417
4418                 if (!mb->is_main)
4419                         /* 
4420                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4421                          * the main module, but that needs to reference the FILE table
4422                          * which isn't emitted yet.
4423                          */
4424                         return;
4425                 else
4426                         idx = 0;
4427         }
4428
4429         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4430 }
4431
4432 static void
4433 set_version_from_string (MonoString *version, guint32 *values)
4434 {
4435         gchar *ver, *p, *str;
4436         guint32 i;
4437         
4438         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4439         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4440         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4441         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4442         if (!version)
4443                 return;
4444         ver = str = mono_string_to_utf8 (version);
4445         for (i = 0; i < 4; ++i) {
4446                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4447                 switch (*p) {
4448                 case '.':
4449                         p++;
4450                         break;
4451                 case '*':
4452                         /* handle Revision and Build */
4453                         p++;
4454                         break;
4455                 }
4456                 ver = p;
4457         }
4458         g_free (str);
4459 }
4460
4461 static guint32
4462 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4463         gsize len;
4464         guint32 token = 0;
4465         char blob_size [6];
4466         char *b = blob_size;
4467
4468         if (!pkey)
4469                 return token;
4470
4471         len = mono_array_length (pkey);
4472         mono_metadata_encode_value (len, b, &b);
4473         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4474         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4475
4476         assembly->public_key = g_malloc (len);
4477         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4478         assembly->public_key_len = len;
4479
4480         /* Special case: check for ECMA key (16 bytes) */
4481         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4482                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4483                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4484         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4485                 /* minimum key size (in 2.0) is 384 bits */
4486                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4487         } else {
4488                 /* FIXME - verifier */
4489                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4490                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4491         }
4492         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4493
4494         return token;
4495 }
4496
4497 static void
4498 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4499 {
4500         MonoDynamicTable *table;
4501         MonoDynamicImage *assembly;
4502         MonoReflectionAssemblyBuilder *assemblyb;
4503         MonoDomain *domain;
4504         guint32 *values;
4505         int i;
4506         guint32 module_index;
4507
4508         assemblyb = moduleb->assemblyb;
4509         assembly = moduleb->dynamic_image;
4510         domain = mono_object_domain (assemblyb);
4511
4512         /* Emit ASSEMBLY table */
4513         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4514         alloc_table (table, 1);
4515         values = table->values + MONO_ASSEMBLY_SIZE;
4516         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4517         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4518         if (assemblyb->culture) {
4519                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4520         } else {
4521                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4522         }
4523         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4524         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4525         set_version_from_string (assemblyb->version, values);
4526
4527         /* Emit FILE + EXPORTED_TYPE table */
4528         module_index = 0;
4529         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4530                 int j;
4531                 MonoReflectionModuleBuilder *file_module = 
4532                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4533                 if (file_module != moduleb) {
4534                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4535                         module_index ++;
4536                         if (file_module->types) {
4537                                 for (j = 0; j < file_module->num_types; ++j) {
4538                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4539                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4540                                 }
4541                         }
4542                 }
4543         }
4544         if (assemblyb->loaded_modules) {
4545                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4546                         MonoReflectionModule *file_module = 
4547                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4548                         mono_image_fill_file_table (domain, file_module, assembly);
4549                         module_index ++;
4550                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4551                 }
4552         }
4553         if (assemblyb->type_forwarders)
4554                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4555
4556         /* Emit MANIFESTRESOURCE table */
4557         module_index = 0;
4558         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4559                 int j;
4560                 MonoReflectionModuleBuilder *file_module = 
4561                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4562                 /* The table for the main module is emitted later */
4563                 if (file_module != moduleb) {
4564                         module_index ++;
4565                         if (file_module->resources) {
4566                                 int len = mono_array_length (file_module->resources);
4567                                 for (j = 0; j < len; ++j) {
4568                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4569                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4570                                 }
4571                         }
4572                 }
4573         }               
4574 }
4575
4576 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4577
4578 /*
4579  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4580  * for the modulebuilder @moduleb.
4581  * At the end of the process, method and field tokens are fixed up and the 
4582  * on-disk compressed metadata representation is created.
4583  */
4584 void
4585 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4586 {
4587         MonoDynamicTable *table;
4588         MonoDynamicImage *assembly;
4589         MonoReflectionAssemblyBuilder *assemblyb;
4590         MonoDomain *domain;
4591         MonoPtrArray types;
4592         guint32 *values;
4593         int i, j;
4594
4595         assemblyb = moduleb->assemblyb;
4596         assembly = moduleb->dynamic_image;
4597         domain = mono_object_domain (assemblyb);
4598
4599         if (assembly->text_rva)
4600                 return;
4601
4602         assembly->text_rva = START_TEXT_RVA;
4603
4604         if (moduleb->is_main) {
4605                 mono_image_emit_manifest (moduleb);
4606         }
4607
4608         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4609         table->rows = 1; /* .<Module> */
4610         table->next_idx++;
4611         alloc_table (table, table->rows);
4612         /*
4613          * Set the first entry.
4614          */
4615         values = table->values + table->columns;
4616         values [MONO_TYPEDEF_FLAGS] = 0;
4617         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4618         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4619         values [MONO_TYPEDEF_EXTENDS] = 0;
4620         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4621         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4622
4623         /* 
4624          * handle global methods 
4625          * FIXME: test what to do when global methods are defined in multiple modules.
4626          */
4627         if (moduleb->global_methods) {
4628                 table = &assembly->tables [MONO_TABLE_METHOD];
4629                 table->rows += mono_array_length (moduleb->global_methods);
4630                 alloc_table (table, table->rows);
4631                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4632                         mono_image_get_method_info (
4633                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4634         }
4635         if (moduleb->global_fields) {
4636                 table = &assembly->tables [MONO_TABLE_FIELD];
4637                 table->rows += mono_array_length (moduleb->global_fields);
4638                 alloc_table (table, table->rows);
4639                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4640                         mono_image_get_field_info (
4641                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4642         }
4643
4644         table = &assembly->tables [MONO_TABLE_MODULE];
4645         alloc_table (table, 1);
4646         mono_image_fill_module_table (domain, moduleb, assembly);
4647
4648         /* Collect all types into a list sorted by their table_idx */
4649         mono_ptr_array_init (types, moduleb->num_types);
4650
4651         if (moduleb->types)
4652                 for (i = 0; i < moduleb->num_types; ++i) {
4653                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4654                         collect_types (&types, type);
4655                 }
4656
4657         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4658         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4659         table->rows += mono_ptr_array_size (types);
4660         alloc_table (table, table->rows);
4661
4662         /*
4663          * Emit type names + namespaces at one place inside the string heap,
4664          * so load_class_names () needs to touch fewer pages.
4665          */
4666         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4668                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4669         }
4670         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4671                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4672                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4673         }
4674
4675         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4676                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4677                 mono_image_get_type_info (domain, type, assembly);
4678         }
4679
4680         /* 
4681          * table->rows is already set above and in mono_image_fill_module_table.
4682          */
4683         /* add all the custom attributes at the end, once all the indexes are stable */
4684         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4685
4686         /* CAS assembly permissions */
4687         if (assemblyb->permissions_minimum)
4688                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4689         if (assemblyb->permissions_optional)
4690                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4691         if (assemblyb->permissions_refused)
4692                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4693
4694         module_add_cattrs (assembly, moduleb);
4695
4696         /* fixup tokens */
4697         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4698
4699         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4700          * the final tokens and don't need another fixup pass. */
4701
4702         if (moduleb->global_methods) {
4703                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4704                         MonoReflectionMethodBuilder *mb = mono_array_get (
4705                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4706                         mono_image_add_methodimpl (assembly, mb);
4707                 }
4708         }
4709
4710         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4711                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4712                 if (type->methods) {
4713                         for (j = 0; j < type->num_methods; ++j) {
4714                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4715                                         type->methods, MonoReflectionMethodBuilder*, j);
4716
4717                                 mono_image_add_methodimpl (assembly, mb);
4718                         }
4719                 }
4720         }
4721
4722         mono_ptr_array_destroy (types);
4723
4724         fixup_cattrs (assembly);
4725 }
4726
4727 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4728
4729 void
4730 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4731 {
4732         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4733 }
4734
4735 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4736
4737
4738 typedef struct {
4739         guint32 import_lookup_table;
4740         guint32 timestamp;
4741         guint32 forwarder;
4742         guint32 name_rva;
4743         guint32 import_address_table_rva;
4744 } MonoIDT;
4745
4746 typedef struct {
4747         guint32 name_rva;
4748         guint32 flags;
4749 } MonoILT;
4750
4751 #ifndef DISABLE_REFLECTION_EMIT
4752
4753 /*
4754  * mono_image_insert_string:
4755  * @module: module builder object
4756  * @str: a string
4757  *
4758  * Insert @str into the user string stream of @module.
4759  */
4760 guint32
4761 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4762 {
4763         MonoDynamicImage *assembly;
4764         guint32 idx;
4765         char buf [16];
4766         char *b = buf;
4767         
4768         MONO_ARCH_SAVE_REGS;
4769
4770         if (!module->dynamic_image)
4771                 mono_image_module_basic_init (module);
4772
4773         assembly = module->dynamic_image;
4774         
4775         if (assembly->save) {
4776                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4777                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4778 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4779         {
4780                 char *swapped = g_malloc (2 * mono_string_length (str));
4781                 const char *p = (const char*)mono_string_chars (str);
4782
4783                 swap_with_size (swapped, p, 2, mono_string_length (str));
4784                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4785                 g_free (swapped);
4786         }
4787 #else
4788                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4789 #endif
4790                 mono_image_add_stream_data (&assembly->us, "", 1);
4791         } else {
4792                 idx = assembly->us.index ++;
4793         }
4794
4795         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4796
4797         return MONO_TOKEN_STRING | idx;
4798 }
4799
4800 guint32
4801 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4802 {
4803         MonoClass *klass;
4804         guint32 token = 0;
4805         MonoMethodSignature *sig;
4806
4807         klass = obj->vtable->klass;
4808         if (strcmp (klass->name, "MonoMethod") == 0) {
4809                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4810                 MonoMethodSignature *old;
4811                 guint32 sig_token, parent;
4812                 int nargs, i;
4813
4814                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4815
4816                 nargs = mono_array_length (opt_param_types);
4817                 old = mono_method_signature (method);
4818                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4819
4820                 sig->hasthis = old->hasthis;
4821                 sig->explicit_this = old->explicit_this;
4822                 sig->call_convention = old->call_convention;
4823                 sig->generic_param_count = old->generic_param_count;
4824                 sig->param_count = old->param_count + nargs;
4825                 sig->sentinelpos = old->param_count;
4826                 sig->ret = old->ret;
4827
4828                 for (i = 0; i < old->param_count; i++)
4829                         sig->params [i] = old->params [i];
4830
4831                 for (i = 0; i < nargs; i++) {
4832                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4833                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4834                 }
4835
4836                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4837                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4838                 parent >>= MONO_TYPEDEFORREF_BITS;
4839
4840                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4841                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4842
4843                 sig_token = method_encode_signature (assembly, sig);
4844                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4845         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4846                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4847                 ReflectionMethodBuilder rmb;
4848                 guint32 parent, sig_token;
4849                 int nopt_args, nparams, ngparams, i;
4850                 char *name;
4851
4852                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4853                 rmb.opt_types = opt_param_types;
4854                 nopt_args = mono_array_length (opt_param_types);
4855
4856                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4857                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4858                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4859
4860                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4861                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4862                 sig->call_convention = rmb.call_conv;
4863                 sig->generic_param_count = ngparams;
4864                 sig->param_count = nparams + nopt_args;
4865                 sig->sentinelpos = nparams;
4866                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4867
4868                 for (i = 0; i < nparams; i++) {
4869                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4870                         sig->params [i] = mono_reflection_type_get_handle (rt);
4871                 }
4872
4873                 for (i = 0; i < nopt_args; i++) {
4874                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4875                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4876                 }
4877
4878                 sig_token = method_builder_encode_signature (assembly, &rmb);
4879
4880                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4881                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4882
4883                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4884                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4885
4886                 name = mono_string_to_utf8 (rmb.name);
4887                 token = mono_image_get_varargs_method_token (
4888                         assembly, parent, name, sig_token);
4889                 g_free (name);
4890         } else {
4891                 g_error ("requested method token for %s\n", klass->name);
4892         }
4893
4894         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4895         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4896         return token;
4897 }
4898
4899 /*
4900  * mono_image_create_token:
4901  * @assembly: a dynamic assembly
4902  * @obj:
4903  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4904  *
4905  * Get a token to insert in the IL code stream for the given MemberInfo.
4906  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4907  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4908  * entry.
4909  */
4910 guint32
4911 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4912                                                  gboolean create_open_instance, gboolean register_token)
4913 {
4914         MonoClass *klass;
4915         guint32 token = 0;
4916
4917         klass = obj->vtable->klass;
4918
4919         /* Check for user defined reflection objects */
4920         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4921         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4922                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4923
4924         if (strcmp (klass->name, "MethodBuilder") == 0) {
4925                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4926                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4927
4928                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4929                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4930                 else
4931                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4932                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4933         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4934                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4935                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4936
4937                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4938                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4939                 else
4940                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4941                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4942         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4943                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4944                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4945                 if (tb->generic_params) {
4946                         token = mono_image_get_generic_field_token (assembly, fb);
4947                 } else {
4948                         if (tb->module->dynamic_image == assembly) {
4949                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4950                         } else {
4951                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4952                         }
4953                 }
4954         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4955                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4956                 if (create_open_instance && tb->generic_params) {
4957                         MonoType *type;
4958                         init_type_builder_generics (obj);
4959                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4960                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4961                         token = mono_metadata_token_from_dor (token);
4962                 } else if (tb->module->dynamic_image == assembly) {
4963                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4964                 } else {
4965                         MonoType *type;
4966                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4967                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4968                 }
4969         } else if (strcmp (klass->name, "MonoType") == 0) {
4970                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4971                 MonoClass *mc = mono_class_from_mono_type (type);
4972                 token = mono_metadata_token_from_dor (
4973                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4974         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4975                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4976                 token = mono_metadata_token_from_dor (
4977                         mono_image_typedef_or_ref (assembly, type));
4978         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4979                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4980                 token = mono_metadata_token_from_dor (
4981                         mono_image_typedef_or_ref (assembly, type));
4982         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4983                    strcmp (klass->name, "MonoMethod") == 0 ||
4984                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4985                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4986                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4987                 if (m->method->is_inflated) {
4988                         if (create_open_instance)
4989                                 token = mono_image_get_methodspec_token (assembly, m->method);
4990                         else
4991                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4992                 } else if ((m->method->klass->image == &assembly->image) &&
4993                          !m->method->klass->generic_class) {
4994                         static guint32 method_table_idx = 0xffffff;
4995                         if (m->method->klass->wastypebuilder) {
4996                                 /* we use the same token as the one that was assigned
4997                                  * to the Methodbuilder.
4998                                  * FIXME: do the equivalent for Fields.
4999                                  */
5000                                 token = m->method->token;
5001                         } else {
5002                                 /*
5003                                  * Each token should have a unique index, but the indexes are
5004                                  * assigned by managed code, so we don't know about them. An
5005                                  * easy solution is to count backwards...
5006                                  */
5007                                 method_table_idx --;
5008                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5009                         }
5010                 } else {
5011                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5012                 }
5013                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5014         } else if (strcmp (klass->name, "MonoField") == 0) {
5015                 MonoReflectionField *f = (MonoReflectionField *)obj;
5016                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5017                         static guint32 field_table_idx = 0xffffff;
5018                         field_table_idx --;
5019                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5020                 } else {
5021                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5022                 }
5023                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5024         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5025                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5026                 token = mono_image_get_array_token (assembly, m);
5027         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5028                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5029                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5030         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5031                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5032                 token = mono_metadata_token_from_dor (
5033                         mono_image_typedef_or_ref (assembly, type));
5034         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5035                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5036                 token = mono_image_get_field_on_inst_token (assembly, f);
5037         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5038                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5039                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5040         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5041                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5042                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5043         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5044                 MonoReflectionType *type = (MonoReflectionType *)obj;
5045                 token = mono_metadata_token_from_dor (
5046                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5047         } else {
5048                 g_error ("requested token for %s\n", klass->name);
5049         }
5050
5051         if (register_token)
5052                 mono_image_register_token (assembly, token, obj);
5053
5054         return token;
5055 }
5056
5057 /*
5058  * mono_image_register_token:
5059  *
5060  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5061  * the Module.ResolveXXXToken () methods to work.
5062  */
5063 void
5064 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5065 {
5066         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5067         if (prev) {
5068                 /* There could be multiple MethodInfo objects with the same token */
5069                 //g_assert (prev == obj);
5070         } else {
5071                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5072         }
5073 }
5074
5075 static MonoDynamicImage*
5076 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5077 {
5078         static const guchar entrycode [16] = {0xff, 0x25, 0};
5079         MonoDynamicImage *image;
5080         int i;
5081
5082         const char *version;
5083
5084         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5085                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5086         else
5087                 version = mono_get_runtime_info ()->runtime_version;
5088
5089 #if HAVE_BOEHM_GC
5090         /* The MonoGHashTable's need GC tracking */
5091         image = GC_MALLOC (sizeof (MonoDynamicImage));
5092 #else
5093         image = g_new0 (MonoDynamicImage, 1);
5094 #endif
5095         
5096         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5097         
5098         /*g_print ("created image %p\n", image);*/
5099         /* keep in sync with image.c */
5100         image->image.name = assembly_name;
5101         image->image.assembly_name = image->image.name; /* they may be different */
5102         image->image.module_name = module_name;
5103         image->image.version = g_strdup (version);
5104         image->image.md_version_major = 1;
5105         image->image.md_version_minor = 1;
5106         image->image.dynamic = TRUE;
5107
5108         image->image.references = g_new0 (MonoAssembly*, 1);
5109         image->image.references [0] = NULL;
5110
5111         mono_image_init (&image->image);
5112
5113         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5114         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5115         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5116         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5117         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5118         image->handleref = g_hash_table_new (NULL, NULL);
5119         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5120         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5121         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5122         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5123         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5124         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5125         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5126         image->gen_params = g_ptr_array_new ();
5127         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5128
5129         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5130         string_heap_init (&image->sheap);
5131         mono_image_add_stream_data (&image->us, "", 1);
5132         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5133         /* import tables... */
5134         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5135         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5136         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5137         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5138         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5139         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5140         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5141         stream_data_align (&image->code);
5142
5143         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5144
5145         for (i=0; i < MONO_TABLE_NUM; ++i) {
5146                 image->tables [i].next_idx = 1;
5147                 image->tables [i].columns = table_sizes [i];
5148         }
5149
5150         image->image.assembly = (MonoAssembly*)assembly;
5151         image->run = assembly->run;
5152         image->save = assembly->save;
5153         image->pe_kind = 0x1; /* ILOnly */
5154         image->machine = 0x14c; /* I386 */
5155         
5156         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5157
5158         return image;
5159 }
5160 #endif
5161
5162 static void
5163 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5164 {
5165         g_free (key);
5166 }
5167
5168 static void
5169 release_hashtable (MonoGHashTable **hash)
5170 {
5171         if (*hash) {
5172                 mono_g_hash_table_destroy (*hash);
5173                 *hash = NULL;
5174         }
5175 }
5176
5177 void
5178 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5179 {
5180         release_hashtable (&image->token_fixups);
5181         release_hashtable (&image->handleref_managed);
5182         release_hashtable (&image->tokens);
5183         release_hashtable (&image->remapped_tokens);
5184         release_hashtable (&image->generic_def_objects);
5185         release_hashtable (&image->methodspec);
5186 }
5187
5188 void
5189 mono_dynamic_image_free (MonoDynamicImage *image)
5190 {
5191         MonoDynamicImage *di = image;
5192         GList *list;
5193         int i;
5194
5195         if (di->methodspec)
5196                 mono_g_hash_table_destroy (di->methodspec);
5197         if (di->typespec)
5198                 g_hash_table_destroy (di->typespec);
5199         if (di->typeref)
5200                 g_hash_table_destroy (di->typeref);
5201         if (di->handleref)
5202                 g_hash_table_destroy (di->handleref);
5203         if (di->handleref_managed)
5204                 mono_g_hash_table_destroy (di->handleref_managed);
5205         if (di->tokens)
5206                 mono_g_hash_table_destroy (di->tokens);
5207         if (di->remapped_tokens)
5208                 mono_g_hash_table_destroy (di->remapped_tokens);
5209         if (di->generic_def_objects)
5210                 mono_g_hash_table_destroy (di->generic_def_objects);
5211         if (di->blob_cache) {
5212                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5213                 g_hash_table_destroy (di->blob_cache);
5214         }
5215         if (di->standalonesig_cache)
5216                 g_hash_table_destroy (di->standalonesig_cache);
5217         for (list = di->array_methods; list; list = list->next) {
5218                 ArrayMethod *am = (ArrayMethod *)list->data;
5219                 g_free (am->sig);
5220                 g_free (am->name);
5221                 g_free (am);
5222         }
5223         g_list_free (di->array_methods);
5224         if (di->gen_params) {
5225                 for (i = 0; i < di->gen_params->len; i++) {
5226                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5227                         mono_gc_deregister_root ((char*) &entry->gparam);
5228                         g_free (entry);
5229                 }
5230                 g_ptr_array_free (di->gen_params, TRUE);
5231         }
5232         if (di->token_fixups)
5233                 mono_g_hash_table_destroy (di->token_fixups);
5234         if (di->method_to_table_idx)
5235                 g_hash_table_destroy (di->method_to_table_idx);
5236         if (di->field_to_table_idx)
5237                 g_hash_table_destroy (di->field_to_table_idx);
5238         if (di->method_aux_hash)
5239                 g_hash_table_destroy (di->method_aux_hash);
5240         if (di->vararg_aux_hash)
5241                 g_hash_table_destroy (di->vararg_aux_hash);
5242         g_free (di->strong_name);
5243         g_free (di->win32_res);
5244         if (di->public_key)
5245                 g_free (di->public_key);
5246
5247         /*g_print ("string heap destroy for image %p\n", di);*/
5248         mono_dynamic_stream_reset (&di->sheap);
5249         mono_dynamic_stream_reset (&di->code);
5250         mono_dynamic_stream_reset (&di->resources);
5251         mono_dynamic_stream_reset (&di->us);
5252         mono_dynamic_stream_reset (&di->blob);
5253         mono_dynamic_stream_reset (&di->tstream);
5254         mono_dynamic_stream_reset (&di->guid);
5255         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5256                 g_free (di->tables [i].values);
5257         }
5258 }       
5259
5260 #ifndef DISABLE_REFLECTION_EMIT
5261
5262 /*
5263  * mono_image_basic_init:
5264  * @assembly: an assembly builder object
5265  *
5266  * Create the MonoImage that represents the assembly builder and setup some
5267  * of the helper hash table and the basic metadata streams.
5268  */
5269 void
5270 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5271 {
5272         MonoDynamicAssembly *assembly;
5273         MonoDynamicImage *image;
5274         MonoDomain *domain = mono_object_domain (assemblyb);
5275         
5276         MONO_ARCH_SAVE_REGS;
5277
5278         if (assemblyb->dynamic_assembly)
5279                 return;
5280
5281 #if HAVE_BOEHM_GC
5282         /* assembly->assembly.image might be GC allocated */
5283         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5284 #else
5285         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5286 #endif
5287
5288         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5289         
5290         assembly->assembly.ref_count = 1;
5291         assembly->assembly.dynamic = TRUE;
5292         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5293         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5294         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5295         if (assemblyb->culture)
5296                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5297         else
5298                 assembly->assembly.aname.culture = g_strdup ("");
5299
5300         if (assemblyb->version) {
5301                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5302                         char **version = g_strsplit (vstr, ".", 4);
5303                         char **parts = version;
5304                         assembly->assembly.aname.major = atoi (*parts++);
5305                         assembly->assembly.aname.minor = atoi (*parts++);
5306                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5307                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5308
5309                         g_strfreev (version);
5310                         g_free (vstr);
5311         } else {
5312                         assembly->assembly.aname.major = 0;
5313                         assembly->assembly.aname.minor = 0;
5314                         assembly->assembly.aname.build = 0;
5315                         assembly->assembly.aname.revision = 0;
5316         }
5317
5318         assembly->run = assemblyb->access != 2;
5319         assembly->save = assemblyb->access != 1;
5320         assembly->domain = domain;
5321
5322         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5323         image->initial_image = TRUE;
5324         assembly->assembly.aname.name = image->image.name;
5325         assembly->assembly.image = &image->image;
5326         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5327                 /* -1 to correct for the trailing NULL byte */
5328                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5329                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5330                 }
5331                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5332         }
5333
5334         mono_domain_assemblies_lock (domain);
5335         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5336         mono_domain_assemblies_unlock (domain);
5337
5338         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5339         
5340         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5341         
5342         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5343 }
5344
5345 #endif /* !DISABLE_REFLECTION_EMIT */
5346
5347 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5348
5349 static int
5350 calc_section_size (MonoDynamicImage *assembly)
5351 {
5352         int nsections = 0;
5353
5354         /* alignment constraints */
5355         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5356         g_assert ((assembly->code.index % 4) == 0);
5357         assembly->meta_size += 3;
5358         assembly->meta_size &= ~3;
5359         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5360         g_assert ((assembly->resources.index % 4) == 0);
5361
5362         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5363         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5364         nsections++;
5365
5366         if (assembly->win32_res) {
5367                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5368
5369                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5370                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5371                 nsections++;
5372         }
5373
5374         assembly->sections [MONO_SECTION_RELOC].size = 12;
5375         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5376         nsections++;
5377
5378         return nsections;
5379 }
5380
5381 typedef struct {
5382         guint32 id;
5383         guint32 offset;
5384         GSList *children;
5385         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5386 } ResTreeNode;
5387
5388 static int
5389 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5390 {
5391         ResTreeNode *t1 = (ResTreeNode*)a;
5392         ResTreeNode *t2 = (ResTreeNode*)b;
5393
5394         return t1->id - t2->id;
5395 }
5396
5397 /*
5398  * resource_tree_create:
5399  *
5400  *  Organize the resources into a resource tree.
5401  */
5402 static ResTreeNode *
5403 resource_tree_create (MonoArray *win32_resources)
5404 {
5405         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5406         GSList *l;
5407         int i;
5408
5409         tree = g_new0 (ResTreeNode, 1);
5410         
5411         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5412                 MonoReflectionWin32Resource *win32_res =
5413                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5414
5415                 /* Create node */
5416
5417                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5418                 lang_node = g_new0 (ResTreeNode, 1);
5419                 lang_node->id = win32_res->lang_id;
5420                 lang_node->win32_res = win32_res;
5421
5422                 /* Create type node if neccesary */
5423                 type_node = NULL;
5424                 for (l = tree->children; l; l = l->next)
5425                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5426                                 type_node = (ResTreeNode*)l->data;
5427                                 break;
5428                         }
5429
5430                 if (!type_node) {
5431                         type_node = g_new0 (ResTreeNode, 1);
5432                         type_node->id = win32_res->res_type;
5433
5434                         /* 
5435                          * The resource types have to be sorted otherwise
5436                          * Windows Explorer can't display the version information.
5437                          */
5438                         tree->children = g_slist_insert_sorted (tree->children, 
5439                                 type_node, resource_tree_compare_by_id);
5440                 }
5441
5442                 /* Create res node if neccesary */
5443                 res_node = NULL;
5444                 for (l = type_node->children; l; l = l->next)
5445                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5446                                 res_node = (ResTreeNode*)l->data;
5447                                 break;
5448                         }
5449
5450                 if (!res_node) {
5451                         res_node = g_new0 (ResTreeNode, 1);
5452                         res_node->id = win32_res->res_id;
5453                         type_node->children = g_slist_append (type_node->children, res_node);
5454                 }
5455
5456                 res_node->children = g_slist_append (res_node->children, lang_node);
5457         }
5458
5459         return tree;
5460 }
5461
5462 /*
5463  * resource_tree_encode:
5464  * 
5465  *   Encode the resource tree into the format used in the PE file.
5466  */
5467 static void
5468 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5469 {
5470         char *entries;
5471         MonoPEResourceDir dir;
5472         MonoPEResourceDirEntry dir_entry;
5473         MonoPEResourceDataEntry data_entry;
5474         GSList *l;
5475         guint32 res_id_entries;
5476
5477         /*
5478          * For the format of the resource directory, see the article
5479          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5480          * Matt Pietrek
5481          */
5482
5483         memset (&dir, 0, sizeof (dir));
5484         memset (&dir_entry, 0, sizeof (dir_entry));
5485         memset (&data_entry, 0, sizeof (data_entry));
5486
5487         g_assert (sizeof (dir) == 16);
5488         g_assert (sizeof (dir_entry) == 8);
5489         g_assert (sizeof (data_entry) == 16);
5490
5491         node->offset = p - begin;
5492
5493         /* IMAGE_RESOURCE_DIRECTORY */
5494         res_id_entries = g_slist_length (node->children);
5495         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5496
5497         memcpy (p, &dir, sizeof (dir));
5498         p += sizeof (dir);
5499
5500         /* Reserve space for entries */
5501         entries = p;
5502         p += sizeof (dir_entry) * res_id_entries;
5503
5504         /* Write children */
5505         for (l = node->children; l; l = l->next) {
5506                 ResTreeNode *child = (ResTreeNode*)l->data;
5507
5508                 if (child->win32_res) {
5509                         guint32 size;
5510
5511                         child->offset = p - begin;
5512
5513                         /* IMAGE_RESOURCE_DATA_ENTRY */
5514                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5515                         size = mono_array_length (child->win32_res->res_data);
5516                         data_entry.rde_size = GUINT32_TO_LE (size);
5517
5518                         memcpy (p, &data_entry, sizeof (data_entry));
5519                         p += sizeof (data_entry);
5520
5521                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5522                         p += size;
5523                 } else {
5524                         resource_tree_encode (child, begin, p, &p);
5525                 }
5526         }
5527
5528         /* IMAGE_RESOURCE_ENTRY */
5529         for (l = node->children; l; l = l->next) {
5530                 ResTreeNode *child = (ResTreeNode*)l->data;
5531
5532                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5533                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5534
5535                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5536                 entries += sizeof (dir_entry);
5537         }
5538
5539         *endbuf = p;
5540 }
5541
5542 static void
5543 resource_tree_free (ResTreeNode * node)
5544 {
5545         GSList * list;
5546         for (list = node->children; list; list = list->next)
5547                 resource_tree_free ((ResTreeNode*)list->data);
5548         g_slist_free(node->children);
5549         g_free (node);
5550 }
5551
5552 static void
5553 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5554 {
5555         char *buf;
5556         char *p;
5557         guint32 size, i;
5558         MonoReflectionWin32Resource *win32_res;
5559         ResTreeNode *tree;
5560
5561         if (!assemblyb->win32_resources)
5562                 return;
5563
5564         /*
5565          * Resources are stored in a three level tree inside the PE file.
5566          * - level one contains a node for each type of resource
5567          * - level two contains a node for each resource
5568          * - level three contains a node for each instance of a resource for a
5569          *   specific language.
5570          */
5571
5572         tree = resource_tree_create (assemblyb->win32_resources);
5573
5574         /* Estimate the size of the encoded tree */
5575         size = 0;
5576         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5577                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5578                 size += mono_array_length (win32_res->res_data);
5579         }
5580         /* Directory structure */
5581         size += mono_array_length (assemblyb->win32_resources) * 256;
5582         p = buf = g_malloc (size);
5583
5584         resource_tree_encode (tree, p, p, &p);
5585
5586         g_assert (p - buf <= size);
5587
5588         assembly->win32_res = g_malloc (p - buf);
5589         assembly->win32_res_size = p - buf;
5590         memcpy (assembly->win32_res, buf, p - buf);
5591
5592         g_free (buf);
5593         resource_tree_free (tree);
5594 }
5595
5596 static void
5597 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5598 {
5599         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5600         int i;
5601
5602         p += sizeof (MonoPEResourceDir);
5603         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5604                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5605                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5606                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5607                         fixup_resource_directory (res_section, child, rva);
5608                 } else {
5609                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5610                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5611                 }
5612
5613                 p += sizeof (MonoPEResourceDirEntry);
5614         }
5615 }
5616
5617 static void
5618 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5619 {
5620         guint32 dummy;
5621         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5622                 g_error ("WriteFile returned %d\n", GetLastError ());
5623 }
5624
5625 /*
5626  * mono_image_create_pefile:
5627  * @mb: a module builder object
5628  * 
5629  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5630  * assembly->pefile where it can be easily retrieved later in chunks.
5631  */
5632 void
5633 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5634 {
5635         MonoMSDOSHeader *msdos;
5636         MonoDotNetHeader *header;
5637         MonoSectionTable *section;
5638         MonoCLIHeader *cli_header;
5639         guint32 size, image_size, virtual_base, text_offset;
5640         guint32 header_start, section_start, file_offset, virtual_offset;
5641         MonoDynamicImage *assembly;
5642         MonoReflectionAssemblyBuilder *assemblyb;
5643         MonoDynamicStream pefile_stream = {0};
5644         MonoDynamicStream *pefile = &pefile_stream;
5645         int i, nsections;
5646         guint32 *rva, value;
5647         guchar *p;
5648         static const unsigned char msheader[] = {
5649                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5650                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5651                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5652                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5653                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5654                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5655                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5656                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5657         };
5658
5659         assemblyb = mb->assemblyb;
5660
5661         mono_image_basic_init (assemblyb);
5662         assembly = mb->dynamic_image;
5663
5664         assembly->pe_kind = assemblyb->pe_kind;
5665         assembly->machine = assemblyb->machine;
5666         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5667         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5668         
5669         mono_image_build_metadata (mb);
5670
5671         if (mb->is_main && assemblyb->resources) {
5672                 int len = mono_array_length (assemblyb->resources);
5673                 for (i = 0; i < len; ++i)
5674                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5675         }
5676
5677         if (mb->resources) {
5678                 int len = mono_array_length (mb->resources);
5679                 for (i = 0; i < len; ++i)
5680                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5681         }
5682
5683         build_compressed_metadata (assembly);
5684
5685         if (mb->is_main)
5686                 assembly_add_win32_resources (assembly, assemblyb);
5687
5688         nsections = calc_section_size (assembly);
5689         
5690         /* The DOS header and stub */
5691         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5692         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5693
5694         /* the dotnet header */
5695         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5696
5697         /* the section tables */
5698         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5699
5700         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5701         virtual_offset = VIRT_ALIGN;
5702         image_size = 0;
5703
5704         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5705                 if (!assembly->sections [i].size)
5706                         continue;
5707                 /* align offsets */
5708                 file_offset += FILE_ALIGN - 1;
5709                 file_offset &= ~(FILE_ALIGN - 1);
5710                 virtual_offset += VIRT_ALIGN - 1;
5711                 virtual_offset &= ~(VIRT_ALIGN - 1);
5712
5713                 assembly->sections [i].offset = file_offset;
5714                 assembly->sections [i].rva = virtual_offset;
5715
5716                 file_offset += assembly->sections [i].size;
5717                 virtual_offset += assembly->sections [i].size;
5718                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5719         }
5720
5721         file_offset += FILE_ALIGN - 1;
5722         file_offset &= ~(FILE_ALIGN - 1);
5723
5724         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5725
5726         /* back-patch info */
5727         msdos = (MonoMSDOSHeader*)pefile->data;
5728         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5729
5730         header = (MonoDotNetHeader*)(pefile->data + header_start);
5731         header->pesig [0] = 'P';
5732         header->pesig [1] = 'E';
5733         
5734         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5735         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5736         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5737         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5738         if (assemblyb->pekind == 1) {
5739                 /* it's a dll */
5740                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5741         } else {
5742                 /* it's an exe */
5743                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5744         }
5745
5746         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5747
5748         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5749         header->pe.pe_major = 6;
5750         header->pe.pe_minor = 0;
5751         size = assembly->sections [MONO_SECTION_TEXT].size;
5752         size += FILE_ALIGN - 1;
5753         size &= ~(FILE_ALIGN - 1);
5754         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5755         size = assembly->sections [MONO_SECTION_RSRC].size;
5756         size += FILE_ALIGN - 1;
5757         size &= ~(FILE_ALIGN - 1);
5758         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5759         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5760         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5761         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5762         /* pe_rva_entry_point always at the beginning of the text section */
5763         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5764
5765         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5766         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5767         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5768         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5769         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5770         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5771         size = section_start;
5772         size += FILE_ALIGN - 1;
5773         size &= ~(FILE_ALIGN - 1);
5774         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5775         size = image_size;
5776         size += VIRT_ALIGN - 1;
5777         size &= ~(VIRT_ALIGN - 1);
5778         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5779
5780         /*
5781         // Translate the PEFileKind value to the value expected by the Windows loader
5782         */
5783         {
5784                 short kind;
5785
5786                 /*
5787                 // PEFileKinds.Dll == 1
5788                 // PEFileKinds.ConsoleApplication == 2
5789                 // PEFileKinds.WindowApplication == 3
5790                 //
5791                 // need to get:
5792                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5793                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5794                 */
5795                 if (assemblyb->pekind == 3)
5796                         kind = 2;
5797                 else
5798                         kind = 3;
5799                 
5800                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5801         }    
5802         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5803         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5804         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5805         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5806         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5807         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5808
5809         /* fill data directory entries */
5810
5811         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5812         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5813
5814         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5815         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5816
5817         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5818         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5819         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5820         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5821         /* patch entrypoint name */
5822         if (assemblyb->pekind == 1)
5823                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5824         else
5825                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5826         /* patch imported function RVA name */
5827         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5828         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5829
5830         /* the import table */
5831         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5832         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5833         /* patch imported dll RVA name and other entries in the dir */
5834         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5835         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5836         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5837         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5838         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5839         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5840
5841         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5842         value = (assembly->text_rva + assembly->imp_names_offset);
5843         *p++ = (value) & 0xff;
5844         *p++ = (value >> 8) & (0xff);
5845         *p++ = (value >> 16) & (0xff);
5846         *p++ = (value >> 24) & (0xff);
5847
5848         /* the CLI header info */
5849         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5850         cli_header->ch_size = GUINT32_FROM_LE (72);
5851         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5852         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5853         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5854         if (assemblyb->entry_point) {
5855                 guint32 table_idx = 0;
5856                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5857                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5858                         table_idx = methodb->table_idx;
5859                 } else {
5860                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5861                 }
5862                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5863         } else {
5864                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5865         }
5866         /* The embedded managed resources */
5867         text_offset = assembly->text_rva + assembly->code.index;
5868         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5869         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5870         text_offset += assembly->resources.index;
5871         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5872         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5873         text_offset += assembly->meta_size;
5874         if (assembly->strong_name_size) {
5875                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5876                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5877                 text_offset += assembly->strong_name_size;
5878         }
5879
5880         /* write the section tables and section content */
5881         section = (MonoSectionTable*)(pefile->data + section_start);
5882         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5883                 static const char section_names [][7] = {
5884                         ".text", ".rsrc", ".reloc"
5885                 };
5886                 if (!assembly->sections [i].size)
5887                         continue;
5888                 strcpy (section->st_name, section_names [i]);
5889                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5890                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5891                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5892                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5893                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5894                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5895                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5896                 section ++;
5897         }
5898         
5899         checked_write_file (file, pefile->data, pefile->index);
5900         
5901         mono_dynamic_stream_reset (pefile);
5902         
5903         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5904                 if (!assembly->sections [i].size)
5905                         continue;
5906                 
5907                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5908                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5909                 
5910                 switch (i) {
5911                 case MONO_SECTION_TEXT:
5912                         /* patch entry point */
5913                         p = (guchar*)(assembly->code.data + 2);
5914                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5915                         *p++ = (value) & 0xff;
5916                         *p++ = (value >> 8) & 0xff;
5917                         *p++ = (value >> 16) & 0xff;
5918                         *p++ = (value >> 24) & 0xff;
5919                 
5920                         checked_write_file (file, assembly->code.data, assembly->code.index);
5921                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5922                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5923                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5924                                 
5925
5926                         g_free (assembly->image.raw_metadata);
5927                         break;
5928                 case MONO_SECTION_RELOC: {
5929                         struct {
5930                                 guint32 page_rva;
5931                                 guint32 block_size;
5932                                 guint16 type_and_offset;
5933                                 guint16 term;
5934                         } reloc;
5935                         
5936                         g_assert (sizeof (reloc) == 12);
5937                         
5938                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5939                         reloc.block_size = GUINT32_FROM_LE (12);
5940                         
5941                         /* 
5942                          * the entrypoint is always at the start of the text section 
5943                          * 3 is IMAGE_REL_BASED_HIGHLOW
5944                          * 2 is patch_size_rva - text_rva
5945                          */
5946                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5947                         reloc.term = 0;
5948                         
5949                         checked_write_file (file, &reloc, sizeof (reloc));
5950                         
5951                         break;
5952                 }
5953                 case MONO_SECTION_RSRC:
5954                         if (assembly->win32_res) {
5955
5956                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5957                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5958                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5959                         }
5960                         break;
5961                 default:
5962                         g_assert_not_reached ();
5963                 }
5964         }
5965         
5966         /* check that the file is properly padded */
5967         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5968                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5969         if (! SetEndOfFile (file))
5970                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5971         
5972         mono_dynamic_stream_reset (&assembly->code);
5973         mono_dynamic_stream_reset (&assembly->us);
5974         mono_dynamic_stream_reset (&assembly->blob);
5975         mono_dynamic_stream_reset (&assembly->guid);
5976         mono_dynamic_stream_reset (&assembly->sheap);
5977
5978         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5979         g_hash_table_destroy (assembly->blob_cache);
5980         assembly->blob_cache = NULL;
5981 }
5982
5983 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5984
5985 void
5986 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5987 {
5988         g_assert_not_reached ();
5989 }
5990
5991 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5992
5993 #ifndef DISABLE_REFLECTION_EMIT
5994
5995 MonoReflectionModule *
5996 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5997 {
5998         char *name;
5999         MonoImage *image;
6000         MonoImageOpenStatus status;
6001         MonoDynamicAssembly *assembly;
6002         guint32 module_count;
6003         MonoImage **new_modules;
6004         gboolean *new_modules_loaded;
6005         
6006         name = mono_string_to_utf8 (fileName);
6007
6008         image = mono_image_open (name, &status);
6009         if (!image) {
6010                 MonoException *exc;
6011                 if (status == MONO_IMAGE_ERROR_ERRNO)
6012                         exc = mono_get_exception_file_not_found (fileName);
6013                 else
6014                         exc = mono_get_exception_bad_image_format (name);
6015                 g_free (name);
6016                 mono_raise_exception (exc);
6017         }
6018
6019         g_free (name);
6020
6021         assembly = ab->dynamic_assembly;
6022         image->assembly = (MonoAssembly*)assembly;
6023
6024         module_count = image->assembly->image->module_count;
6025         new_modules = g_new0 (MonoImage *, module_count + 1);
6026         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6027
6028         if (image->assembly->image->modules)
6029                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6030         if (image->assembly->image->modules_loaded)
6031                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6032         new_modules [module_count] = image;
6033         new_modules_loaded [module_count] = TRUE;
6034         mono_image_addref (image);
6035
6036         g_free (image->assembly->image->modules);
6037         image->assembly->image->modules = new_modules;
6038         image->assembly->image->modules_loaded = new_modules_loaded;
6039         image->assembly->image->module_count ++;
6040
6041         mono_assembly_load_references (image, &status);
6042         if (status) {
6043                 mono_image_close (image);
6044                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6045         }
6046
6047         return mono_module_get_object (mono_domain_get (), image);
6048 }
6049
6050 #endif /* DISABLE_REFLECTION_EMIT */
6051
6052 /*
6053  * We need to return always the same object for MethodInfo, FieldInfo etc..
6054  * but we need to consider the reflected type.
6055  * type uses a different hash, since it uses custom hash/equal functions.
6056  */
6057
6058 typedef struct {
6059         gpointer item;
6060         MonoClass *refclass;
6061 } ReflectedEntry;
6062
6063 static gboolean
6064 reflected_equal (gconstpointer a, gconstpointer b) {
6065         const ReflectedEntry *ea = a;
6066         const ReflectedEntry *eb = b;
6067
6068         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6069 }
6070
6071 static guint
6072 reflected_hash (gconstpointer a) {
6073         const ReflectedEntry *ea = a;
6074         return mono_aligned_addr_hash (ea->item);
6075 }
6076
6077 #define CHECK_OBJECT(t,p,k)     \
6078         do {    \
6079                 t _obj; \
6080                 ReflectedEntry e;       \
6081                 e.item = (p);   \
6082                 e.refclass = (k);       \
6083                 mono_domain_lock (domain);      \
6084                 if (!domain->refobject_hash)    \
6085                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6086                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6087                         mono_domain_unlock (domain);    \
6088                         return _obj;    \
6089                 }       \
6090         mono_domain_unlock (domain); \
6091         } while (0)
6092
6093 #ifdef HAVE_BOEHM_GC
6094 /* ReflectedEntry doesn't need to be GC tracked */
6095 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6096 #define FREE_REFENTRY(entry) g_free ((entry))
6097 #define REFENTRY_REQUIRES_CLEANUP
6098 #else
6099 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6100 /* FIXME: */
6101 #define FREE_REFENTRY(entry)
6102 #endif
6103
6104 #define CACHE_OBJECT(t,p,o,k)   \
6105         do {    \
6106                 t _obj; \
6107         ReflectedEntry pe; \
6108         pe.item = (p); \
6109         pe.refclass = (k); \
6110         mono_domain_lock (domain); \
6111                 if (!domain->refobject_hash)    \
6112                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6113         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6114         if (!_obj) { \
6115                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6116                     e->item = (p);      \
6117                     e->refclass = (k);  \
6118                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6119             _obj = o; \
6120         } \
6121                 mono_domain_unlock (domain);    \
6122         return _obj; \
6123         } while (0)
6124
6125 static void
6126 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6127 {
6128         mono_domain_lock (domain);
6129         if (domain->refobject_hash) {
6130         ReflectedEntry pe;
6131                 gpointer orig_pe, orig_value;
6132
6133                 pe.item = o;
6134                 pe.refclass = klass;
6135                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6136                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6137                         FREE_REFENTRY (orig_pe);
6138                 }
6139         }
6140         mono_domain_unlock (domain);
6141 }
6142
6143 #ifdef REFENTRY_REQUIRES_CLEANUP
6144 static void
6145 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6146 {
6147         FREE_REFENTRY (key);
6148 }
6149 #endif
6150
6151 void
6152 mono_reflection_cleanup_domain (MonoDomain *domain)
6153 {
6154         if (domain->refobject_hash) {
6155 /*let's avoid scanning the whole hashtable if not needed*/
6156 #ifdef REFENTRY_REQUIRES_CLEANUP
6157                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6158 #endif
6159                 mono_g_hash_table_destroy (domain->refobject_hash);
6160                 domain->refobject_hash = NULL;
6161         }
6162 }
6163
6164 #ifndef DISABLE_REFLECTION_EMIT
6165 static gpointer
6166 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6167 {
6168         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6169 }
6170
6171 static gpointer
6172 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6173 {
6174         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6175 }
6176
6177 void
6178 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6179 {
6180         MonoDynamicImage *image = moduleb->dynamic_image;
6181         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6182         if (!image) {
6183                 MonoError error;
6184                 int module_count;
6185                 MonoImage **new_modules;
6186                 MonoImage *ass;
6187                 char *name, *fqname;
6188                 /*
6189                  * FIXME: we already created an image in mono_image_basic_init (), but
6190                  * we don't know which module it belongs to, since that is only 
6191                  * determined at assembly save time.
6192                  */
6193                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6194                 name = mono_string_to_utf8 (ab->name);
6195                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6196                 if (!mono_error_ok (&error)) {
6197                         g_free (name);
6198                         mono_error_raise_exception (&error);
6199                 }
6200                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6201
6202                 moduleb->module.image = &image->image;
6203                 moduleb->dynamic_image = image;
6204                 register_module (mono_object_domain (moduleb), moduleb, image);
6205
6206                 /* register the module with the assembly */
6207                 ass = ab->dynamic_assembly->assembly.image;
6208                 module_count = ass->module_count;
6209                 new_modules = g_new0 (MonoImage *, module_count + 1);
6210
6211                 if (ass->modules)
6212                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6213                 new_modules [module_count] = &image->image;
6214                 mono_image_addref (&image->image);
6215
6216                 g_free (ass->modules);
6217                 ass->modules = new_modules;
6218                 ass->module_count ++;
6219         }
6220 }
6221
6222 void
6223 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6224 {
6225         MonoDynamicImage *image = moduleb->dynamic_image;
6226
6227         g_assert (type->type);
6228         image->wrappers_type = mono_class_from_mono_type (type->type);
6229 }
6230
6231 #endif
6232
6233 /*
6234  * mono_assembly_get_object:
6235  * @domain: an app domain
6236  * @assembly: an assembly
6237  *
6238  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6239  */
6240 MonoReflectionAssembly*
6241 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6242 {
6243         static MonoClass *assembly_type;
6244         MonoReflectionAssembly *res;
6245         
6246         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6247         if (!assembly_type) {
6248                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6249                 if (class == NULL)
6250                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6251                 g_assert (class);
6252                 assembly_type = class;
6253         }
6254         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6255         res->assembly = assembly;
6256
6257         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6258 }
6259
6260
6261
6262 MonoReflectionModule*   
6263 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6264 {
6265         static MonoClass *module_type;
6266         MonoReflectionModule *res;
6267         char* basename;
6268         
6269         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6270         if (!module_type) {
6271                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6272                 if (class == NULL)
6273                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6274                 g_assert (class);
6275                 module_type = class;
6276         }
6277         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6278
6279         res->image = image;
6280         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6281
6282         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6283         basename = g_path_get_basename (image->name);
6284         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6285         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6286         
6287         g_free (basename);
6288
6289         if (image->assembly->image == image) {
6290                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6291         } else {
6292                 int i;
6293                 res->token = 0;
6294                 if (image->assembly->image->modules) {
6295                         for (i = 0; i < image->assembly->image->module_count; i++) {
6296                                 if (image->assembly->image->modules [i] == image)
6297                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6298                         }
6299                         g_assert (res->token);
6300                 }
6301         }
6302
6303         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6304 }
6305
6306 MonoReflectionModule*   
6307 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6308 {
6309         static MonoClass *module_type;
6310         MonoReflectionModule *res;
6311         MonoTableInfo *table;
6312         guint32 cols [MONO_FILE_SIZE];
6313         const char *name;
6314         guint32 i, name_idx;
6315         const char *val;
6316         
6317         if (!module_type) {
6318                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6319                 if (class == NULL)
6320                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6321                 g_assert (class);
6322                 module_type = class;
6323         }
6324         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6325
6326         table = &image->tables [MONO_TABLE_FILE];
6327         g_assert (table_index < table->rows);
6328         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6329
6330         res->image = NULL;
6331         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6332         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6333
6334         /* Check whenever the row has a corresponding row in the moduleref table */
6335         table = &image->tables [MONO_TABLE_MODULEREF];
6336         for (i = 0; i < table->rows; ++i) {
6337                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6338                 val = mono_metadata_string_heap (image, name_idx);
6339                 if (strcmp (val, name) == 0)
6340                         res->image = image->modules [i];
6341         }
6342
6343         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6344         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6345         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6346         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6347         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6348
6349         return res;
6350 }
6351
6352 static gboolean
6353 verify_safe_for_managed_space (MonoType *type)
6354 {
6355         switch (type->type) {
6356 #ifdef DEBUG_HARDER
6357         case MONO_TYPE_ARRAY:
6358                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6359         case MONO_TYPE_PTR:
6360                 return verify_safe_for_managed_space (type->data.type);
6361         case MONO_TYPE_SZARRAY:
6362                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6363         case MONO_TYPE_GENERICINST: {
6364                 MonoGenericInst *inst = type->data.generic_class->inst;
6365                 int i;
6366                 if (!inst->is_open)
6367                         break;
6368                 for (i = 0; i < inst->type_argc; ++i)
6369                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6370                                 return FALSE;
6371                 break;
6372         }
6373 #endif
6374         case MONO_TYPE_VAR:
6375         case MONO_TYPE_MVAR:
6376                 return TRUE;
6377         }
6378         return TRUE;
6379 }
6380
6381 static MonoType*
6382 mono_type_normalize (MonoType *type)
6383 {
6384         int i;
6385         MonoGenericClass *gclass;
6386         MonoGenericInst *ginst;
6387         MonoClass *gtd;
6388         MonoGenericContainer *gcontainer;
6389         MonoType **argv = NULL;
6390         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6391
6392         if (type->type != MONO_TYPE_GENERICINST)
6393                 return type;
6394
6395         gclass = type->data.generic_class;
6396         ginst = gclass->context.class_inst;
6397         if (!ginst->is_open)
6398                 return type;
6399
6400         gtd = gclass->container_class;
6401         gcontainer = gtd->generic_container;
6402         argv = g_newa (MonoType*, ginst->type_argc);
6403
6404         for (i = 0; i < ginst->type_argc; ++i) {
6405                 MonoType *t = ginst->type_argv [i], *norm;
6406                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6407                         is_denorm_gtd = FALSE;
6408                 norm = mono_type_normalize (t);
6409                 argv [i] = norm;
6410                 if (norm != t)
6411                         requires_rebind = TRUE;
6412         }
6413
6414         if (is_denorm_gtd)
6415                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6416
6417         if (requires_rebind) {
6418                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6419                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6420         }
6421
6422         return type;
6423 }
6424 /*
6425  * mono_type_get_object:
6426  * @domain: an app domain
6427  * @type: a type
6428  *
6429  * Return an System.MonoType object representing the type @type.
6430  */
6431 MonoReflectionType*
6432 mono_type_get_object (MonoDomain *domain, MonoType *type)
6433 {
6434         MonoType *norm_type;
6435         MonoReflectionType *res;
6436         MonoClass *klass = mono_class_from_mono_type (type);
6437
6438         /*we must avoid using @type as it might have come
6439          * from a mono_metadata_type_dup and the caller
6440          * expects that is can be freed.
6441          * Using the right type from 
6442          */
6443         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6444
6445         /* void is very common */
6446         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6447                 return (MonoReflectionType*)domain->typeof_void;
6448
6449         /*
6450          * If the vtable of the given class was already created, we can use
6451          * the MonoType from there and avoid all locking and hash table lookups.
6452          * 
6453          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6454          * that the resulting object is different.   
6455          */
6456         if (type == &klass->byval_arg && !klass->image->dynamic) {
6457                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6458                 if (vtable && vtable->type)
6459                         return vtable->type;
6460         }
6461
6462         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6463         mono_domain_lock (domain);
6464         if (!domain->type_hash)
6465                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6466                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6467         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6468                 mono_domain_unlock (domain);
6469                 mono_loader_unlock ();
6470                 return res;
6471         }
6472
6473         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6474          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6475          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6476          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6477          * artifact of how generics are encoded and should be transparent to managed code so we
6478          * need to weed out this diference when retrieving managed System.Type objects.
6479          */
6480         norm_type = mono_type_normalize (type);
6481         if (norm_type != type) {
6482                 res = mono_type_get_object (domain, norm_type);
6483                 mono_g_hash_table_insert (domain->type_hash, type, res);
6484                 mono_domain_unlock (domain);
6485                 mono_loader_unlock ();
6486                 return res;
6487         }
6488
6489         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6490         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6491                 g_assert (0);
6492
6493         if (!verify_safe_for_managed_space (type)) {
6494                 mono_domain_unlock (domain);
6495                 mono_loader_unlock ();
6496                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6497         }
6498
6499         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6500                 gboolean is_type_done = TRUE;
6501                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6502                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6503                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6504                 */
6505                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6506                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6507
6508                         if (gparam->owner && gparam->owner->is_method) {
6509                                 MonoMethod *method = gparam->owner->owner.method;
6510                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6511                                         is_type_done = FALSE;
6512                         } else if (gparam->owner && !gparam->owner->is_method) {
6513                                 MonoClass *klass = gparam->owner->owner.klass;
6514                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6515                                         is_type_done = FALSE;
6516                         }
6517                 } 
6518
6519                 /* g_assert_not_reached (); */
6520                 /* should this be considered an error condition? */
6521                 if (is_type_done && !type->byref) {
6522                         mono_domain_unlock (domain);
6523                         mono_loader_unlock ();
6524                         return mono_class_get_ref_info (klass);
6525                 }
6526         }
6527         /* This is stored in vtables/JITted code so it has to be pinned */
6528         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6529         res->type = type;
6530         mono_g_hash_table_insert (domain->type_hash, type, res);
6531
6532         if (type->type == MONO_TYPE_VOID)
6533                 domain->typeof_void = (MonoObject*)res;
6534
6535         mono_domain_unlock (domain);
6536         mono_loader_unlock ();
6537         return res;
6538 }
6539
6540 /*
6541  * mono_method_get_object:
6542  * @domain: an app domain
6543  * @method: a method
6544  * @refclass: the reflected type (can be NULL)
6545  *
6546  * Return an System.Reflection.MonoMethod object representing the method @method.
6547  */
6548 MonoReflectionMethod*
6549 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6550 {
6551         /*
6552          * We use the same C representation for methods and constructors, but the type 
6553          * name in C# is different.
6554          */
6555         static MonoClass *System_Reflection_MonoMethod = NULL;
6556         static MonoClass *System_Reflection_MonoCMethod = NULL;
6557         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6558         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6559         MonoClass *klass;
6560         MonoReflectionMethod *ret;
6561
6562         if (method->is_inflated) {
6563                 MonoReflectionGenericMethod *gret;
6564
6565                 refclass = method->klass;
6566                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6567                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6568                         if (!System_Reflection_MonoGenericCMethod)
6569                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6570                         klass = System_Reflection_MonoGenericCMethod;
6571                 } else {
6572                         if (!System_Reflection_MonoGenericMethod)
6573                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6574                         klass = System_Reflection_MonoGenericMethod;
6575                 }
6576                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6577                 gret->method.method = method;
6578                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6579                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6580                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6581         }
6582
6583         if (!refclass)
6584                 refclass = method->klass;
6585
6586         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6587         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6588                 if (!System_Reflection_MonoCMethod)
6589                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6590                 klass = System_Reflection_MonoCMethod;
6591         }
6592         else {
6593                 if (!System_Reflection_MonoMethod)
6594                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6595                 klass = System_Reflection_MonoMethod;
6596         }
6597         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6598         ret->method = method;
6599         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6600         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6601 }
6602
6603 /*
6604  * mono_method_clear_object:
6605  *
6606  *   Clear the cached reflection objects for the dynamic method METHOD.
6607  */
6608 void
6609 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6610 {
6611         MonoClass *klass;
6612         g_assert (method->dynamic);
6613
6614         klass = method->klass;
6615         while (klass) {
6616                 clear_cached_object (domain, method, klass);
6617                 klass = klass->parent;
6618         }
6619         /* Added by mono_param_get_objects () */
6620         clear_cached_object (domain, &(method->signature), NULL);
6621         klass = method->klass;
6622         while (klass) {
6623                 clear_cached_object (domain, &(method->signature), klass);
6624                 klass = klass->parent;
6625         }
6626 }
6627
6628 /*
6629  * mono_field_get_object:
6630  * @domain: an app domain
6631  * @klass: a type
6632  * @field: a field
6633  *
6634  * Return an System.Reflection.MonoField object representing the field @field
6635  * in class @klass.
6636  */
6637 MonoReflectionField*
6638 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6639 {
6640         MonoReflectionField *res;
6641         static MonoClass *monofield_klass;
6642
6643         CHECK_OBJECT (MonoReflectionField *, field, klass);
6644         if (!monofield_klass)
6645                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6646         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6647         res->klass = klass;
6648         res->field = field;
6649         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6650
6651         if (is_field_on_inst (field)) {
6652                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6653                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6654         } else {
6655                 if (field->type)
6656                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6657                 res->attrs = mono_field_get_flags (field);
6658         }
6659         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6660 }
6661
6662 /*
6663  * mono_property_get_object:
6664  * @domain: an app domain
6665  * @klass: a type
6666  * @property: a property
6667  *
6668  * Return an System.Reflection.MonoProperty object representing the property @property
6669  * in class @klass.
6670  */
6671 MonoReflectionProperty*
6672 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6673 {
6674         MonoReflectionProperty *res;
6675         static MonoClass *monoproperty_klass;
6676
6677         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6678         if (!monoproperty_klass)
6679                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6680         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6681         res->klass = klass;
6682         res->property = property;
6683         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6684 }
6685
6686 /*
6687  * mono_event_get_object:
6688  * @domain: an app domain
6689  * @klass: a type
6690  * @event: a event
6691  *
6692  * Return an System.Reflection.MonoEvent object representing the event @event
6693  * in class @klass.
6694  */
6695 MonoReflectionEvent*
6696 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6697 {
6698         MonoReflectionEvent *res;
6699         MonoReflectionMonoEvent *mono_event;
6700         static MonoClass *monoevent_klass;
6701
6702         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6703         if (!monoevent_klass)
6704                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6705         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6706         mono_event->klass = klass;
6707         mono_event->event = event;
6708         res = (MonoReflectionEvent*)mono_event;
6709         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6710 }
6711
6712 /**
6713  * mono_get_reflection_missing_object:
6714  * @domain: Domain where the object lives
6715  *
6716  * Returns the System.Reflection.Missing.Value singleton object
6717  * (of type System.Reflection.Missing).
6718  *
6719  * Used as the value for ParameterInfo.DefaultValue when Optional
6720  * is present
6721  */
6722 static MonoObject *
6723 mono_get_reflection_missing_object (MonoDomain *domain)
6724 {
6725         MonoObject *obj;
6726         static MonoClassField *missing_value_field = NULL;
6727         
6728         if (!missing_value_field) {
6729                 MonoClass *missing_klass;
6730                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6731                 mono_class_init (missing_klass);
6732                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6733                 g_assert (missing_value_field);
6734         }
6735         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6736         g_assert (obj);
6737         return obj;
6738 }
6739
6740 static MonoObject*
6741 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6742 {
6743         if (!*dbnull)
6744                 *dbnull = mono_get_dbnull_object (domain);
6745         return *dbnull;
6746 }
6747
6748 static MonoObject*
6749 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6750 {
6751         if (!*reflection_missing)
6752                 *reflection_missing = mono_get_reflection_missing_object (domain);
6753         return *reflection_missing;
6754 }
6755
6756 /*
6757  * mono_param_get_objects:
6758  * @domain: an app domain
6759  * @method: a method
6760  *
6761  * Return an System.Reflection.ParameterInfo array object representing the parameters
6762  * in the method @method.
6763  */
6764 MonoArray*
6765 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6766 {
6767         static MonoClass *System_Reflection_ParameterInfo;
6768         static MonoClass *System_Reflection_ParameterInfo_array;
6769         MonoError error;
6770         MonoArray *res = NULL;
6771         MonoReflectionMethod *member = NULL;
6772         MonoReflectionParameter *param = NULL;
6773         char **names, **blobs = NULL;
6774         guint32 *types = NULL;
6775         MonoType *type = NULL;
6776         MonoObject *dbnull = NULL;
6777         MonoObject *missing = NULL;
6778         MonoMarshalSpec **mspecs;
6779         MonoMethodSignature *sig;
6780         MonoVTable *pinfo_vtable;
6781         int i;
6782
6783         if (!System_Reflection_ParameterInfo_array) {
6784                 MonoClass *klass;
6785
6786                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6787                 mono_memory_barrier ();
6788                 System_Reflection_ParameterInfo = klass; 
6789         
6790                 klass = mono_array_class_get (klass, 1);
6791                 mono_memory_barrier ();
6792                 System_Reflection_ParameterInfo_array = klass;
6793         }
6794
6795         sig = mono_method_signature_checked (method, &error);
6796         if (!mono_error_ok (&error))
6797                 mono_error_raise_exception (&error);
6798
6799         if (!sig->param_count)
6800                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6801
6802         /* Note: the cache is based on the address of the signature into the method
6803          * since we already cache MethodInfos with the method as keys.
6804          */
6805         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6806
6807         member = mono_method_get_object (domain, method, refclass);
6808         names = g_new (char *, sig->param_count);
6809         mono_method_get_param_names (method, (const char **) names);
6810
6811         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6812         mono_method_get_marshal_info (method, mspecs);
6813
6814         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6815         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6816         for (i = 0; i < sig->param_count; ++i) {
6817                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6818                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6819                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6820                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6821                 param->PositionImpl = i;
6822                 param->AttrsImpl = sig->params [i]->attrs;
6823
6824                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6825                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6826                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6827                         else
6828                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6829                 } else {
6830
6831                         if (!blobs) {
6832                                 blobs = g_new0 (char *, sig->param_count);
6833                                 types = g_new0 (guint32, sig->param_count);
6834                                 get_default_param_value_blobs (method, blobs, types); 
6835                         }
6836
6837                         /* Build MonoType for the type from the Constant Table */
6838                         if (!type)
6839                                 type = g_new0 (MonoType, 1);
6840                         type->type = types [i];
6841                         type->data.klass = NULL;
6842                         if (types [i] == MONO_TYPE_CLASS)
6843                                 type->data.klass = mono_defaults.object_class;
6844                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6845                                 /* For enums, types [i] contains the base type */
6846
6847                                         type->type = MONO_TYPE_VALUETYPE;
6848                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6849                         } else
6850                                 type->data.klass = mono_class_from_mono_type (type);
6851
6852                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6853
6854                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6855                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6856                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6857                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6858                                 else
6859                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6860                         }
6861                         
6862                 }
6863
6864                 if (mspecs [i + 1])
6865                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6866                 
6867                 mono_array_setref (res, i, param);
6868         }
6869         g_free (names);
6870         g_free (blobs);
6871         g_free (types);
6872         g_free (type);
6873
6874         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6875                 if (mspecs [i])
6876                         mono_metadata_free_marshal_spec (mspecs [i]);
6877         g_free (mspecs);
6878         
6879         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6880 }
6881
6882 MonoArray*
6883 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6884 {
6885         return mono_param_get_objects_internal (domain, method, NULL);
6886 }
6887
6888 /*
6889  * mono_method_body_get_object:
6890  * @domain: an app domain
6891  * @method: a method
6892  *
6893  * Return an System.Reflection.MethodBody object representing the method @method.
6894  */
6895 MonoReflectionMethodBody*
6896 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6897 {
6898         static MonoClass *System_Reflection_MethodBody = NULL;
6899         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6900         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6901         MonoReflectionMethodBody *ret;
6902         MonoMethodHeader *header;
6903         MonoImage *image;
6904         guint32 method_rva, local_var_sig_token;
6905     char *ptr;
6906         unsigned char format, flags;
6907         int i;
6908
6909         /* for compatibility with .net */
6910     if (method->dynamic)
6911         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6912
6913         if (!System_Reflection_MethodBody)
6914                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6915         if (!System_Reflection_LocalVariableInfo)
6916                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6917         if (!System_Reflection_ExceptionHandlingClause)
6918                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6919
6920         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6921
6922         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6923                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6924             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6925             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6926                 return NULL;
6927
6928         image = method->klass->image;
6929         header = mono_method_get_header (method);
6930
6931         if (!image->dynamic) {
6932                 /* Obtain local vars signature token */
6933                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6934                 ptr = mono_image_rva_map (image, method_rva);
6935                 flags = *(const unsigned char *) ptr;
6936                 format = flags & METHOD_HEADER_FORMAT_MASK;
6937                 switch (format){
6938                 case METHOD_HEADER_TINY_FORMAT:
6939                         local_var_sig_token = 0;
6940                         break;
6941                 case METHOD_HEADER_FAT_FORMAT:
6942                         ptr += 2;
6943                         ptr += 2;
6944                         ptr += 4;
6945                         local_var_sig_token = read32 (ptr);
6946                         break;
6947                 default:
6948                         g_assert_not_reached ();
6949                 }
6950         } else
6951                 local_var_sig_token = 0; //FIXME
6952
6953         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6954
6955         ret->init_locals = header->init_locals;
6956         ret->max_stack = header->max_stack;
6957         ret->local_var_sig_token = local_var_sig_token;
6958         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6959         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6960
6961         /* Locals */
6962         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6963         for (i = 0; i < header->num_locals; ++i) {
6964                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6965                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6966                 info->is_pinned = header->locals [i]->pinned;
6967                 info->local_index = i;
6968                 mono_array_setref (ret->locals, i, info);
6969         }
6970
6971         /* Exceptions */
6972         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6973         for (i = 0; i < header->num_clauses; ++i) {
6974                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6975                 MonoExceptionClause *clause = &header->clauses [i];
6976
6977                 info->flags = clause->flags;
6978                 info->try_offset = clause->try_offset;
6979                 info->try_length = clause->try_len;
6980                 info->handler_offset = clause->handler_offset;
6981                 info->handler_length = clause->handler_len;
6982                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6983                         info->filter_offset = clause->data.filter_offset;
6984                 else if (clause->data.catch_class)
6985                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6986
6987                 mono_array_setref (ret->clauses, i, info);
6988         }
6989
6990         mono_metadata_free_mh (header);
6991         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6992         return ret;
6993 }
6994
6995 /**
6996  * mono_get_dbnull_object:
6997  * @domain: Domain where the object lives
6998  *
6999  * Returns the System.DBNull.Value singleton object
7000  *
7001  * Used as the value for ParameterInfo.DefaultValue 
7002  */
7003 MonoObject *
7004 mono_get_dbnull_object (MonoDomain *domain)
7005 {
7006         MonoObject *obj;
7007         static MonoClassField *dbnull_value_field = NULL;
7008         
7009         if (!dbnull_value_field) {
7010                 MonoClass *dbnull_klass;
7011                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7012                 mono_class_init (dbnull_klass);
7013                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7014                 g_assert (dbnull_value_field);
7015         }
7016         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7017         g_assert (obj);
7018         return obj;
7019 }
7020
7021 static void
7022 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7023 {
7024         guint32 param_index, i, lastp, crow = 0;
7025         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7026         gint32 idx;
7027
7028         MonoClass *klass = method->klass;
7029         MonoImage *image = klass->image;
7030         MonoMethodSignature *methodsig = mono_method_signature (method);
7031
7032         MonoTableInfo *constt;
7033         MonoTableInfo *methodt;
7034         MonoTableInfo *paramt;
7035
7036         if (!methodsig->param_count)
7037                 return;
7038
7039         mono_class_init (klass);
7040
7041         if (klass->image->dynamic) {
7042                 MonoReflectionMethodAux *aux;
7043                 if (method->is_inflated)
7044                         method = ((MonoMethodInflated*)method)->declaring;
7045                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7046                 if (aux && aux->param_defaults) {
7047                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7048                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7049                 }
7050                 return;
7051         }
7052
7053         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7054         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7055         constt = &image->tables [MONO_TABLE_CONSTANT];
7056
7057         idx = mono_method_get_index (method) - 1;
7058         g_assert (idx != -1);
7059
7060         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7061         if (idx + 1 < methodt->rows)
7062                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7063         else
7064                 lastp = paramt->rows + 1;
7065
7066         for (i = param_index; i < lastp; ++i) {
7067                 guint32 paramseq;
7068
7069                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7070                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7071
7072                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7073                         continue;
7074
7075                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7076                 if (!crow) {
7077                         continue;
7078                 }
7079         
7080                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7081                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7082                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7083         }
7084
7085         return;
7086 }
7087
7088 MonoObject *
7089 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7090 {
7091         void *retval;
7092         MonoClass *klass;
7093         MonoObject *object;
7094         MonoType *basetype = type;
7095
7096         if (!blob)
7097                 return NULL;
7098         
7099         klass = mono_class_from_mono_type (type);
7100         if (klass->valuetype) {
7101                 object = mono_object_new (domain, klass);
7102                 retval = ((gchar *) object + sizeof (MonoObject));
7103                 if (klass->enumtype)
7104                         basetype = mono_class_enum_basetype (klass);
7105         } else {
7106                 retval = &object;
7107         }
7108                         
7109         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7110                 return object;
7111         else
7112                 return NULL;
7113 }
7114
7115 static int
7116 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7117         int found_sep;
7118         char *s;
7119         gboolean quoted = FALSE;
7120
7121         memset (assembly, 0, sizeof (MonoAssemblyName));
7122         assembly->culture = "";
7123         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7124
7125         if (*p == '"') {
7126                 quoted = TRUE;
7127                 p++;
7128         }
7129         assembly->name = p;
7130         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7131                 p++;
7132         if (quoted) {
7133                 if (*p != '"')
7134                         return 1;
7135                 *p = 0;
7136                 p++;
7137         }
7138         if (*p != ',')
7139                 return 1;
7140         *p = 0;
7141         /* Remove trailing whitespace */
7142         s = p - 1;
7143         while (*s && g_ascii_isspace (*s))
7144                 *s-- = 0;
7145         p ++;
7146         while (g_ascii_isspace (*p))
7147                 p++;
7148         while (*p) {
7149                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7150                         p += 8;
7151                         assembly->major = strtoul (p, &s, 10);
7152                         if (s == p || *s != '.')
7153                                 return 1;
7154                         p = ++s;
7155                         assembly->minor = strtoul (p, &s, 10);
7156                         if (s == p || *s != '.')
7157                                 return 1;
7158                         p = ++s;
7159                         assembly->build = strtoul (p, &s, 10);
7160                         if (s == p || *s != '.')
7161                                 return 1;
7162                         p = ++s;
7163                         assembly->revision = strtoul (p, &s, 10);
7164                         if (s == p)
7165                                 return 1;
7166                         p = s;
7167                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7168                         p += 8;
7169                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7170                                 assembly->culture = "";
7171                                 p += 7;
7172                         } else {
7173                                 assembly->culture = p;
7174                                 while (*p && *p != ',') {
7175                                         p++;
7176                                 }
7177                         }
7178                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7179                         p += 15;
7180                         if (strncmp (p, "null", 4) == 0) {
7181                                 p += 4;
7182                         } else {
7183                                 int len;
7184                                 gchar *start = p;
7185                                 while (*p && *p != ',') {
7186                                         p++;
7187                                 }
7188                                 len = (p - start + 1);
7189                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7190                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7191                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7192                         }
7193                 } else {
7194                         while (*p && *p != ',')
7195                                 p++;
7196                 }
7197                 found_sep = 0;
7198                 while (g_ascii_isspace (*p) || *p == ',') {
7199                         *p++ = 0;
7200                         found_sep = 1;
7201                         continue;
7202                 }
7203                 /* failed */
7204                 if (!found_sep)
7205                         return 1;
7206         }
7207
7208         return 0;
7209 }
7210
7211 /*
7212  * mono_reflection_parse_type:
7213  * @name: type name
7214  *
7215  * Parse a type name as accepted by the GetType () method and output the info
7216  * extracted in the info structure.
7217  * the name param will be mangled, so, make a copy before passing it to this function.
7218  * The fields in info will be valid until the memory pointed to by name is valid.
7219  *
7220  * See also mono_type_get_name () below.
7221  *
7222  * Returns: 0 on parse error.
7223  */
7224 static int
7225 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7226                              MonoTypeNameParse *info)
7227 {
7228         char *start, *p, *w, *temp, *last_point, *startn;
7229         int in_modifiers = 0;
7230         int isbyref = 0, rank, arity = 0, i;
7231
7232         start = p = w = name;
7233
7234         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7235         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7236         info->name = info->name_space = NULL;
7237         info->nested = NULL;
7238         info->modifiers = NULL;
7239         info->type_arguments = NULL;
7240
7241         /* last_point separates the namespace from the name */
7242         last_point = NULL;
7243         /* Skips spaces */
7244         while (*p == ' ') p++, start++, w++, name++;
7245
7246         while (*p) {
7247                 switch (*p) {
7248                 case '+':
7249                         *p = 0; /* NULL terminate the name */
7250                         startn = p + 1;
7251                         info->nested = g_list_append (info->nested, startn);
7252                         /* we have parsed the nesting namespace + name */
7253                         if (info->name)
7254                                 break;
7255                         if (last_point) {
7256                                 info->name_space = start;
7257                                 *last_point = 0;
7258                                 info->name = last_point + 1;
7259                         } else {
7260                                 info->name_space = (char *)"";
7261                                 info->name = start;
7262                         }
7263                         break;
7264                 case '.':
7265                         last_point = p;
7266                         break;
7267                 case '\\':
7268                         ++p;
7269                         break;
7270                 case '&':
7271                 case '*':
7272                 case '[':
7273                 case ',':
7274                 case ']':
7275                         in_modifiers = 1;
7276                         break;
7277                 case '`':
7278                         ++p;
7279                         i = strtol (p, &temp, 10);
7280                         arity += i;
7281                         if (p == temp)
7282                                 return 0;
7283                         p = temp-1;
7284                         break;
7285                 default:
7286                         break;
7287                 }
7288                 if (in_modifiers)
7289                         break;
7290                 // *w++ = *p++;
7291                 p++;
7292         }
7293         
7294         if (!info->name) {
7295                 if (last_point) {
7296                         info->name_space = start;
7297                         *last_point = 0;
7298                         info->name = last_point + 1;
7299                 } else {
7300                         info->name_space = (char *)"";
7301                         info->name = start;
7302                 }
7303         }
7304         while (*p) {
7305                 switch (*p) {
7306                 case '&':
7307                         if (isbyref) /* only one level allowed by the spec */
7308                                 return 0;
7309                         isbyref = 1;
7310                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7311                         *p++ = 0;
7312                         break;
7313                 case '*':
7314                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7315                         *p++ = 0;
7316                         break;
7317                 case '[':
7318                         if (arity != 0) {
7319                                 *p++ = 0;
7320                                 info->type_arguments = g_ptr_array_new ();
7321                                 for (i = 0; i < arity; i++) {
7322                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7323                                         gboolean fqname = FALSE;
7324
7325                                         g_ptr_array_add (info->type_arguments, subinfo);
7326
7327                                         if (*p == '[') {
7328                                                 p++;
7329                                                 fqname = TRUE;
7330                                         }
7331
7332                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7333                                                 return 0;
7334
7335                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7336                                         if (fqname && (*p != ']')) {
7337                                                 char *aname;
7338
7339                                                 if (*p != ',')
7340                                                         return 0;
7341                                                 *p++ = 0;
7342
7343                                                 aname = p;
7344                                                 while (*p && (*p != ']'))
7345                                                         p++;
7346
7347                                                 if (*p != ']')
7348                                                         return 0;
7349
7350                                                 *p++ = 0;
7351                                                 while (*aname) {
7352                                                         if (g_ascii_isspace (*aname)) {
7353                                                                 ++aname;
7354                                                                 continue;
7355                                                         }
7356                                                         break;
7357                                                 }
7358                                                 if (!*aname ||
7359                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7360                                                         return 0;
7361                                         } else if (fqname && (*p == ']')) {
7362                                                 *p++ = 0;
7363                                         }
7364
7365                                         if (i + 1 < arity) {
7366                                                 if (*p != ',')
7367                                                         return 0;
7368                                         } else {
7369                                                 if (*p != ']')
7370                                                         return 0;
7371                                         }
7372                                         *p++ = 0;
7373                                 }
7374
7375                                 arity = 0;
7376                                 break;
7377                         }
7378                         rank = 1;
7379                         *p++ = 0;
7380                         while (*p) {
7381                                 if (*p == ']')
7382                                         break;
7383                                 if (*p == ',')
7384                                         rank++;
7385                                 else if (*p == '*') /* '*' means unknown lower bound */
7386                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7387                                 else
7388                                         return 0;
7389                                 ++p;
7390                         }
7391                         if (*p++ != ']')
7392                                 return 0;
7393                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7394                         break;
7395                 case ']':
7396                         if (is_recursed)
7397                                 goto end;
7398                         return 0;
7399                 case ',':
7400                         if (is_recursed)
7401                                 goto end;
7402                         *p++ = 0;
7403                         while (*p) {
7404                                 if (g_ascii_isspace (*p)) {
7405                                         ++p;
7406                                         continue;
7407                                 }
7408                                 break;
7409                         }
7410                         if (!*p)
7411                                 return 0; /* missing assembly name */
7412                         if (!assembly_name_to_aname (&info->assembly, p))
7413                                 return 0;
7414                         break;
7415                 default:
7416                         return 0;
7417                 }
7418                 if (info->assembly.name)
7419                         break;
7420         }
7421         // *w = 0; /* terminate class name */
7422  end:
7423         if (!info->name || !*info->name)
7424                 return 0;
7425         if (endptr)
7426                 *endptr = p;
7427         /* add other consistency checks */
7428         return 1;
7429 }
7430
7431 int
7432 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7433 {
7434         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7435 }
7436
7437 static MonoType*
7438 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7439 {
7440         gboolean type_resolve = FALSE;
7441         MonoType *type;
7442         MonoImage *rootimage = image;
7443
7444         if (info->assembly.name) {
7445                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7446                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7447                         /* 
7448                          * This could happen in the AOT compiler case when the search hook is not
7449                          * installed.
7450                          */
7451                         assembly = image->assembly;
7452                 if (!assembly) {
7453                         /* then we must load the assembly ourselve - see #60439 */
7454                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7455                         if (!assembly)
7456                                 return NULL;
7457                 }
7458                 image = assembly->image;
7459         } else if (!image) {
7460                 image = mono_defaults.corlib;
7461         }
7462
7463         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7465                 image = mono_defaults.corlib;
7466                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7467         }
7468
7469         return type;
7470 }
7471
7472 static MonoType*
7473 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7474 {
7475         MonoClass *klass;
7476         GList *mod;
7477         int modval;
7478         gboolean bounded = FALSE;
7479         
7480         if (!image)
7481                 image = mono_defaults.corlib;
7482
7483         if (ignorecase)
7484                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7485         else
7486                 klass = mono_class_from_name (image, info->name_space, info->name);
7487         if (!klass)
7488                 return NULL;
7489         for (mod = info->nested; mod; mod = mod->next) {
7490                 gpointer iter = NULL;
7491                 MonoClass *parent;
7492
7493                 parent = klass;
7494                 mono_class_init (parent);
7495
7496                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7497                         if (ignorecase) {
7498                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7499                                         break;
7500                         } else {
7501                                 if (strcmp (klass->name, mod->data) == 0)
7502                                         break;
7503                         }
7504                 }
7505                 if (!klass)
7506                         break;
7507         }
7508         if (!klass)
7509                 return NULL;
7510
7511         if (info->type_arguments) {
7512                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7513                 MonoReflectionType *the_type;
7514                 MonoType *instance;
7515                 int i;
7516
7517                 for (i = 0; i < info->type_arguments->len; i++) {
7518                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7519
7520                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7521                         if (!type_args [i]) {
7522                                 g_free (type_args);
7523                                 return NULL;
7524                         }
7525                 }
7526
7527                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7528
7529                 instance = mono_reflection_bind_generic_parameters (
7530                         the_type, info->type_arguments->len, type_args);
7531
7532                 g_free (type_args);
7533                 if (!instance)
7534                         return NULL;
7535
7536                 klass = mono_class_from_mono_type (instance);
7537         }
7538
7539         for (mod = info->modifiers; mod; mod = mod->next) {
7540                 modval = GPOINTER_TO_UINT (mod->data);
7541                 if (!modval) { /* byref: must be last modifier */
7542                         return &klass->this_arg;
7543                 } else if (modval == -1) {
7544                         klass = mono_ptr_class_get (&klass->byval_arg);
7545                 } else if (modval == -2) {
7546                         bounded = TRUE;
7547                 } else { /* array rank */
7548                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7549                 }
7550         }
7551
7552         return &klass->byval_arg;
7553 }
7554
7555 /*
7556  * mono_reflection_get_type:
7557  * @image: a metadata context
7558  * @info: type description structure
7559  * @ignorecase: flag for case-insensitive string compares
7560  * @type_resolve: whenever type resolve was already tried
7561  *
7562  * Build a MonoType from the type description in @info.
7563  * 
7564  */
7565
7566 MonoType*
7567 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7568         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7569 }
7570
7571 static MonoType*
7572 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7573 {
7574         MonoReflectionAssemblyBuilder *abuilder;
7575         MonoType *type;
7576         int i;
7577
7578         g_assert (assembly->dynamic);
7579         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7580
7581         /* Enumerate all modules */
7582
7583         type = NULL;
7584         if (abuilder->modules) {
7585                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7586                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7587                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7588                         if (type)
7589                                 break;
7590                 }
7591         }
7592
7593         if (!type && abuilder->loaded_modules) {
7594                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7595                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7596                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7597                         if (type)
7598                                 break;
7599                 }
7600         }
7601
7602         return type;
7603 }
7604         
7605 MonoType*
7606 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7607 {
7608         MonoType *type;
7609         MonoReflectionAssembly *assembly;
7610         GString *fullName;
7611         GList *mod;
7612
7613         if (image && image->dynamic)
7614                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7615         else
7616                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7617         if (type)
7618                 return type;
7619         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7620                 return NULL;
7621
7622         if (type_resolve) {
7623                 if (*type_resolve) 
7624                         return NULL;
7625                 else
7626                         *type_resolve = TRUE;
7627         }
7628         
7629         /* Reconstruct the type name */
7630         fullName = g_string_new ("");
7631         if (info->name_space && (info->name_space [0] != '\0'))
7632                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7633         else
7634                 g_string_printf (fullName, "%s", info->name);
7635         for (mod = info->nested; mod; mod = mod->next)
7636                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7637
7638         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7639         if (assembly) {
7640                 if (assembly->assembly->dynamic)
7641                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7642                 else
7643                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7644                                                                                                           info, ignorecase);
7645         }
7646         g_string_free (fullName, TRUE);
7647         return type;
7648 }
7649
7650 void
7651 mono_reflection_free_type_info (MonoTypeNameParse *info)
7652 {
7653         g_list_free (info->modifiers);
7654         g_list_free (info->nested);
7655
7656         if (info->type_arguments) {
7657                 int i;
7658
7659                 for (i = 0; i < info->type_arguments->len; i++) {
7660                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7661
7662                         mono_reflection_free_type_info (subinfo);
7663                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7664                         g_free (subinfo);
7665                 }
7666
7667                 g_ptr_array_free (info->type_arguments, TRUE);
7668         }
7669 }
7670
7671 /*
7672  * mono_reflection_type_from_name:
7673  * @name: type name.
7674  * @image: a metadata context (can be NULL).
7675  *
7676  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7677  * it defaults to get the type from @image or, if @image is NULL or loading
7678  * from it fails, uses corlib.
7679  * 
7680  */
7681 MonoType*
7682 mono_reflection_type_from_name (char *name, MonoImage *image)
7683 {
7684         MonoType *type = NULL;
7685         MonoTypeNameParse info;
7686         char *tmp;
7687
7688         /* Make a copy since parse_type modifies its argument */
7689         tmp = g_strdup (name);
7690         
7691         /*g_print ("requested type %s\n", str);*/
7692         if (mono_reflection_parse_type (tmp, &info)) {
7693                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7694         }
7695
7696         g_free (tmp);
7697         mono_reflection_free_type_info (&info);
7698         return type;
7699 }
7700
7701 /*
7702  * mono_reflection_get_token:
7703  *
7704  *   Return the metadata token of OBJ which should be an object
7705  * representing a metadata element.
7706  */
7707 guint32
7708 mono_reflection_get_token (MonoObject *obj)
7709 {
7710         MonoClass *klass;
7711         guint32 token = 0;
7712
7713         klass = obj->vtable->klass;
7714
7715         if (strcmp (klass->name, "MethodBuilder") == 0) {
7716                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7717
7718                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7719         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7720                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7721
7722                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7723         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7724                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7725
7726                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7727         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7728                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7729                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7730         } else if (strcmp (klass->name, "MonoType") == 0) {
7731                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7732                 MonoClass *mc = mono_class_from_mono_type (type);
7733                 if (!mono_class_init (mc))
7734                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7735
7736                 token = mc->type_token;
7737         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7738                    strcmp (klass->name, "MonoMethod") == 0 ||
7739                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7740                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7741                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7742                 if (m->method->is_inflated) {
7743                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7744                         return inflated->declaring->token;
7745                 } else {
7746                         token = m->method->token;
7747                 }
7748         } else if (strcmp (klass->name, "MonoField") == 0) {
7749                 MonoReflectionField *f = (MonoReflectionField*)obj;
7750
7751                 if (is_field_on_inst (f->field)) {
7752                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7753                         int field_index = f->field - dgclass->fields;
7754                         MonoObject *obj;
7755
7756                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7757                         obj = dgclass->field_objects [field_index];
7758                         return mono_reflection_get_token (obj);
7759                 }
7760                 token = mono_class_get_field_token (f->field);
7761         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7762                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7763
7764                 token = mono_class_get_property_token (p->property);
7765         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7766                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7767
7768                 token = mono_class_get_event_token (p->event);
7769         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7770                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7771                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7772                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7773
7774                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7775         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7776                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7777
7778                 token = m->token;
7779         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7780                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7781         } else {
7782                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7783                 MonoException *ex = mono_get_exception_not_implemented (msg);
7784                 g_free (msg);
7785                 mono_raise_exception (ex);
7786         }
7787
7788         return token;
7789 }
7790
7791 static void*
7792 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7793 {
7794         int slen, type = t->type;
7795         MonoClass *tklass = t->data.klass;
7796
7797 handle_enum:
7798         switch (type) {
7799         case MONO_TYPE_U1:
7800         case MONO_TYPE_I1:
7801         case MONO_TYPE_BOOLEAN: {
7802                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7803                 *bval = *p;
7804                 *end = p + 1;
7805                 return bval;
7806         }
7807         case MONO_TYPE_CHAR:
7808         case MONO_TYPE_U2:
7809         case MONO_TYPE_I2: {
7810                 guint16 *val = g_malloc (sizeof (guint16));
7811                 *val = read16 (p);
7812                 *end = p + 2;
7813                 return val;
7814         }
7815 #if SIZEOF_VOID_P == 4
7816         case MONO_TYPE_U:
7817         case MONO_TYPE_I:
7818 #endif
7819         case MONO_TYPE_R4:
7820         case MONO_TYPE_U4:
7821         case MONO_TYPE_I4: {
7822                 guint32 *val = g_malloc (sizeof (guint32));
7823                 *val = read32 (p);
7824                 *end = p + 4;
7825                 return val;
7826         }
7827 #if SIZEOF_VOID_P == 8
7828         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7829         case MONO_TYPE_I:
7830 #endif
7831         case MONO_TYPE_U8:
7832         case MONO_TYPE_I8: {
7833                 guint64 *val = g_malloc (sizeof (guint64));
7834                 *val = read64 (p);
7835                 *end = p + 8;
7836                 return val;
7837         }
7838         case MONO_TYPE_R8: {
7839                 double *val = g_malloc (sizeof (double));
7840                 readr8 (p, val);
7841                 *end = p + 8;
7842                 return val;
7843         }
7844         case MONO_TYPE_VALUETYPE:
7845                 if (t->data.klass->enumtype) {
7846                         type = mono_class_enum_basetype (t->data.klass)->type;
7847                         goto handle_enum;
7848                 } else {
7849                         MonoClass *k =  t->data.klass;
7850                         
7851                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7852                                 guint64 *val = g_malloc (sizeof (guint64));
7853                                 *val = read64 (p);
7854                                 *end = p + 8;
7855                                 return val;
7856                         }
7857                 }
7858                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7859                 break;
7860                 
7861         case MONO_TYPE_STRING:
7862                 if (*p == (char)0xFF) {
7863                         *end = p + 1;
7864                         return NULL;
7865                 }
7866                 slen = mono_metadata_decode_value (p, &p);
7867                 *end = p + slen;
7868                 return mono_string_new_len (mono_domain_get (), p, slen);
7869         case MONO_TYPE_CLASS: {
7870                 char *n;
7871                 MonoType *t;
7872                 if (*p == (char)0xFF) {
7873                         *end = p + 1;
7874                         return NULL;
7875                 }
7876 handle_type:
7877                 slen = mono_metadata_decode_value (p, &p);
7878                 n = g_memdup (p, slen + 1);
7879                 n [slen] = 0;
7880                 t = mono_reflection_type_from_name (n, image);
7881                 if (!t)
7882                         g_warning ("Cannot load type '%s'", n);
7883                 g_free (n);
7884                 *end = p + slen;
7885                 if (t)
7886                         return mono_type_get_object (mono_domain_get (), t);
7887                 else
7888                         return NULL;
7889         }
7890         case MONO_TYPE_OBJECT: {
7891                 char subt = *p++;
7892                 MonoObject *obj;
7893                 MonoClass *subc = NULL;
7894                 void *val;
7895
7896                 if (subt == 0x50) {
7897                         goto handle_type;
7898                 } else if (subt == 0x0E) {
7899                         type = MONO_TYPE_STRING;
7900                         goto handle_enum;
7901                 } else if (subt == 0x1D) {
7902                         MonoType simple_type = {{0}};
7903                         int etype = *p;
7904                         p ++;
7905
7906                         type = MONO_TYPE_SZARRAY;
7907                         if (etype == 0x50) {
7908                                 tklass = mono_defaults.systemtype_class;
7909                         } else {
7910                                 if (etype == 0x51)
7911                                         /* See Partition II, Appendix B3 */
7912                                         etype = MONO_TYPE_OBJECT;
7913                                 simple_type.type = etype;
7914                                 tklass = mono_class_from_mono_type (&simple_type);
7915                         }
7916                         goto handle_enum;
7917                 } else if (subt == 0x55) {
7918                         char *n;
7919                         MonoType *t;
7920                         slen = mono_metadata_decode_value (p, &p);
7921                         n = g_memdup (p, slen + 1);
7922                         n [slen] = 0;
7923                         t = mono_reflection_type_from_name (n, image);
7924                         if (!t)
7925                                 g_error ("Cannot load type '%s'", n);
7926                         g_free (n);
7927                         p += slen;
7928                         subc = mono_class_from_mono_type (t);
7929                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7930                         MonoType simple_type = {{0}};
7931                         simple_type.type = subt;
7932                         subc = mono_class_from_mono_type (&simple_type);
7933                 } else {
7934                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7935                 }
7936                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7937                 obj = mono_object_new (mono_domain_get (), subc);
7938                 g_assert (!subc->has_references);
7939                 mono_gc_memmove ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7940                 g_free (val);
7941                 return obj;
7942         }
7943         case MONO_TYPE_SZARRAY: {
7944                 MonoArray *arr;
7945                 guint32 i, alen, basetype;
7946                 alen = read32 (p);
7947                 p += 4;
7948                 if (alen == 0xffffffff) {
7949                         *end = p;
7950                         return NULL;
7951                 }
7952                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7953                 basetype = tklass->byval_arg.type;
7954                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7955                         basetype = mono_class_enum_basetype (tklass)->type;
7956                 switch (basetype)
7957                 {
7958                         case MONO_TYPE_U1:
7959                         case MONO_TYPE_I1:
7960                         case MONO_TYPE_BOOLEAN:
7961                                 for (i = 0; i < alen; i++) {
7962                                         MonoBoolean val = *p++;
7963                                         mono_array_set (arr, MonoBoolean, i, val);
7964                                 }
7965                                 break;
7966                         case MONO_TYPE_CHAR:
7967                         case MONO_TYPE_U2:
7968                         case MONO_TYPE_I2:
7969                                 for (i = 0; i < alen; i++) {
7970                                         guint16 val = read16 (p);
7971                                         mono_array_set (arr, guint16, i, val);
7972                                         p += 2;
7973                                 }
7974                                 break;
7975                         case MONO_TYPE_R4:
7976                         case MONO_TYPE_U4:
7977                         case MONO_TYPE_I4:
7978                                 for (i = 0; i < alen; i++) {
7979                                         guint32 val = read32 (p);
7980                                         mono_array_set (arr, guint32, i, val);
7981                                         p += 4;
7982                                 }
7983                                 break;
7984                         case MONO_TYPE_R8:
7985                                 for (i = 0; i < alen; i++) {
7986                                         double val;
7987                                         readr8 (p, &val);
7988                                         mono_array_set (arr, double, i, val);
7989                                         p += 8;
7990                                 }
7991                                 break;
7992                         case MONO_TYPE_U8:
7993                         case MONO_TYPE_I8:
7994                                 for (i = 0; i < alen; i++) {
7995                                         guint64 val = read64 (p);
7996                                         mono_array_set (arr, guint64, i, val);
7997                                         p += 8;
7998                                 }
7999                                 break;
8000                         case MONO_TYPE_CLASS:
8001                         case MONO_TYPE_OBJECT:
8002                         case MONO_TYPE_STRING:
8003                                 for (i = 0; i < alen; i++) {
8004                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8005                                         mono_array_setref (arr, i, item);
8006                                 }
8007                                 break;
8008                         default:
8009                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8010                 }
8011                 *end=p;
8012                 return arr;
8013         }
8014         default:
8015                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8016         }
8017         return NULL;
8018 }
8019
8020 static MonoObject*
8021 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8022 {
8023         static MonoClass *klass;
8024         static MonoMethod *ctor;
8025         MonoObject *retval;
8026         void *params [2], *unboxed;
8027
8028         if (!klass)
8029                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8030         if (!ctor)
8031                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8032         
8033         params [0] = mono_type_get_object (mono_domain_get (), t);
8034         params [1] = val;
8035         retval = mono_object_new (mono_domain_get (), klass);
8036         unboxed = mono_object_unbox (retval);
8037         mono_runtime_invoke (ctor, unboxed, params, NULL);
8038
8039         return retval;
8040 }
8041
8042 static MonoObject*
8043 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8044 {
8045         static MonoClass *klass;
8046         static MonoMethod *ctor;
8047         MonoObject *retval;
8048         void *unboxed, *params [2];
8049
8050         if (!klass)
8051                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8052         if (!ctor)
8053                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8054
8055         params [0] = minfo;
8056         params [1] = typedarg;
8057         retval = mono_object_new (mono_domain_get (), klass);
8058         unboxed = mono_object_unbox (retval);
8059         mono_runtime_invoke (ctor, unboxed, params, NULL);
8060
8061         return retval;
8062 }
8063
8064 static gboolean
8065 type_is_reference (MonoType *type)
8066 {
8067         switch (type->type) {
8068         case MONO_TYPE_BOOLEAN:
8069         case MONO_TYPE_CHAR:
8070         case MONO_TYPE_U:
8071         case MONO_TYPE_I:
8072         case MONO_TYPE_U1:
8073         case MONO_TYPE_I1:
8074         case MONO_TYPE_U2:
8075         case MONO_TYPE_I2:
8076         case MONO_TYPE_U4:
8077         case MONO_TYPE_I4:
8078         case MONO_TYPE_U8:
8079         case MONO_TYPE_I8:
8080         case MONO_TYPE_R8:
8081         case MONO_TYPE_R4:
8082         case MONO_TYPE_VALUETYPE:
8083                 return FALSE;
8084         default:
8085                 return TRUE;
8086         }
8087 }
8088
8089 static void
8090 free_param_data (MonoMethodSignature *sig, void **params) {
8091         int i;
8092         for (i = 0; i < sig->param_count; ++i) {
8093                 if (!type_is_reference (sig->params [i]))
8094                         g_free (params [i]);
8095         }
8096 }
8097
8098 /*
8099  * Find the field index in the metadata FieldDef table.
8100  */
8101 static guint32
8102 find_field_index (MonoClass *klass, MonoClassField *field) {
8103         int i;
8104
8105         for (i = 0; i < klass->field.count; ++i) {
8106                 if (field == &klass->fields [i])
8107                         return klass->field.first + 1 + i;
8108         }
8109         return 0;
8110 }
8111
8112 /*
8113  * Find the property index in the metadata Property table.
8114  */
8115 static guint32
8116 find_property_index (MonoClass *klass, MonoProperty *property) {
8117         int i;
8118
8119         for (i = 0; i < klass->ext->property.count; ++i) {
8120                 if (property == &klass->ext->properties [i])
8121                         return klass->ext->property.first + 1 + i;
8122         }
8123         return 0;
8124 }
8125
8126 /*
8127  * Find the event index in the metadata Event table.
8128  */
8129 static guint32
8130 find_event_index (MonoClass *klass, MonoEvent *event) {
8131         int i;
8132
8133         for (i = 0; i < klass->ext->event.count; ++i) {
8134                 if (event == &klass->ext->events [i])
8135                         return klass->ext->event.first + 1 + i;
8136         }
8137         return 0;
8138 }
8139
8140 static MonoObject*
8141 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8142 {
8143         const char *p = (const char*)data;
8144         const char *named;
8145         guint32 i, j, num_named;
8146         MonoObject *attr;
8147         void *params_buf [32];
8148         void **params;
8149         MonoMethodSignature *sig;
8150
8151         mono_error_init (error);
8152
8153         mono_class_init (method->klass);
8154
8155         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8156                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8157                 return NULL;
8158         }
8159
8160         if (len == 0) {
8161                 attr = mono_object_new (mono_domain_get (), method->klass);
8162                 mono_runtime_invoke (method, attr, NULL, NULL);
8163                 return attr;
8164         }
8165
8166         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8167                 return NULL;
8168
8169         /*g_print ("got attr %s\n", method->klass->name);*/
8170
8171         sig = mono_method_signature (method);
8172         if (sig->param_count < 32)
8173                 params = params_buf;
8174         else
8175                 /* Allocate using GC so it gets GC tracking */
8176                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8177
8178         /* skip prolog */
8179         p += 2;
8180         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8181                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8182         }
8183
8184         named = p;
8185         attr = mono_object_new (mono_domain_get (), method->klass);
8186         mono_runtime_invoke (method, attr, params, NULL);
8187         free_param_data (method->signature, params);
8188         num_named = read16 (named);
8189         named += 2;
8190         for (j = 0; j < num_named; j++) {
8191                 gint name_len;
8192                 char *name, named_type, data_type;
8193                 named_type = *named++;
8194                 data_type = *named++; /* type of data */
8195                 if (data_type == MONO_TYPE_SZARRAY)
8196                         data_type = *named++;
8197                 if (data_type == MONO_TYPE_ENUM) {
8198                         gint type_len;
8199                         char *type_name;
8200                         type_len = mono_metadata_decode_blob_size (named, &named);
8201                         type_name = g_malloc (type_len + 1);
8202                         memcpy (type_name, named, type_len);
8203                         type_name [type_len] = 0;
8204                         named += type_len;
8205                         /* FIXME: lookup the type and check type consistency */
8206                         g_free (type_name);
8207                 }
8208                 name_len = mono_metadata_decode_blob_size (named, &named);
8209                 name = g_malloc (name_len + 1);
8210                 memcpy (name, named, name_len);
8211                 name [name_len] = 0;
8212                 named += name_len;
8213                 if (named_type == 0x53) {
8214                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8215                         void *val = load_cattr_value (image, field->type, named, &named);
8216                         mono_field_set_value (attr, field, val);
8217                         if (!type_is_reference (field->type))
8218                                 g_free (val);
8219                 } else if (named_type == 0x54) {
8220                         MonoProperty *prop;
8221                         void *pparams [1];
8222                         MonoType *prop_type;
8223
8224                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8225                         /* can we have more that 1 arg in a custom attr named property? */
8226                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8227                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8228                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8229                         mono_property_set_value (prop, attr, pparams, NULL);
8230                         if (!type_is_reference (prop_type))
8231                                 g_free (pparams [0]);
8232                 }
8233                 g_free (name);
8234         }
8235
8236         if (params != params_buf)
8237                 mono_gc_free_fixed (params);
8238
8239         return attr;
8240 }
8241         
8242 /*
8243  * mono_reflection_create_custom_attr_data_args:
8244  *
8245  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8246  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8247  * NAMED_ARG_INFO will contain information about the named arguments.
8248  */
8249 void
8250 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)
8251 {
8252         MonoArray *typedargs, *namedargs;
8253         MonoClass *attrklass;
8254         MonoDomain *domain;
8255         const char *p = (const char*)data;
8256         const char *named;
8257         guint32 i, j, num_named;
8258         CattrNamedArg *arginfo = NULL;
8259
8260         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8261                 return;
8262
8263         mono_class_init (method->klass);
8264
8265         *typed_args = NULL;
8266         *named_args = NULL;
8267         *named_arg_info = NULL;
8268         
8269         domain = mono_domain_get ();
8270
8271         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8272                 return;
8273
8274         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8275         
8276         /* skip prolog */
8277         p += 2;
8278         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8279                 MonoObject *obj;
8280                 void *val;
8281
8282                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8283                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8284                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8285                 mono_array_setref (typedargs, i, obj);
8286
8287                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8288                         g_free (val);
8289         }
8290
8291         named = p;
8292         num_named = read16 (named);
8293         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8294         named += 2;
8295         attrklass = method->klass;
8296
8297         arginfo = g_new0 (CattrNamedArg, num_named);
8298         *named_arg_info = arginfo;
8299
8300         for (j = 0; j < num_named; j++) {
8301                 gint name_len;
8302                 char *name, named_type, data_type;
8303                 named_type = *named++;
8304                 data_type = *named++; /* type of data */
8305                 if (data_type == MONO_TYPE_SZARRAY)
8306                         data_type = *named++;
8307                 if (data_type == MONO_TYPE_ENUM) {
8308                         gint type_len;
8309                         char *type_name;
8310                         type_len = mono_metadata_decode_blob_size (named, &named);
8311                         type_name = g_malloc (type_len + 1);
8312                         memcpy (type_name, named, type_len);
8313                         type_name [type_len] = 0;
8314                         named += type_len;
8315                         /* FIXME: lookup the type and check type consistency */
8316                         g_free (type_name);
8317                 }
8318                 name_len = mono_metadata_decode_blob_size (named, &named);
8319                 name = g_malloc (name_len + 1);
8320                 memcpy (name, named, name_len);
8321                 name [name_len] = 0;
8322                 named += name_len;
8323                 if (named_type == 0x53) {
8324                         MonoObject *obj;
8325                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8326                         void *val;
8327
8328                         arginfo [j].type = field->type;
8329                         arginfo [j].field = field;
8330
8331                         val = load_cattr_value (image, field->type, named, &named);
8332                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8333                         mono_array_setref (namedargs, j, obj);
8334                         if (!type_is_reference (field->type))
8335                                 g_free (val);
8336                 } else if (named_type == 0x54) {
8337                         MonoObject *obj;
8338                         MonoType *prop_type;
8339                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8340                         void *val;
8341
8342                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8343                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8344
8345                         arginfo [j].type = prop_type;
8346                         arginfo [j].prop = prop;
8347
8348                         val = load_cattr_value (image, prop_type, named, &named);
8349                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8350                         mono_array_setref (namedargs, j, obj);
8351                         if (!type_is_reference (prop_type))
8352                                 g_free (val);
8353                 }
8354                 g_free (name);
8355         }
8356
8357         *typed_args = typedargs;
8358         *named_args = namedargs;
8359 }
8360
8361 void
8362 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8363 {
8364         MonoDomain *domain;
8365         MonoArray *typedargs, *namedargs;
8366         MonoImage *image;
8367         MonoMethod *method;
8368         CattrNamedArg *arginfo;
8369         int i;
8370
8371         *ctor_args = NULL;
8372         *named_args = NULL;
8373
8374         if (len == 0)
8375                 return;
8376
8377         image = assembly->assembly->image;
8378         method = ref_method->method;
8379         domain = mono_object_domain (ref_method);
8380
8381         if (!mono_class_init (method->klass))
8382                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8383
8384         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8385         if (mono_loader_get_last_error ())
8386                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8387
8388         if (!typedargs || !namedargs)
8389                 return;
8390
8391         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8392                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8393                 MonoObject *typedarg;
8394
8395                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8396                 mono_array_setref (typedargs, i, typedarg);
8397         }
8398
8399         for (i = 0; i < mono_array_length (namedargs); ++i) {
8400                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8401                 MonoObject *typedarg, *namedarg, *minfo;
8402
8403                 if (arginfo [i].prop)
8404                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8405                 else
8406                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8407
8408                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8409                 namedarg = create_cattr_named_arg (minfo, typedarg);
8410
8411                 mono_array_setref (namedargs, i, namedarg);
8412         }
8413
8414         *ctor_args = typedargs;
8415         *named_args = namedargs;
8416 }
8417
8418 static MonoObject*
8419 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8420 {
8421         static MonoMethod *ctor;
8422         MonoDomain *domain;
8423         MonoObject *attr;
8424         void *params [4];
8425
8426         g_assert (image->assembly);
8427
8428         if (!ctor)
8429                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8430
8431         domain = mono_domain_get ();
8432         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8433         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8434         params [1] = mono_assembly_get_object (domain, image->assembly);
8435         params [2] = (gpointer)&cattr->data;
8436         params [3] = &cattr->data_size;
8437         mono_runtime_invoke (ctor, attr, params, NULL);
8438         return attr;
8439 }
8440
8441 static MonoArray*
8442 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8443 {
8444         MonoArray *result;
8445         MonoObject *attr;
8446         int i, n;
8447
8448         mono_error_init (error);
8449
8450         n = 0;
8451         for (i = 0; i < cinfo->num_attrs; ++i) {
8452                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8453                         n ++;
8454         }
8455
8456         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8457         n = 0;
8458         for (i = 0; i < cinfo->num_attrs; ++i) {
8459                 if (!cinfo->attrs [i].ctor)
8460                         /* The cattr type is not finished yet */
8461                         /* We should include the type name but cinfo doesn't contain it */
8462                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8463                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8464                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8465                         if (!mono_error_ok (error))
8466                                 return result;
8467                         mono_array_setref (result, n, attr);
8468                         n ++;
8469                 }
8470         }
8471         return result;
8472 }
8473
8474 MonoArray*
8475 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8476 {
8477         MonoError error;
8478
8479         return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8480 }
8481
8482 static MonoArray*
8483 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8484 {
8485         MonoArray *result;
8486         MonoObject *attr;
8487         int i;
8488         
8489         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8490         for (i = 0; i < cinfo->num_attrs; ++i) {
8491                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8492                 mono_array_setref (result, i, attr);
8493         }
8494         return result;
8495 }
8496
8497 /**
8498  * mono_custom_attrs_from_index:
8499  *
8500  * Returns: NULL if no attributes are found or if a loading error occurs.
8501  */
8502 MonoCustomAttrInfo*
8503 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8504 {
8505         guint32 mtoken, i, len;
8506         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8507         MonoTableInfo *ca;
8508         MonoCustomAttrInfo *ainfo;
8509         GList *tmp, *list = NULL;
8510         const char *data;
8511
8512         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8513
8514         i = mono_metadata_custom_attrs_from_index (image, idx);
8515         if (!i)
8516                 return NULL;
8517         i --;
8518         while (i < ca->rows) {
8519                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8520                         break;
8521                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8522                 ++i;
8523         }
8524         len = g_list_length (list);
8525         if (!len)
8526                 return NULL;
8527         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8528         ainfo->num_attrs = len;
8529         ainfo->image = image;
8530         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8531                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8532                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8533                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8534                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8535                         mtoken |= MONO_TOKEN_METHOD_DEF;
8536                         break;
8537                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8538                         mtoken |= MONO_TOKEN_MEMBER_REF;
8539                         break;
8540                 default:
8541                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8542                         break;
8543                 }
8544                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8545                 if (!ainfo->attrs [i].ctor) {
8546                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8547                         g_list_free (list);
8548                         g_free (ainfo);
8549                         return NULL;
8550                 }
8551
8552                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8553                         /*FIXME raising an exception here doesn't make any sense*/
8554                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8555                         g_list_free (list);
8556                         g_free (ainfo);
8557                         return NULL;
8558                 }
8559                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8560                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8561                 ainfo->attrs [i].data = (guchar*)data;
8562         }
8563         g_list_free (list);
8564
8565         return ainfo;
8566 }
8567
8568 MonoCustomAttrInfo*
8569 mono_custom_attrs_from_method (MonoMethod *method)
8570 {
8571         guint32 idx;
8572
8573         /*
8574          * An instantiated method has the same cattrs as the generic method definition.
8575          *
8576          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8577          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8578          */
8579         if (method->is_inflated)
8580                 method = ((MonoMethodInflated *) method)->declaring;
8581         
8582         if (method->dynamic || method->klass->image->dynamic)
8583                 return lookup_custom_attr (method->klass->image, method);
8584
8585         if (!method->token)
8586                 /* Synthetic methods */
8587                 return NULL;
8588
8589         idx = mono_method_get_index (method);
8590         idx <<= MONO_CUSTOM_ATTR_BITS;
8591         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8592         return mono_custom_attrs_from_index (method->klass->image, idx);
8593 }
8594
8595 MonoCustomAttrInfo*
8596 mono_custom_attrs_from_class (MonoClass *klass)
8597 {
8598         guint32 idx;
8599
8600         if (klass->generic_class)
8601                 klass = klass->generic_class->container_class;
8602
8603         if (klass->image->dynamic)
8604                 return lookup_custom_attr (klass->image, klass);
8605
8606         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8607                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8608                 idx <<= MONO_CUSTOM_ATTR_BITS;
8609                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8610         } else {
8611                 idx = mono_metadata_token_index (klass->type_token);
8612                 idx <<= MONO_CUSTOM_ATTR_BITS;
8613                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8614         }
8615         return mono_custom_attrs_from_index (klass->image, idx);
8616 }
8617
8618 MonoCustomAttrInfo*
8619 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8620 {
8621         guint32 idx;
8622         
8623         if (assembly->image->dynamic)
8624                 return lookup_custom_attr (assembly->image, assembly);
8625         idx = 1; /* there is only one assembly */
8626         idx <<= MONO_CUSTOM_ATTR_BITS;
8627         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8628         return mono_custom_attrs_from_index (assembly->image, idx);
8629 }
8630
8631 static MonoCustomAttrInfo*
8632 mono_custom_attrs_from_module (MonoImage *image)
8633 {
8634         guint32 idx;
8635         
8636         if (image->dynamic)
8637                 return lookup_custom_attr (image, image);
8638         idx = 1; /* there is only one module */
8639         idx <<= MONO_CUSTOM_ATTR_BITS;
8640         idx |= MONO_CUSTOM_ATTR_MODULE;
8641         return mono_custom_attrs_from_index (image, idx);
8642 }
8643
8644 MonoCustomAttrInfo*
8645 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8646 {
8647         guint32 idx;
8648         
8649         if (klass->image->dynamic) {
8650                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8651                 return lookup_custom_attr (klass->image, property);
8652         }
8653         idx = find_property_index (klass, property);
8654         idx <<= MONO_CUSTOM_ATTR_BITS;
8655         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8656         return mono_custom_attrs_from_index (klass->image, idx);
8657 }
8658
8659 MonoCustomAttrInfo*
8660 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8661 {
8662         guint32 idx;
8663         
8664         if (klass->image->dynamic) {
8665                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8666                 return lookup_custom_attr (klass->image, event);
8667         }
8668         idx = find_event_index (klass, event);
8669         idx <<= MONO_CUSTOM_ATTR_BITS;
8670         idx |= MONO_CUSTOM_ATTR_EVENT;
8671         return mono_custom_attrs_from_index (klass->image, idx);
8672 }
8673
8674 MonoCustomAttrInfo*
8675 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8676 {
8677         guint32 idx;
8678         if (klass->image->dynamic) {
8679                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8680                 return lookup_custom_attr (klass->image, field);
8681         }
8682         idx = find_field_index (klass, field);
8683         idx <<= MONO_CUSTOM_ATTR_BITS;
8684         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8685         return mono_custom_attrs_from_index (klass->image, idx);
8686 }
8687
8688 MonoCustomAttrInfo*
8689 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8690 {
8691         MonoTableInfo *ca;
8692         guint32 i, idx, method_index;
8693         guint32 param_list, param_last, param_pos, found;
8694         MonoImage *image;
8695         MonoReflectionMethodAux *aux;
8696
8697         /*
8698          * An instantiated method has the same cattrs as the generic method definition.
8699          *
8700          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8701          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8702          */
8703         if (method->is_inflated)
8704                 method = ((MonoMethodInflated *) method)->declaring;
8705
8706         if (method->klass->image->dynamic) {
8707                 MonoCustomAttrInfo *res, *ainfo;
8708                 int size;
8709
8710                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8711                 if (!aux || !aux->param_cattr)
8712                         return NULL;
8713
8714                 /* Need to copy since it will be freed later */
8715                 ainfo = aux->param_cattr [param];
8716                 if (!ainfo)
8717                         return NULL;
8718                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8719                 res = g_malloc0 (size);
8720                 memcpy (res, ainfo, size);
8721                 return res;
8722         }
8723
8724         image = method->klass->image;
8725         method_index = mono_method_get_index (method);
8726         if (!method_index)
8727                 return NULL;
8728         ca = &image->tables [MONO_TABLE_METHOD];
8729
8730         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8731         if (method_index == ca->rows) {
8732                 ca = &image->tables [MONO_TABLE_PARAM];
8733                 param_last = ca->rows + 1;
8734         } else {
8735                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8736                 ca = &image->tables [MONO_TABLE_PARAM];
8737         }
8738         found = FALSE;
8739         for (i = param_list; i < param_last; ++i) {
8740                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8741                 if (param_pos == param) {
8742                         found = TRUE;
8743                         break;
8744                 }
8745         }
8746         if (!found)
8747                 return NULL;
8748         idx = i;
8749         idx <<= MONO_CUSTOM_ATTR_BITS;
8750         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8751         return mono_custom_attrs_from_index (image, idx);
8752 }
8753
8754 gboolean
8755 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8756 {
8757         int i;
8758         MonoClass *klass;
8759         for (i = 0; i < ainfo->num_attrs; ++i) {
8760                 klass = ainfo->attrs [i].ctor->klass;
8761                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8762                         return TRUE;
8763         }
8764         return FALSE;
8765 }
8766
8767 MonoObject*
8768 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8769 {
8770         int i, attr_index;
8771         MonoClass *klass;
8772         MonoArray *attrs;
8773
8774         attr_index = -1;
8775         for (i = 0; i < ainfo->num_attrs; ++i) {
8776                 klass = ainfo->attrs [i].ctor->klass;
8777                 if (mono_class_has_parent (klass, attr_klass)) {
8778                         attr_index = i;
8779                         break;
8780                 }
8781         }
8782         if (attr_index == -1)
8783                 return NULL;
8784
8785         attrs = mono_custom_attrs_construct (ainfo);
8786         if (attrs)
8787                 return mono_array_get (attrs, MonoObject*, attr_index);
8788         else
8789                 return NULL;
8790 }
8791
8792 /*
8793  * mono_reflection_get_custom_attrs_info:
8794  * @obj: a reflection object handle
8795  *
8796  * Return the custom attribute info for attributes defined for the
8797  * reflection handle @obj. The objects.
8798  *
8799  * FIXME this function leaks like a sieve for SRE objects.
8800  */
8801 MonoCustomAttrInfo*
8802 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8803 {
8804         MonoClass *klass;
8805         MonoCustomAttrInfo *cinfo = NULL;
8806         
8807         klass = obj->vtable->klass;
8808         if (klass == mono_defaults.monotype_class) {
8809                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8810                 klass = mono_class_from_mono_type (type);
8811                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8812                 cinfo = mono_custom_attrs_from_class (klass);
8813         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8814                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8815                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8816         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8817                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8818                 cinfo = mono_custom_attrs_from_module (module->image);
8819         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8820                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8821                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8822         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8823                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8824                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8825         } else if (strcmp ("MonoField", klass->name) == 0) {
8826                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8827                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8828         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8829                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8830                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8831         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8832                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8833                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8834         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8835                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8836                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8837                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8838                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8839                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8840                 } else if (is_sr_mono_property (member_class)) {
8841                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8842                         MonoMethod *method;
8843                         if (!(method = prop->property->get))
8844                                 method = prop->property->set;
8845                         g_assert (method);
8846
8847                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8848                 } 
8849 #ifndef DISABLE_REFLECTION_EMIT
8850                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8851                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8852                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8853                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8854                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8855                         MonoMethod *method = NULL;
8856                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8857                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8858                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8859                                 method = ((MonoReflectionMethod *)c->cb)->method;
8860                         else
8861                                 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));
8862
8863                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8864                 } 
8865 #endif
8866                 else {
8867                         char *type_name = mono_type_get_full_name (member_class);
8868                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8869                         MonoException *ex = mono_get_exception_not_supported  (msg);
8870                         g_free (type_name);
8871                         g_free (msg);
8872                         mono_raise_exception (ex);
8873                 }
8874         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8875                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8876                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8877         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8878                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8879                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8880         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8881                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8882                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8883         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8884                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8885                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8886         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8887                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8888                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8889         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8890                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8891                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8892         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8893                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8894                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8895         } else { /* handle other types here... */
8896                 g_error ("get custom attrs not yet supported for %s", klass->name);
8897         }
8898
8899         return cinfo;
8900 }
8901
8902 /*
8903  * mono_reflection_get_custom_attrs_by_type:
8904  * @obj: a reflection object handle
8905  *
8906  * Return an array with all the custom attributes defined of the
8907  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8908  * of that type are returned. The objects are fully build. Return NULL if a loading error
8909  * occurs.
8910  */
8911 MonoArray*
8912 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8913 {
8914         MonoArray *result;
8915         MonoCustomAttrInfo *cinfo;
8916
8917         mono_error_init (error);
8918
8919         cinfo = mono_reflection_get_custom_attrs_info (obj);
8920         if (cinfo) {
8921                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8922                 if (!cinfo->cached)
8923                         mono_custom_attrs_free (cinfo);
8924         } else {
8925                 if (mono_loader_get_last_error ())
8926                         return NULL;
8927                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8928         }
8929
8930         return result;
8931 }
8932
8933 /*
8934  * mono_reflection_get_custom_attrs:
8935  * @obj: a reflection object handle
8936  *
8937  * Return an array with all the custom attributes defined of the
8938  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8939  * occurs.
8940  */
8941 MonoArray*
8942 mono_reflection_get_custom_attrs (MonoObject *obj)
8943 {
8944         MonoError error;
8945
8946         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8947 }
8948
8949 /*
8950  * mono_reflection_get_custom_attrs_data:
8951  * @obj: a reflection obj handle
8952  *
8953  * Returns an array of System.Reflection.CustomAttributeData,
8954  * which include information about attributes reflected on
8955  * types loaded using the Reflection Only methods
8956  */
8957 MonoArray*
8958 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8959 {
8960         MonoArray *result;
8961         MonoCustomAttrInfo *cinfo;
8962
8963         cinfo = mono_reflection_get_custom_attrs_info (obj);
8964         if (cinfo) {
8965                 result = mono_custom_attrs_data_construct (cinfo);
8966                 if (!cinfo->cached)
8967                         mono_custom_attrs_free (cinfo);
8968         } else
8969                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8970
8971         return result;
8972 }
8973
8974 static MonoReflectionType*
8975 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8976 {
8977         static MonoMethod *method_get_underlying_system_type = NULL;
8978         MonoMethod *usertype_method;
8979
8980         if (!method_get_underlying_system_type)
8981                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8982         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8983         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8984 }
8985
8986
8987 static gboolean
8988 is_corlib_type (MonoClass *class)
8989 {
8990         return class->image == mono_defaults.corlib;
8991 }
8992
8993 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8994         static MonoClass *cached_class; \
8995         if (cached_class) \
8996                 return cached_class == _class; \
8997         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8998                 cached_class = _class; \
8999                 return TRUE; \
9000         } \
9001         return FALSE; \
9002 } while (0) \
9003
9004
9005 #ifndef DISABLE_REFLECTION_EMIT
9006 static gboolean
9007 is_sre_array (MonoClass *class)
9008 {
9009         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9010 }
9011
9012 static gboolean
9013 is_sre_byref (MonoClass *class)
9014 {
9015         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9016 }
9017
9018 static gboolean
9019 is_sre_pointer (MonoClass *class)
9020 {
9021         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9022 }
9023
9024 static gboolean
9025 is_sre_generic_instance (MonoClass *class)
9026 {
9027         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9028 }
9029
9030 static gboolean
9031 is_sre_type_builder (MonoClass *class)
9032 {
9033         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9034 }
9035
9036 static gboolean
9037 is_sre_method_builder (MonoClass *class)
9038 {
9039         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9040 }
9041
9042 static gboolean
9043 is_sre_ctor_builder (MonoClass *class)
9044 {
9045         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9046 }
9047
9048 static gboolean
9049 is_sre_field_builder (MonoClass *class)
9050 {
9051         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9052 }
9053
9054 static gboolean
9055 is_sre_method_on_tb_inst (MonoClass *class)
9056 {
9057         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9058 }
9059
9060 static gboolean
9061 is_sre_ctor_on_tb_inst (MonoClass *class)
9062 {
9063         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9064 }
9065
9066 MonoType*
9067 mono_reflection_type_get_handle (MonoReflectionType* ref)
9068 {
9069         MonoClass *class;
9070         if (!ref)
9071                 return NULL;
9072         if (ref->type)
9073                 return ref->type;
9074
9075         if (is_usertype (ref)) {
9076                 ref = mono_reflection_type_get_underlying_system_type (ref);
9077                 if (ref == NULL || is_usertype (ref))
9078                         return NULL;
9079                 if (ref->type)
9080                         return ref->type;
9081         }
9082
9083         class = mono_object_class (ref);
9084
9085         if (is_sre_array (class)) {
9086                 MonoType *res;
9087                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9088                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9089                 g_assert (base);
9090                 if (sre_array->rank == 0) //single dimentional array
9091                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9092                 else
9093                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9094                 sre_array->type.type = res;
9095                 return res;
9096         } else if (is_sre_byref (class)) {
9097                 MonoType *res;
9098                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9099                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9100                 g_assert (base);
9101                 res = &mono_class_from_mono_type (base)->this_arg;
9102                 sre_byref->type.type = res;
9103                 return res;
9104         } else if (is_sre_pointer (class)) {
9105                 MonoType *res;
9106                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9107                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9108                 g_assert (base);
9109                 res = &mono_ptr_class_get (base)->byval_arg;
9110                 sre_pointer->type.type = res;
9111                 return res;
9112         } else if (is_sre_generic_instance (class)) {
9113                 MonoType *res, **types;
9114                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9115                 int i, count;
9116
9117                 count = mono_array_length (gclass->type_arguments);
9118                 types = g_new0 (MonoType*, count);
9119                 for (i = 0; i < count; ++i) {
9120                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9121                         types [i] = mono_reflection_type_get_handle (t);
9122                         if (!types[i]) {
9123                                 g_free (types);
9124                                 return NULL;
9125                         }
9126                 }
9127
9128                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9129                 g_free (types);
9130                 g_assert (res);
9131                 gclass->type.type = res;
9132                 return res;
9133         }
9134
9135         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9136         return NULL;
9137 }
9138
9139
9140
9141 void
9142 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9143 {
9144         mono_reflection_type_get_handle (type);
9145 }
9146
9147 void
9148 mono_reflection_register_with_runtime (MonoReflectionType *type)
9149 {
9150         MonoType *res = mono_reflection_type_get_handle (type);
9151         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9152         MonoClass *class;
9153
9154         if (!res)
9155                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9156
9157         class = mono_class_from_mono_type (res);
9158
9159         mono_loader_lock (); /*same locking as mono_type_get_object*/
9160         mono_domain_lock (domain);
9161
9162         if (!class->image->dynamic) {
9163                 mono_class_setup_supertypes (class);
9164         } else {
9165                 if (!domain->type_hash)
9166                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9167                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9168                 mono_g_hash_table_insert (domain->type_hash, res, type);
9169         }
9170         mono_domain_unlock (domain);
9171         mono_loader_unlock ();
9172 }
9173
9174 /**
9175  * LOCKING: Assumes the loader lock is held.
9176  */
9177 static MonoMethodSignature*
9178 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9179         MonoMethodSignature *sig;
9180         int count, i;
9181
9182         count = parameters? mono_array_length (parameters): 0;
9183
9184         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9185         sig->param_count = count;
9186         sig->sentinelpos = -1; /* FIXME */
9187         for (i = 0; i < count; ++i)
9188                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9189         return sig;
9190 }
9191
9192 /**
9193  * LOCKING: Assumes the loader lock is held.
9194  */
9195 static MonoMethodSignature*
9196 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9197         MonoMethodSignature *sig;
9198
9199         sig = parameters_to_signature (image, ctor->parameters);
9200         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9201         sig->ret = &mono_defaults.void_class->byval_arg;
9202         return sig;
9203 }
9204
9205 /**
9206  * LOCKING: Assumes the loader lock is held.
9207  */
9208 static MonoMethodSignature*
9209 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9210         MonoMethodSignature *sig;
9211
9212         sig = parameters_to_signature (image, method->parameters);
9213         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9214         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9215         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9216         return sig;
9217 }
9218
9219 static MonoMethodSignature*
9220 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9221         MonoMethodSignature *sig;
9222
9223         sig = parameters_to_signature (NULL, method->parameters);
9224         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9225         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9226         sig->generic_param_count = 0;
9227         return sig;
9228 }
9229
9230 static void
9231 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9232 {
9233         MonoClass *klass = mono_object_class (prop);
9234         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9235                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9236                 *name = mono_string_to_utf8 (pb->name);
9237                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9238         } else {
9239                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9240                 *name = g_strdup (p->property->name);
9241                 if (p->property->get)
9242                         *type = mono_method_signature (p->property->get)->ret;
9243                 else
9244                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9245         }
9246 }
9247
9248 static void
9249 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9250 {
9251         MonoClass *klass = mono_object_class (field);
9252         if (strcmp (klass->name, "FieldBuilder") == 0) {
9253                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9254                 *name = mono_string_to_utf8 (fb->name);
9255                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9256         } else {
9257                 MonoReflectionField *f = (MonoReflectionField *)field;
9258                 *name = g_strdup (mono_field_get_name (f->field));
9259                 *type = f->field->type;
9260         }
9261 }
9262
9263 #else /* DISABLE_REFLECTION_EMIT */
9264
9265 void
9266 mono_reflection_register_with_runtime (MonoReflectionType *type)
9267 {
9268         /* This is empty */
9269 }
9270
9271 static gboolean
9272 is_sre_type_builder (MonoClass *class)
9273 {
9274         return FALSE;
9275 }
9276
9277 static gboolean
9278 is_sre_generic_instance (MonoClass *class)
9279 {
9280         return FALSE;
9281 }
9282
9283 static void
9284 init_type_builder_generics (MonoObject *type)
9285 {
9286 }
9287
9288 #endif /* !DISABLE_REFLECTION_EMIT */
9289
9290
9291 static gboolean
9292 is_sr_mono_field (MonoClass *class)
9293 {
9294         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9295 }
9296
9297 static gboolean
9298 is_sr_mono_property (MonoClass *class)
9299 {
9300         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9301 }
9302
9303 static gboolean
9304 is_sr_mono_method (MonoClass *class)
9305 {
9306         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9307 }
9308
9309 static gboolean
9310 is_sr_mono_cmethod (MonoClass *class)
9311 {
9312         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9313 }
9314
9315 static gboolean
9316 is_sr_mono_generic_method (MonoClass *class)
9317 {
9318         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9319 }
9320
9321 static gboolean
9322 is_sr_mono_generic_cmethod (MonoClass *class)
9323 {
9324         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9325 }
9326
9327 gboolean
9328 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9329 {
9330         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9331 }
9332
9333 static gboolean
9334 is_usertype (MonoReflectionType *ref)
9335 {
9336         MonoClass *class = mono_object_class (ref);
9337         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9338 }
9339
9340 static MonoReflectionType*
9341 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9342 {
9343         if (!type || type->type)
9344                 return type;
9345
9346         if (is_usertype (type)) {
9347                 type = mono_reflection_type_get_underlying_system_type (type);
9348                 if (is_usertype (type))
9349                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9350         }
9351
9352         return type;
9353 }
9354 /*
9355  * Encode a value in a custom attribute stream of bytes.
9356  * The value to encode is either supplied as an object in argument val
9357  * (valuetypes are boxed), or as a pointer to the data in the
9358  * argument argval.
9359  * @type represents the type of the value
9360  * @buffer is the start of the buffer
9361  * @p the current position in the buffer
9362  * @buflen contains the size of the buffer and is used to return the new buffer size
9363  * if this needs to be realloced.
9364  * @retbuffer and @retp return the start and the position of the buffer
9365  */
9366 static void
9367 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9368 {
9369         MonoTypeEnum simple_type;
9370         
9371         if ((p-buffer) + 10 >= *buflen) {
9372                 char *newbuf;
9373                 *buflen *= 2;
9374                 newbuf = g_realloc (buffer, *buflen);
9375                 p = newbuf + (p-buffer);
9376                 buffer = newbuf;
9377         }
9378         if (!argval)
9379                 argval = ((char*)arg + sizeof (MonoObject));
9380         simple_type = type->type;
9381 handle_enum:
9382         switch (simple_type) {
9383         case MONO_TYPE_BOOLEAN:
9384         case MONO_TYPE_U1:
9385         case MONO_TYPE_I1:
9386                 *p++ = *argval;
9387                 break;
9388         case MONO_TYPE_CHAR:
9389         case MONO_TYPE_U2:
9390         case MONO_TYPE_I2:
9391                 swap_with_size (p, argval, 2, 1);
9392                 p += 2;
9393                 break;
9394         case MONO_TYPE_U4:
9395         case MONO_TYPE_I4:
9396         case MONO_TYPE_R4:
9397                 swap_with_size (p, argval, 4, 1);
9398                 p += 4;
9399                 break;
9400         case MONO_TYPE_R8:
9401 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9402                 p [0] = argval [4];
9403                 p [1] = argval [5];
9404                 p [2] = argval [6];
9405                 p [3] = argval [7];
9406                 p [4] = argval [0];
9407                 p [5] = argval [1];
9408                 p [6] = argval [2];
9409                 p [7] = argval [3];
9410 #else
9411                 swap_with_size (p, argval, 8, 1);
9412 #endif
9413                 p += 8;
9414                 break;
9415         case MONO_TYPE_U8:
9416         case MONO_TYPE_I8:
9417                 swap_with_size (p, argval, 8, 1);
9418                 p += 8;
9419                 break;
9420         case MONO_TYPE_VALUETYPE:
9421                 if (type->data.klass->enumtype) {
9422                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9423                         goto handle_enum;
9424                 } else {
9425                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9426                 }
9427                 break;
9428         case MONO_TYPE_STRING: {
9429                 char *str;
9430                 guint32 slen;
9431                 if (!arg) {
9432                         *p++ = 0xFF;
9433                         break;
9434                 }
9435                 str = mono_string_to_utf8 ((MonoString*)arg);
9436                 slen = strlen (str);
9437                 if ((p-buffer) + 10 + slen >= *buflen) {
9438                         char *newbuf;
9439                         *buflen *= 2;
9440                         *buflen += slen;
9441                         newbuf = g_realloc (buffer, *buflen);
9442                         p = newbuf + (p-buffer);
9443                         buffer = newbuf;
9444                 }
9445                 mono_metadata_encode_value (slen, p, &p);
9446                 memcpy (p, str, slen);
9447                 p += slen;
9448                 g_free (str);
9449                 break;
9450         }
9451         case MONO_TYPE_CLASS: {
9452                 char *str;
9453                 guint32 slen;
9454                 if (!arg) {
9455                         *p++ = 0xFF;
9456                         break;
9457                 }
9458 handle_type:
9459                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9460                 slen = strlen (str);
9461                 if ((p-buffer) + 10 + slen >= *buflen) {
9462                         char *newbuf;
9463                         *buflen *= 2;
9464                         *buflen += slen;
9465                         newbuf = g_realloc (buffer, *buflen);
9466                         p = newbuf + (p-buffer);
9467                         buffer = newbuf;
9468                 }
9469                 mono_metadata_encode_value (slen, p, &p);
9470                 memcpy (p, str, slen);
9471                 p += slen;
9472                 g_free (str);
9473                 break;
9474         }
9475         case MONO_TYPE_SZARRAY: {
9476                 int len, i;
9477                 MonoClass *eclass, *arg_eclass;
9478
9479                 if (!arg) {
9480                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9481                         break;
9482                 }
9483                 len = mono_array_length ((MonoArray*)arg);
9484                 *p++ = len & 0xff;
9485                 *p++ = (len >> 8) & 0xff;
9486                 *p++ = (len >> 16) & 0xff;
9487                 *p++ = (len >> 24) & 0xff;
9488                 *retp = p;
9489                 *retbuffer = buffer;
9490                 eclass = type->data.klass;
9491                 arg_eclass = mono_object_class (arg)->element_class;
9492
9493                 if (!eclass) {
9494                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9495                         eclass = mono_defaults.object_class;
9496                 }
9497                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9498                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9499                         int elsize = mono_class_array_element_size (arg_eclass);
9500                         for (i = 0; i < len; ++i) {
9501                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9502                                 elptr += elsize;
9503                         }
9504                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9505                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9506                         int elsize = mono_class_array_element_size (eclass);
9507                         for (i = 0; i < len; ++i) {
9508                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9509                                 elptr += elsize;
9510                         }
9511                 } else {
9512                         for (i = 0; i < len; ++i) {
9513                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9514                         }
9515                 }
9516                 break;
9517         }
9518         case MONO_TYPE_OBJECT: {
9519                 MonoClass *klass;
9520                 char *str;
9521                 guint32 slen;
9522
9523                 /*
9524                  * The parameter type is 'object' but the type of the actual
9525                  * argument is not. So we have to add type information to the blob
9526                  * too. This is completely undocumented in the spec.
9527                  */
9528
9529                 if (arg == NULL) {
9530                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9531                         *p++ = 0xFF;
9532                         break;
9533                 }
9534                 
9535                 klass = mono_object_class (arg);
9536
9537                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9538                         *p++ = 0x50;
9539                         goto handle_type;
9540                 } else if (klass->enumtype) {
9541                         *p++ = 0x55;
9542                 } else if (klass == mono_defaults.string_class) {
9543                         simple_type = MONO_TYPE_STRING;
9544                         *p++ = 0x0E;
9545                         goto handle_enum;
9546                 } else if (klass->rank == 1) {
9547                         *p++ = 0x1D;
9548                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9549                                 /* See Partition II, Appendix B3 */
9550                                 *p++ = 0x51;
9551                         else
9552                                 *p++ = klass->element_class->byval_arg.type;
9553                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9554                         break;
9555                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9556                         *p++ = simple_type = klass->byval_arg.type;
9557                         goto handle_enum;
9558                 } else {
9559                         g_error ("unhandled type in custom attr");
9560                 }
9561                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9562                 slen = strlen (str);
9563                 if ((p-buffer) + 10 + slen >= *buflen) {
9564                         char *newbuf;
9565                         *buflen *= 2;
9566                         *buflen += slen;
9567                         newbuf = g_realloc (buffer, *buflen);
9568                         p = newbuf + (p-buffer);
9569                         buffer = newbuf;
9570                 }
9571                 mono_metadata_encode_value (slen, p, &p);
9572                 memcpy (p, str, slen);
9573                 p += slen;
9574                 g_free (str);
9575                 simple_type = mono_class_enum_basetype (klass)->type;
9576                 goto handle_enum;
9577         }
9578         default:
9579                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9580         }
9581         *retp = p;
9582         *retbuffer = buffer;
9583 }
9584
9585 static void
9586 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9587 {
9588         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9589                 char *str = type_get_qualified_name (type, NULL);
9590                 int slen = strlen (str);
9591
9592                 *p++ = 0x55;
9593                 /*
9594                  * This seems to be optional...
9595                  * *p++ = 0x80;
9596                  */
9597                 mono_metadata_encode_value (slen, p, &p);
9598                 memcpy (p, str, slen);
9599                 p += slen;
9600                 g_free (str);
9601         } else if (type->type == MONO_TYPE_OBJECT) {
9602                 *p++ = 0x51;
9603         } else if (type->type == MONO_TYPE_CLASS) {
9604                 /* it should be a type: encode_cattr_value () has the check */
9605                 *p++ = 0x50;
9606         } else {
9607                 mono_metadata_encode_value (type->type, p, &p);
9608                 if (type->type == MONO_TYPE_SZARRAY)
9609                         /* See the examples in Partition VI, Annex B */
9610                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9611         }
9612
9613         *retp = p;
9614 }
9615
9616 #ifndef DISABLE_REFLECTION_EMIT
9617 static void
9618 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9619 {
9620         int len;
9621         /* Preallocate a large enough buffer */
9622         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9623                 char *str = type_get_qualified_name (type, NULL);
9624                 len = strlen (str);
9625                 g_free (str);
9626         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9627                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9628                 len = strlen (str);
9629                 g_free (str);
9630         } else {
9631                 len = 0;
9632         }
9633         len += strlen (name);
9634
9635         if ((p-buffer) + 20 + len >= *buflen) {
9636                 char *newbuf;
9637                 *buflen *= 2;
9638                 *buflen += len;
9639                 newbuf = g_realloc (buffer, *buflen);
9640                 p = newbuf + (p-buffer);
9641                 buffer = newbuf;
9642         }
9643
9644         encode_field_or_prop_type (type, p, &p);
9645
9646         len = strlen (name);
9647         mono_metadata_encode_value (len, p, &p);
9648         memcpy (p, name, len);
9649         p += len;
9650         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9651         *retp = p;
9652         *retbuffer = buffer;
9653 }
9654
9655 /*
9656  * mono_reflection_get_custom_attrs_blob:
9657  * @ctor: custom attribute constructor
9658  * @ctorArgs: arguments o the constructor
9659  * @properties:
9660  * @propValues:
9661  * @fields:
9662  * @fieldValues:
9663  * 
9664  * Creates the blob of data that needs to be saved in the metadata and that represents
9665  * the custom attributed described by @ctor, @ctorArgs etc.
9666  * Returns: a Byte array representing the blob of data.
9667  */
9668 MonoArray*
9669 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9670 {
9671         MonoArray *result;
9672         MonoMethodSignature *sig;
9673         MonoObject *arg;
9674         char *buffer, *p;
9675         guint32 buflen, i;
9676
9677         MONO_ARCH_SAVE_REGS;
9678
9679         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9680                 /* sig is freed later so allocate it in the heap */
9681                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9682         } else {
9683                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9684         }
9685
9686         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9687         buflen = 256;
9688         p = buffer = g_malloc (buflen);
9689         /* write the prolog */
9690         *p++ = 1;
9691         *p++ = 0;
9692         for (i = 0; i < sig->param_count; ++i) {
9693                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9694                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9695         }
9696         i = 0;
9697         if (properties)
9698                 i += mono_array_length (properties);
9699         if (fields)
9700                 i += mono_array_length (fields);
9701         *p++ = i & 0xff;
9702         *p++ = (i >> 8) & 0xff;
9703         if (properties) {
9704                 MonoObject *prop;
9705                 for (i = 0; i < mono_array_length (properties); ++i) {
9706                         MonoType *ptype;
9707                         char *pname;
9708
9709                         prop = mono_array_get (properties, gpointer, i);
9710                         get_prop_name_and_type (prop, &pname, &ptype);
9711                         *p++ = 0x54; /* PROPERTY signature */
9712                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9713                         g_free (pname);
9714                 }
9715         }
9716
9717         if (fields) {
9718                 MonoObject *field;
9719                 for (i = 0; i < mono_array_length (fields); ++i) {
9720                         MonoType *ftype;
9721                         char *fname;
9722
9723                         field = mono_array_get (fields, gpointer, i);
9724                         get_field_name_and_type (field, &fname, &ftype);
9725                         *p++ = 0x53; /* FIELD signature */
9726                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9727                         g_free (fname);
9728                 }
9729         }
9730
9731         g_assert (p - buffer <= buflen);
9732         buflen = p - buffer;
9733         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9734         p = mono_array_addr (result, char, 0);
9735         memcpy (p, buffer, buflen);
9736         g_free (buffer);
9737         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9738                 g_free (sig);
9739         return result;
9740 }
9741
9742 /*
9743  * mono_reflection_setup_internal_class:
9744  * @tb: a TypeBuilder object
9745  *
9746  * Creates a MonoClass that represents the TypeBuilder.
9747  * This is a trick that lets us simplify a lot of reflection code
9748  * (and will allow us to support Build and Run assemblies easier).
9749  */
9750 void
9751 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9752 {
9753         MonoError error;
9754         MonoClass *klass, *parent;
9755
9756         MONO_ARCH_SAVE_REGS;
9757
9758         RESOLVE_TYPE (tb->parent);
9759
9760         mono_loader_lock ();
9761
9762         if (tb->parent) {
9763                 /* check so we can compile corlib correctly */
9764                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9765                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9766                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9767                 } else {
9768                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9769                 }
9770         } else {
9771                 parent = NULL;
9772         }
9773         
9774         /* the type has already being created: it means we just have to change the parent */
9775         if (tb->type.type) {
9776                 klass = mono_class_from_mono_type (tb->type.type);
9777                 klass->parent = NULL;
9778                 /* fool mono_class_setup_parent */
9779                 klass->supertypes = NULL;
9780                 mono_class_setup_parent (klass, parent);
9781                 mono_class_setup_mono_type (klass);
9782                 mono_loader_unlock ();
9783                 return;
9784         }
9785
9786         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9787
9788         klass->image = &tb->module->dynamic_image->image;
9789
9790         klass->inited = 1; /* we lie to the runtime */
9791         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9792         if (!mono_error_ok (&error))
9793                 goto failure;
9794         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9795         if (!mono_error_ok (&error))
9796                 goto failure;
9797         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9798         klass->flags = tb->attrs;
9799         
9800         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9801
9802         klass->element_class = klass;
9803
9804         if (mono_class_get_ref_info (klass) == NULL) {
9805
9806                 mono_class_set_ref_info (klass, tb);
9807
9808                 /* Put into cache so mono_class_get () will find it.
9809                 Skip nested types as those should not be available on the global scope. */
9810                 if (!tb->nesting_type) {
9811                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9812                 } else {
9813                         klass->image->reflection_info_unregister_classes =
9814                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9815                 }
9816         } else {
9817                 g_assert (mono_class_get_ref_info (klass) == tb);
9818         }
9819
9820         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9821                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9822
9823         if (parent != NULL) {
9824                 mono_class_setup_parent (klass, parent);
9825         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9826                 const char *old_n = klass->name;
9827                 /* trick to get relative numbering right when compiling corlib */
9828                 klass->name = "BuildingObject";
9829                 mono_class_setup_parent (klass, mono_defaults.object_class);
9830                 klass->name = old_n;
9831         }
9832
9833         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9834                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9835                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9836                 klass->instance_size = sizeof (MonoObject);
9837                 klass->size_inited = 1;
9838                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9839         }
9840
9841         mono_class_setup_mono_type (klass);
9842
9843         mono_class_setup_supertypes (klass);
9844
9845         /*
9846          * FIXME: handle interfaces.
9847          */
9848
9849         tb->type.type = &klass->byval_arg;
9850
9851         if (tb->nesting_type) {
9852                 g_assert (tb->nesting_type->type);
9853                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9854         }
9855
9856         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9857
9858         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9859         
9860         mono_loader_unlock ();
9861         return;
9862
9863 failure:
9864         mono_loader_unlock ();
9865         mono_error_raise_exception (&error);
9866 }
9867
9868 /*
9869  * mono_reflection_setup_generic_class:
9870  * @tb: a TypeBuilder object
9871  *
9872  * Setup the generic class before adding the first generic parameter.
9873  */
9874 void
9875 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9876 {
9877 }
9878
9879 /*
9880  * mono_reflection_create_generic_class:
9881  * @tb: a TypeBuilder object
9882  *
9883  * Creates the generic class after all generic parameters have been added.
9884  */
9885 void
9886 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9887 {
9888         MonoClass *klass;
9889         int count, i;
9890
9891         MONO_ARCH_SAVE_REGS;
9892
9893         klass = mono_class_from_mono_type (tb->type.type);
9894
9895         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9896
9897         if (klass->generic_container || (count == 0))
9898                 return;
9899
9900         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9901
9902         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9903
9904         klass->generic_container->owner.klass = klass;
9905         klass->generic_container->type_argc = count;
9906         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9907
9908         klass->is_generic = 1;
9909
9910         for (i = 0; i < count; i++) {
9911                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9912                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9913                 klass->generic_container->type_params [i] = *param;
9914                 /*Make sure we are a diferent type instance */
9915                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9916                 klass->generic_container->type_params [i].info.pklass = NULL;
9917                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9918
9919                 g_assert (klass->generic_container->type_params [i].param.owner);
9920         }
9921
9922         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9923 }
9924
9925 /*
9926  * mono_reflection_create_internal_class:
9927  * @tb: a TypeBuilder object
9928  *
9929  * Actually create the MonoClass that is associated with the TypeBuilder.
9930  */
9931 void
9932 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9933 {
9934         MonoClass *klass;
9935
9936         MONO_ARCH_SAVE_REGS;
9937
9938         klass = mono_class_from_mono_type (tb->type.type);
9939
9940         mono_loader_lock ();
9941         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9942                 MonoReflectionFieldBuilder *fb;
9943                 MonoClass *ec;
9944                 MonoType *enum_basetype;
9945
9946                 g_assert (tb->fields != NULL);
9947                 g_assert (mono_array_length (tb->fields) >= 1);
9948
9949                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9950
9951                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9952                         mono_loader_unlock ();
9953                         return;
9954                 }
9955
9956                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9957                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9958                 if (!klass->element_class)
9959                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9960
9961                 /*
9962                  * get the element_class from the current corlib.
9963                  */
9964                 ec = default_class_from_mono_type (enum_basetype);
9965                 klass->instance_size = ec->instance_size;
9966                 klass->size_inited = 1;
9967                 /* 
9968                  * this is almost safe to do with enums and it's needed to be able
9969                  * to create objects of the enum type (for use in SetConstant).
9970                  */
9971                 /* FIXME: Does this mean enums can't have method overrides ? */
9972                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9973         }
9974         mono_loader_unlock ();
9975 }
9976
9977 static MonoMarshalSpec*
9978 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9979                                                                 MonoReflectionMarshal *minfo)
9980 {
9981         MonoMarshalSpec *res;
9982
9983         res = image_g_new0 (image, MonoMarshalSpec, 1);
9984         res->native = minfo->type;
9985
9986         switch (minfo->type) {
9987         case MONO_NATIVE_LPARRAY:
9988                 res->data.array_data.elem_type = minfo->eltype;
9989                 if (minfo->has_size) {
9990                         res->data.array_data.param_num = minfo->param_num;
9991                         res->data.array_data.num_elem = minfo->count;
9992                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9993                 }
9994                 else {
9995                         res->data.array_data.param_num = -1;
9996                         res->data.array_data.num_elem = -1;
9997                         res->data.array_data.elem_mult = -1;
9998                 }
9999                 break;
10000
10001         case MONO_NATIVE_BYVALTSTR:
10002         case MONO_NATIVE_BYVALARRAY:
10003                 res->data.array_data.num_elem = minfo->count;
10004                 break;
10005
10006         case MONO_NATIVE_CUSTOM:
10007                 if (minfo->marshaltyperef)
10008                         res->data.custom_data.custom_name =
10009                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10010                 if (minfo->mcookie)
10011                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10012                 break;
10013
10014         default:
10015                 break;
10016         }
10017
10018         return res;
10019 }
10020 #endif /* !DISABLE_REFLECTION_EMIT */
10021
10022 MonoReflectionMarshalAsAttribute*
10023 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10024                                                                                    MonoMarshalSpec *spec)
10025 {
10026         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10027         MonoReflectionMarshalAsAttribute *minfo;
10028         MonoType *mtype;
10029
10030         if (!System_Reflection_Emit_MarshalAsAttribute) {
10031                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10032                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10033                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10034         }
10035
10036         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10037         minfo->utype = spec->native;
10038
10039         switch (minfo->utype) {
10040         case MONO_NATIVE_LPARRAY:
10041                 minfo->array_subtype = spec->data.array_data.elem_type;
10042                 minfo->size_const = spec->data.array_data.num_elem;
10043                 if (spec->data.array_data.param_num != -1)
10044                         minfo->size_param_index = spec->data.array_data.param_num;
10045                 break;
10046
10047         case MONO_NATIVE_BYVALTSTR:
10048         case MONO_NATIVE_BYVALARRAY:
10049                 minfo->size_const = spec->data.array_data.num_elem;
10050                 break;
10051
10052         case MONO_NATIVE_CUSTOM:
10053                 if (spec->data.custom_data.custom_name) {
10054                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10055                         if (mtype)
10056                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10057
10058                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10059                 }
10060                 if (spec->data.custom_data.cookie)
10061                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10062                 break;
10063
10064         default:
10065                 break;
10066         }
10067
10068         return minfo;
10069 }
10070
10071 #ifndef DISABLE_REFLECTION_EMIT
10072 static MonoMethod*
10073 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10074                                          ReflectionMethodBuilder *rmb,
10075                                          MonoMethodSignature *sig)
10076 {
10077         MonoError error;
10078         MonoMethod *m;
10079         MonoMethodWrapper *wrapperm;
10080         MonoMarshalSpec **specs;
10081         MonoReflectionMethodAux *method_aux;
10082         MonoImage *image;
10083         gboolean dynamic;
10084         int i;
10085
10086         mono_error_init (&error);
10087         /*
10088          * Methods created using a MethodBuilder should have their memory allocated
10089          * inside the image mempool, while dynamic methods should have their memory
10090          * malloc'd.
10091          */
10092         dynamic = rmb->refs != NULL;
10093         image = dynamic ? NULL : klass->image;
10094
10095         if (!dynamic)
10096                 g_assert (!klass->generic_class);
10097
10098         mono_loader_lock ();
10099
10100         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10101                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10102                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10103         else
10104                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10105
10106         wrapperm = (MonoMethodWrapper*)m;
10107
10108         m->dynamic = dynamic;
10109         m->slot = -1;
10110         m->flags = rmb->attrs;
10111         m->iflags = rmb->iattrs;
10112         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10113         m->klass = klass;
10114         m->signature = sig;
10115         m->sre_method = TRUE;
10116         m->skip_visibility = rmb->skip_visibility;
10117         if (rmb->table_idx)
10118                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10119
10120         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10121                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10122                         m->string_ctor = 1;
10123
10124                 m->signature->pinvoke = 1;
10125         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10126                 m->signature->pinvoke = 1;
10127
10128                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10129
10130                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10131                 g_assert (mono_error_ok (&error));
10132                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10133                 g_assert (mono_error_ok (&error));
10134                 
10135                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10136
10137                 if (klass->image->dynamic)
10138                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10139
10140                 mono_loader_unlock ();
10141
10142                 return m;
10143         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10144                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10145                 MonoMethodHeader *header;
10146                 guint32 code_size;
10147                 gint32 max_stack, i;
10148                 gint32 num_locals = 0;
10149                 gint32 num_clauses = 0;
10150                 guint8 *code;
10151
10152                 if (rmb->ilgen) {
10153                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10154                         code_size = rmb->ilgen->code_len;
10155                         max_stack = rmb->ilgen->max_stack;
10156                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10157                         if (rmb->ilgen->ex_handlers)
10158                                 num_clauses = method_count_clauses (rmb->ilgen);
10159                 } else {
10160                         if (rmb->code) {
10161                                 code = mono_array_addr (rmb->code, guint8, 0);
10162                                 code_size = mono_array_length (rmb->code);
10163                                 /* we probably need to run a verifier on the code... */
10164                                 max_stack = 8; 
10165                         }
10166                         else {
10167                                 code = NULL;
10168                                 code_size = 0;
10169                                 max_stack = 8;
10170                         }
10171                 }
10172
10173                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10174                 header->code_size = code_size;
10175                 header->code = image_g_malloc (image, code_size);
10176                 memcpy ((char*)header->code, code, code_size);
10177                 header->max_stack = max_stack;
10178                 header->init_locals = rmb->init_locals;
10179                 header->num_locals = num_locals;
10180
10181                 for (i = 0; i < num_locals; ++i) {
10182                         MonoReflectionLocalBuilder *lb = 
10183                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10184
10185                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10186                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10187                 }
10188
10189                 header->num_clauses = num_clauses;
10190                 if (num_clauses) {
10191                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10192                                  rmb->ilgen, num_clauses);
10193                 }
10194
10195                 wrapperm->header = header;
10196         }
10197
10198         if (rmb->generic_params) {
10199                 int count = mono_array_length (rmb->generic_params);
10200                 MonoGenericContainer *container = rmb->generic_container;
10201
10202                 g_assert (container);
10203
10204                 container->type_argc = count;
10205                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10206                 container->owner.method = m;
10207
10208                 m->is_generic = TRUE;
10209                 mono_method_set_generic_container (m, container);
10210
10211                 for (i = 0; i < count; i++) {
10212                         MonoReflectionGenericParam *gp =
10213                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10214                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10215                         container->type_params [i] = *param;
10216                 }
10217
10218                 /*
10219                  * The method signature might have pointers to generic parameters that belong to other methods.
10220                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10221                  * generic parameters.
10222                  */
10223                 for (i = 0; i < m->signature->param_count; ++i) {
10224                         MonoType *t = m->signature->params [i];
10225                         if (t->type == MONO_TYPE_MVAR) {
10226                                 MonoGenericParam *gparam =  t->data.generic_param;
10227                                 if (gparam->num < count) {
10228                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10229                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10230                                 }
10231
10232                         }
10233                 }
10234
10235                 if (klass->generic_container) {
10236                         container->parent = klass->generic_container;
10237                         container->context.class_inst = klass->generic_container->context.class_inst;
10238                 }
10239                 container->context.method_inst = mono_get_shared_generic_inst (container);
10240         }
10241
10242         if (rmb->refs) {
10243                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10244                 int i;
10245                 void **data;
10246
10247                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10248
10249                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10250                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10251                 for (i = 0; i < rmb->nrefs; ++i)
10252                         data [i + 1] = rmb->refs [i];
10253         }
10254
10255         method_aux = NULL;
10256
10257         /* Parameter info */
10258         if (rmb->pinfo) {
10259                 if (!method_aux)
10260                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10261                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10262                 for (i = 0; i <= m->signature->param_count; ++i) {
10263                         MonoReflectionParamBuilder *pb;
10264                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10265                                 if ((i > 0) && (pb->attrs)) {
10266                                         /* Make a copy since it might point to a shared type structure */
10267                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10268                                         m->signature->params [i - 1]->attrs = pb->attrs;
10269                                 }
10270
10271                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10272                                         MonoDynamicImage *assembly;
10273                                         guint32 idx, def_type, len;
10274                                         char *p;
10275                                         const char *p2;
10276
10277                                         if (!method_aux->param_defaults) {
10278                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10279                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10280                                         }
10281                                         assembly = (MonoDynamicImage*)klass->image;
10282                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10283                                         /* Copy the data from the blob since it might get realloc-ed */
10284                                         p = assembly->blob.data + idx;
10285                                         len = mono_metadata_decode_blob_size (p, &p2);
10286                                         len += p2 - p;
10287                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10288                                         method_aux->param_default_types [i] = def_type;
10289                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10290                                 }
10291
10292                                 if (pb->name) {
10293                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10294                                         g_assert (mono_error_ok (&error));
10295                                 }
10296                                 if (pb->cattrs) {
10297                                         if (!method_aux->param_cattr)
10298                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10299                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10300                                 }
10301                         }
10302                 }
10303         }
10304
10305         /* Parameter marshalling */
10306         specs = NULL;
10307         if (rmb->pinfo)         
10308                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10309                         MonoReflectionParamBuilder *pb;
10310                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10311                                 if (pb->marshal_info) {
10312                                         if (specs == NULL)
10313                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10314                                         specs [pb->position] = 
10315                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10316                                 }
10317                         }
10318                 }
10319         if (specs != NULL) {
10320                 if (!method_aux)
10321                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10322                 method_aux->param_marshall = specs;
10323         }
10324
10325         if (klass->image->dynamic && method_aux)
10326                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10327
10328         mono_loader_unlock ();
10329
10330         return m;
10331 }       
10332
10333 static MonoMethod*
10334 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10335 {
10336         ReflectionMethodBuilder rmb;
10337         MonoMethodSignature *sig;
10338
10339         mono_loader_lock ();
10340         sig = ctor_builder_to_signature (klass->image, mb);
10341         mono_loader_unlock ();
10342
10343         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10344
10345         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10346         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10347
10348         /* If we are in a generic class, we might be called multiple times from inflate_method */
10349         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10350                 /* ilgen is no longer needed */
10351                 mb->ilgen = NULL;
10352         }
10353
10354         return mb->mhandle;
10355 }
10356
10357 static MonoMethod*
10358 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10359 {
10360         ReflectionMethodBuilder rmb;
10361         MonoMethodSignature *sig;
10362
10363         mono_loader_lock ();
10364         sig = method_builder_to_signature (klass->image, mb);
10365         mono_loader_unlock ();
10366
10367         reflection_methodbuilder_from_method_builder (&rmb, mb);
10368
10369         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10370         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10371
10372         /* If we are in a generic class, we might be called multiple times from inflate_method */
10373         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10374                 /* ilgen is no longer needed */
10375                 mb->ilgen = NULL;
10376         }
10377         return mb->mhandle;
10378 }
10379
10380 static MonoClassField*
10381 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10382 {
10383         MonoClassField *field;
10384         MonoType *custom;
10385         MonoError error;
10386
10387         field = g_new0 (MonoClassField, 1);
10388
10389         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10390         g_assert (mono_error_ok (&error));
10391         if (fb->attrs || fb->modreq || fb->modopt) {
10392                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10393                 field->type->attrs = fb->attrs;
10394
10395                 g_assert (klass->image->dynamic);
10396                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10397                 g_free (field->type);
10398                 field->type = mono_metadata_type_dup (klass->image, custom);
10399                 g_free (custom);
10400         } else {
10401                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10402         }
10403         if (fb->offset != -1)
10404                 field->offset = fb->offset;
10405         field->parent = klass;
10406         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10407
10408         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10409
10410         return field;
10411 }
10412 #endif
10413
10414 MonoType*
10415 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10416 {
10417         MonoClass *klass;
10418         MonoReflectionTypeBuilder *tb = NULL;
10419         gboolean is_dynamic = FALSE;
10420         MonoDomain *domain;
10421         MonoClass *geninst;
10422
10423         mono_loader_lock ();
10424
10425         domain = mono_object_domain (type);
10426
10427         if (is_sre_type_builder (mono_object_class (type))) {
10428                 tb = (MonoReflectionTypeBuilder *) type;
10429
10430                 is_dynamic = TRUE;
10431         } else if (is_sre_generic_instance (mono_object_class (type))) {
10432                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10433                 MonoReflectionType *gtd = rgi->generic_type;
10434
10435                 if (is_sre_type_builder (mono_object_class (gtd))) {
10436                         tb = (MonoReflectionTypeBuilder *)gtd;
10437                         is_dynamic = TRUE;
10438                 }
10439         }
10440
10441         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10442         if (tb && tb->generic_container)
10443                 mono_reflection_create_generic_class (tb);
10444
10445         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10446         if (!klass->generic_container) {
10447                 mono_loader_unlock ();
10448                 return NULL;
10449         }
10450
10451         if (klass->wastypebuilder) {
10452                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10453
10454                 is_dynamic = TRUE;
10455         }
10456
10457         mono_loader_unlock ();
10458
10459         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10460
10461         return &geninst->byval_arg;
10462 }
10463
10464 MonoClass*
10465 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10466 {
10467         MonoGenericClass *gclass;
10468         MonoGenericInst *inst;
10469
10470         g_assert (klass->generic_container);
10471
10472         inst = mono_metadata_get_generic_inst (type_argc, types);
10473         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10474
10475         return mono_generic_class_get_class (gclass);
10476 }
10477
10478 MonoReflectionMethod*
10479 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10480 {
10481         MonoClass *klass;
10482         MonoMethod *method, *inflated;
10483         MonoMethodInflated *imethod;
10484         MonoGenericContext tmp_context;
10485         MonoGenericInst *ginst;
10486         MonoType **type_argv;
10487         int count, i;
10488
10489         MONO_ARCH_SAVE_REGS;
10490
10491         /*FIXME but this no longer should happen*/
10492         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10493 #ifndef DISABLE_REFLECTION_EMIT
10494                 MonoReflectionMethodBuilder *mb = NULL;
10495                 MonoReflectionTypeBuilder *tb;
10496                 MonoClass *klass;
10497
10498                 mb = (MonoReflectionMethodBuilder *) rmethod;
10499                 tb = (MonoReflectionTypeBuilder *) mb->type;
10500                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10501
10502                 method = methodbuilder_to_mono_method (klass, mb);
10503 #else
10504                 g_assert_not_reached ();
10505                 method = NULL;
10506 #endif
10507         } else {
10508                 method = rmethod->method;
10509         }
10510
10511         klass = method->klass;
10512
10513         if (method->is_inflated)
10514                 method = ((MonoMethodInflated *) method)->declaring;
10515
10516         count = mono_method_signature (method)->generic_param_count;
10517         if (count != mono_array_length (types))
10518                 return NULL;
10519
10520         type_argv = g_new0 (MonoType *, count);
10521         for (i = 0; i < count; i++) {
10522                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10523                 type_argv [i] = mono_reflection_type_get_handle (garg);
10524         }
10525         ginst = mono_metadata_get_generic_inst (count, type_argv);
10526         g_free (type_argv);
10527
10528         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10529         tmp_context.method_inst = ginst;
10530
10531         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10532         imethod = (MonoMethodInflated *) inflated;
10533
10534         /*FIXME but I think this is no longer necessary*/
10535         if (method->klass->image->dynamic) {
10536                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10537                 /*
10538                  * This table maps metadata structures representing inflated methods/fields
10539                  * to the reflection objects representing their generic definitions.
10540                  */
10541                 mono_loader_lock ();
10542                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10543                 mono_loader_unlock ();
10544         }
10545
10546         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10547                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10548         
10549         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10550 }
10551
10552 #ifndef DISABLE_REFLECTION_EMIT
10553
10554 static MonoMethod *
10555 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10556 {
10557         MonoMethodInflated *imethod;
10558         MonoGenericContext *context;
10559         int i;
10560
10561         /*
10562          * With generic code sharing the klass might not be inflated.
10563          * This can happen because classes inflated with their own
10564          * type arguments are "normalized" to the uninflated class.
10565          */
10566         if (!klass->generic_class)
10567                 return method;
10568
10569         context = mono_class_get_context (klass);
10570
10571         if (klass->method.count && klass->methods) {
10572                 /* Find the already created inflated method */
10573                 for (i = 0; i < klass->method.count; ++i) {
10574                         g_assert (klass->methods [i]->is_inflated);
10575                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10576                                 break;
10577                 }
10578                 g_assert (i < klass->method.count);
10579                 imethod = (MonoMethodInflated*)klass->methods [i];
10580         } else {
10581                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10582         }
10583
10584         if (method->is_generic && method->klass->image->dynamic) {
10585                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10586
10587                 mono_loader_lock ();
10588                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10589                 mono_loader_unlock ();
10590         }
10591         return (MonoMethod *) imethod;
10592 }
10593
10594 static MonoMethod *
10595 inflate_method (MonoReflectionType *type, MonoObject *obj)
10596 {
10597         MonoMethod *method;
10598         MonoClass *gklass;
10599
10600         MonoClass *type_class = mono_object_class (type);
10601
10602         if (is_sre_generic_instance (type_class)) {
10603                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10604                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10605         } else if (is_sre_type_builder (type_class)) {
10606                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10607         } else if (type->type) {
10608                 gklass = mono_class_from_mono_type (type->type);
10609                 gklass = mono_class_get_generic_type_definition (gklass);
10610         } else {
10611                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10612         }
10613
10614         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10615                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10616                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10617                 else
10618                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10619         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10620                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10621         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10622                 method = ((MonoReflectionMethod *) obj)->method;
10623         else {
10624                 method = NULL; /* prevent compiler warning */
10625                 g_error ("can't handle type %s", obj->vtable->klass->name);
10626         }
10627
10628         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10629 }
10630
10631 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10632 void
10633 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
10634 {
10635         MonoGenericClass *gclass;
10636         MonoDynamicGenericClass *dgclass;
10637         MonoClass *klass, *gklass;
10638         MonoType *gtype;
10639         int i;
10640
10641         MONO_ARCH_SAVE_REGS;
10642
10643         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10644         klass = mono_class_from_mono_type (gtype);
10645         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10646         gclass = gtype->data.generic_class;
10647
10648         if (!gclass->is_dynamic)
10649                 return;
10650
10651         dgclass = (MonoDynamicGenericClass *) gclass;
10652
10653         if (dgclass->initialized)
10654                 return;
10655
10656         gklass = gclass->container_class;
10657         mono_class_init (gklass);
10658
10659         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10660
10661         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10662         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10663         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10664
10665         for (i = 0; i < dgclass->count_fields; i++) {
10666                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10667                 MonoClassField *field, *inflated_field = NULL;
10668
10669                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10670                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10671                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10672                         field = ((MonoReflectionField *) obj)->field;
10673                 else {
10674                         field = NULL; /* prevent compiler warning */
10675                         g_assert_not_reached ();
10676                 }
10677
10678                 dgclass->fields [i] = *field;
10679                 dgclass->fields [i].parent = klass;
10680                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10681                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10682                 dgclass->field_generic_types [i] = field->type;
10683                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10684                 dgclass->field_objects [i] = obj;
10685
10686                 if (inflated_field) {
10687                         g_free (inflated_field);
10688                 } else {
10689                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10690                 }
10691         }
10692
10693         dgclass->initialized = TRUE;
10694 }
10695
10696 void
10697 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10698 {
10699         MonoDynamicGenericClass *dgclass;
10700         int i;
10701
10702         g_assert (gclass->is_dynamic);
10703
10704         dgclass = (MonoDynamicGenericClass *)gclass;
10705
10706         for (i = 0; i < dgclass->count_fields; ++i) {
10707                 MonoClassField *field = dgclass->fields + i;
10708                 mono_metadata_free_type (field->type);
10709                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10710         }
10711 }
10712
10713 static void
10714 fix_partial_generic_class (MonoClass *klass)
10715 {
10716         MonoClass *gklass = klass->generic_class->container_class;
10717         MonoDynamicGenericClass *dgclass;
10718         int i;
10719
10720         if (klass->wastypebuilder)
10721                 return;
10722
10723         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10724         if (klass->parent != gklass->parent) {
10725                 MonoError error;
10726                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10727                 if (mono_error_ok (&error)) {
10728                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10729                         mono_metadata_free_type (parent_type);
10730                         if (parent != klass->parent) {
10731                                 /*fool mono_class_setup_parent*/
10732                                 klass->supertypes = NULL;
10733                                 mono_class_setup_parent (klass, parent);
10734                         }
10735                 } else {
10736                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10737                         mono_error_cleanup (&error);
10738                         if (gklass->wastypebuilder)
10739                                 klass->wastypebuilder = TRUE;
10740                         return;
10741                 }
10742         }
10743
10744         if (!dgclass->initialized)
10745                 return;
10746
10747         if (klass->method.count != gklass->method.count) {
10748                 klass->method.count = gklass->method.count;
10749                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10750
10751                 for (i = 0; i < klass->method.count; i++) {
10752                         klass->methods [i] = mono_class_inflate_generic_method_full (
10753                                 gklass->methods [i], klass, mono_class_get_context (klass));
10754                 }
10755         }
10756
10757         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10758                 klass->interface_count = gklass->interface_count;
10759                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10760                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10761
10762                 for (i = 0; i < gklass->interface_count; ++i) {
10763                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10764                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10765                         mono_metadata_free_type (iface_type);
10766
10767                         ensure_runtime_vtable (klass->interfaces [i]);
10768                 }
10769                 klass->interfaces_inited = 1;
10770         }
10771
10772         if (klass->field.count != gklass->field.count) {
10773                 klass->field.count = gklass->field.count;
10774                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10775
10776                 for (i = 0; i < klass->field.count; i++) {
10777                         klass->fields [i] = gklass->fields [i];
10778                         klass->fields [i].parent = klass;
10779                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10780                 }
10781         }
10782
10783         /*We can only finish with this klass once it's parent has as well*/
10784         if (gklass->wastypebuilder)
10785                 klass->wastypebuilder = TRUE;
10786         return;
10787 }
10788
10789 static void
10790 ensure_generic_class_runtime_vtable (MonoClass *klass)
10791 {
10792         MonoClass *gklass = klass->generic_class->container_class;
10793
10794         ensure_runtime_vtable (gklass); 
10795
10796         fix_partial_generic_class (klass);
10797 }
10798
10799 static void
10800 ensure_runtime_vtable (MonoClass *klass)
10801 {
10802         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10803         int i, num, j;
10804
10805         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10806                 return;
10807         if (klass->parent)
10808                 ensure_runtime_vtable (klass->parent);
10809
10810         if (tb) {
10811                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10812                 num += tb->num_methods;
10813                 klass->method.count = num;
10814                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10815                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10816                 for (i = 0; i < num; ++i)
10817                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10818                 num = tb->num_methods;
10819                 j = i;
10820                 for (i = 0; i < num; ++i)
10821                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10822         
10823                 if (tb->interfaces) {
10824                         klass->interface_count = mono_array_length (tb->interfaces);
10825                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10826                         for (i = 0; i < klass->interface_count; ++i) {
10827                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10828                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10829                                 ensure_runtime_vtable (klass->interfaces [i]);
10830                         }
10831                         klass->interfaces_inited = 1;
10832                 }
10833         } else if (klass->generic_class){
10834                 ensure_generic_class_runtime_vtable (klass);
10835         }
10836
10837         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10838                 int slot_num = 0;
10839                 for (i = 0; i < klass->method.count; ++i) {
10840                         MonoMethod *im = klass->methods [i];
10841                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10842                                 im->slot = slot_num++;
10843                 }
10844                 
10845                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10846                 mono_class_setup_interface_offsets (klass);
10847                 mono_class_setup_interface_id (klass);
10848         }
10849
10850         /*
10851          * The generic vtable is needed even if image->run is not set since some
10852          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10853          * method->slot being defined.
10854          */
10855
10856         /* 
10857          * tb->methods could not be freed since it is used for determining 
10858          * overrides during dynamic vtable construction.
10859          */
10860 }
10861
10862 static MonoMethod*
10863 mono_reflection_method_get_handle (MonoObject *method)
10864 {
10865         MonoClass *class = mono_object_class (method);
10866         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10867                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10868                 return sr_method->method;
10869         }
10870         if (is_sre_method_builder (class)) {
10871                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10872                 return mb->mhandle;
10873         }
10874         if (is_sre_method_on_tb_inst (class)) {
10875                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10876                 MonoMethod *result;
10877                 /*FIXME move this to a proper method and unify with resolve_object*/
10878                 if (m->method_args) {
10879                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10880                 } else {
10881                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10882                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10883                         MonoMethod *mono_method;
10884
10885                         if (is_sre_method_builder (mono_object_class (m->mb)))
10886                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10887                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10888                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10889                         else
10890                                 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)));
10891
10892                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10893                 }
10894                 return result;
10895         }
10896
10897         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10898         return NULL;
10899 }
10900
10901 void
10902 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10903 {
10904         MonoReflectionTypeBuilder *tb;
10905         int i, j, onum;
10906         MonoReflectionMethod *m;
10907
10908         *overrides = NULL;
10909         *num_overrides = 0;
10910
10911         g_assert (klass->image->dynamic);
10912
10913         if (!mono_class_get_ref_info (klass))
10914                 return;
10915
10916         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10917
10918         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10919
10920         onum = 0;
10921         if (tb->methods) {
10922                 for (i = 0; i < tb->num_methods; ++i) {
10923                         MonoReflectionMethodBuilder *mb = 
10924                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10925                         if (mb->override_methods)
10926                                 onum += mono_array_length (mb->override_methods);
10927                 }
10928         }
10929
10930         if (onum) {
10931                 *overrides = g_new0 (MonoMethod*, onum * 2);
10932
10933                 onum = 0;
10934                 for (i = 0; i < tb->num_methods; ++i) {
10935                         MonoReflectionMethodBuilder *mb = 
10936                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10937                         if (mb->override_methods) {
10938                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
10939                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
10940
10941                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
10942                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
10943
10944                                         g_assert (mb->mhandle);
10945
10946                                         onum ++;
10947                                 }
10948                         }
10949                 }
10950         }
10951
10952         *num_overrides = onum;
10953 }
10954
10955 static void
10956 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10957 {
10958         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10959         MonoReflectionFieldBuilder *fb;
10960         MonoClassField *field;
10961         MonoImage *image = klass->image;
10962         const char *p, *p2;
10963         int i;
10964         guint32 len, idx, real_size = 0;
10965
10966         klass->field.count = tb->num_fields;
10967         klass->field.first = 0;
10968
10969         mono_error_init (error);
10970
10971         if (tb->class_size) {
10972                 if ((tb->packing_size & 0xfffffff0) != 0) {
10973                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", klass->name, tb->packing_size);
10974                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10975                         return;
10976                 }
10977                 klass->packing_size = tb->packing_size;
10978                 real_size = klass->instance_size + tb->class_size;
10979         }
10980
10981         if (!klass->field.count) {
10982                 klass->instance_size = MAX (klass->instance_size, real_size);
10983                 return;
10984         }
10985         
10986         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10987         mono_class_alloc_ext (klass);
10988         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10989         /*
10990         This is, guess what, a hack.
10991         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10992         On the static path no field class is resolved, only types are built. This is the right thing to do
10993         but we suck.
10994         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10995         */
10996         klass->size_inited = 1;
10997
10998         for (i = 0; i < klass->field.count; ++i) {
10999                 MonoArray *rva_data;
11000                 fb = mono_array_get (tb->fields, gpointer, i);
11001                 field = &klass->fields [i];
11002                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11003                 if (!mono_error_ok (error))
11004                         return;
11005                 if (fb->attrs) {
11006                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11007                         field->type->attrs = fb->attrs;
11008                 } else {
11009                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11010                 }
11011
11012                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11013                         char *base = mono_array_addr (rva_data, char, 0);
11014                         size_t size = mono_array_length (rva_data);
11015                         char *data = mono_image_alloc (klass->image, size);
11016                         memcpy (data, base, size);
11017                         klass->ext->field_def_values [i].data = data;
11018                 }
11019                 if (fb->offset != -1)
11020                         field->offset = fb->offset;
11021                 field->parent = klass;
11022                 fb->handle = field;
11023                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11024
11025                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11026                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11027                 }
11028                 if (fb->def_value) {
11029                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11030                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11031                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11032                         /* Copy the data from the blob since it might get realloc-ed */
11033                         p = assembly->blob.data + idx;
11034                         len = mono_metadata_decode_blob_size (p, &p2);
11035                         len += p2 - p;
11036                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11037                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11038                 }
11039         }
11040
11041         klass->instance_size = MAX (klass->instance_size, real_size);
11042         mono_class_layout_fields (klass);
11043 }
11044
11045 static void
11046 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11047 {
11048         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11049         MonoReflectionPropertyBuilder *pb;
11050         MonoImage *image = klass->image;
11051         MonoProperty *properties;
11052         int i;
11053
11054         mono_error_init (error);
11055
11056         if (!klass->ext)
11057                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11058
11059         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11060         klass->ext->property.first = 0;
11061
11062         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11063         klass->ext->properties = properties;
11064         for (i = 0; i < klass->ext->property.count; ++i) {
11065                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11066                 properties [i].parent = klass;
11067                 properties [i].attrs = pb->attrs;
11068                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11069                 if (!mono_error_ok (error))
11070                         return;
11071                 if (pb->get_method)
11072                         properties [i].get = pb->get_method->mhandle;
11073                 if (pb->set_method)
11074                         properties [i].set = pb->set_method->mhandle;
11075
11076                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11077                 if (pb->def_value) {
11078                         guint32 len, idx;
11079                         const char *p, *p2;
11080                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11081                         if (!klass->ext->prop_def_values)
11082                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11083                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11084                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11085                         /* Copy the data from the blob since it might get realloc-ed */
11086                         p = assembly->blob.data + idx;
11087                         len = mono_metadata_decode_blob_size (p, &p2);
11088                         len += p2 - p;
11089                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11090                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11091                 }
11092         }
11093 }
11094
11095 MonoReflectionEvent *
11096 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11097 {
11098         MonoEvent *event = g_new0 (MonoEvent, 1);
11099         MonoClass *klass;
11100
11101         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11102
11103         event->parent = klass;
11104         event->attrs = eb->attrs;
11105         event->name = mono_string_to_utf8 (eb->name);
11106         if (eb->add_method)
11107                 event->add = eb->add_method->mhandle;
11108         if (eb->remove_method)
11109                 event->remove = eb->remove_method->mhandle;
11110         if (eb->raise_method)
11111                 event->raise = eb->raise_method->mhandle;
11112
11113 #ifndef MONO_SMALL_CONFIG
11114         if (eb->other_methods) {
11115                 int j;
11116                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11117                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11118                         MonoReflectionMethodBuilder *mb = 
11119                                 mono_array_get (eb->other_methods,
11120                                                 MonoReflectionMethodBuilder*, j);
11121                         event->other [j] = mb->mhandle;
11122                 }
11123         }
11124 #endif
11125
11126         return mono_event_get_object (mono_object_domain (tb), klass, event);
11127 }
11128
11129 static void
11130 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11131 {
11132         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11133         MonoReflectionEventBuilder *eb;
11134         MonoImage *image = klass->image;
11135         MonoEvent *events;
11136         int i;
11137
11138         mono_error_init (error);
11139
11140         if (!klass->ext)
11141                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11142
11143         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11144         klass->ext->event.first = 0;
11145
11146         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11147         klass->ext->events = events;
11148         for (i = 0; i < klass->ext->event.count; ++i) {
11149                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11150                 events [i].parent = klass;
11151                 events [i].attrs = eb->attrs;
11152                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11153                 if (!mono_error_ok (error))
11154                         return;
11155                 if (eb->add_method)
11156                         events [i].add = eb->add_method->mhandle;
11157                 if (eb->remove_method)
11158                         events [i].remove = eb->remove_method->mhandle;
11159                 if (eb->raise_method)
11160                         events [i].raise = eb->raise_method->mhandle;
11161
11162 #ifndef MONO_SMALL_CONFIG
11163                 if (eb->other_methods) {
11164                         int j;
11165                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11166                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11167                                 MonoReflectionMethodBuilder *mb = 
11168                                         mono_array_get (eb->other_methods,
11169                                                                         MonoReflectionMethodBuilder*, j);
11170                                 events [i].other [j] = mb->mhandle;
11171                         }
11172                 }
11173 #endif
11174                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11175         }
11176 }
11177
11178 static gboolean
11179 remove_instantiations_of_and_ensure_contents (gpointer key,
11180                                                   gpointer value,
11181                                                   gpointer user_data)
11182 {
11183         MonoType *type = (MonoType*)key;
11184         MonoClass *klass = (MonoClass*)user_data;
11185
11186         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11187                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11188                 return TRUE;
11189         } else
11190                 return FALSE;
11191 }
11192
11193 static void
11194 check_array_for_usertypes (MonoArray *arr)
11195 {
11196         int i;
11197
11198         if (!arr)
11199                 return;
11200
11201         for (i = 0; i < mono_array_length (arr); ++i)
11202                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11203 }
11204
11205 MonoReflectionType*
11206 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11207 {
11208         MonoError error;
11209         MonoClass *klass;
11210         MonoDomain* domain;
11211         MonoReflectionType* res;
11212         int i, j;
11213
11214         MONO_ARCH_SAVE_REGS;
11215
11216         domain = mono_object_domain (tb);
11217         klass = mono_class_from_mono_type (tb->type.type);
11218
11219         /*
11220          * Check for user defined Type subclasses.
11221          */
11222         RESOLVE_TYPE (tb->parent);
11223         check_array_for_usertypes (tb->interfaces);
11224         if (tb->fields) {
11225                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11226                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11227                         if (fb) {
11228                                 RESOLVE_TYPE (fb->type);
11229                                 check_array_for_usertypes (fb->modreq);
11230                                 check_array_for_usertypes (fb->modopt);
11231                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11232                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11233                         }
11234                 }
11235         }
11236         if (tb->methods) {
11237                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11238                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11239                         if (mb) {
11240                                 RESOLVE_TYPE (mb->rtype);
11241                                 check_array_for_usertypes (mb->return_modreq);
11242                                 check_array_for_usertypes (mb->return_modopt);
11243                                 check_array_for_usertypes (mb->parameters);
11244                                 if (mb->param_modreq)
11245                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11246                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11247                                 if (mb->param_modopt)
11248                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11249                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11250                         }
11251                 }
11252         }
11253         if (tb->ctors) {
11254                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11255                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11256                         if (mb) {
11257                                 check_array_for_usertypes (mb->parameters);
11258                                 if (mb->param_modreq)
11259                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11260                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11261                                 if (mb->param_modopt)
11262                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11263                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11264                         }
11265                 }
11266         }
11267
11268         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11269
11270         /* 
11271          * we need to lock the domain because the lock will be taken inside
11272          * So, we need to keep the locking order correct.
11273          */
11274         mono_loader_lock ();
11275         mono_domain_lock (domain);
11276         if (klass->wastypebuilder) {
11277                 mono_domain_unlock (domain);
11278                 mono_loader_unlock ();
11279                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11280         }
11281         /*
11282          * Fields to set in klass:
11283          * the various flags: delegate/unicode/contextbound etc.
11284          */
11285         klass->flags = tb->attrs;
11286         klass->has_cctor = 1;
11287         klass->has_finalize = 1;
11288         klass->has_finalize_inited = 1;
11289
11290         /* fool mono_class_setup_parent */
11291         klass->supertypes = NULL;
11292         mono_class_setup_parent (klass, klass->parent);
11293         mono_class_setup_mono_type (klass);
11294
11295 #if 0
11296         if (!((MonoDynamicImage*)klass->image)->run) {
11297                 if (klass->generic_container) {
11298                         /* FIXME: The code below can't handle generic classes */
11299                         klass->wastypebuilder = TRUE;
11300                         mono_loader_unlock ();
11301                         mono_domain_unlock (domain);
11302                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11303                 }
11304         }
11305 #endif
11306
11307         /* enums are done right away */
11308         if (!klass->enumtype)
11309                 ensure_runtime_vtable (klass);
11310
11311         if (tb->subtypes) {
11312                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11313                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11314                         mono_class_alloc_ext (klass);
11315                         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)));
11316                 }
11317         }
11318
11319         klass->nested_classes_inited = TRUE;
11320
11321         /* fields and object layout */
11322         if (klass->parent) {
11323                 if (!klass->parent->size_inited)
11324                         mono_class_init (klass->parent);
11325                 klass->instance_size = klass->parent->instance_size;
11326                 klass->sizes.class_size = 0;
11327                 klass->min_align = klass->parent->min_align;
11328                 /* if the type has no fields we won't call the field_setup
11329                  * routine which sets up klass->has_references.
11330                  */
11331                 klass->has_references |= klass->parent->has_references;
11332         } else {
11333                 klass->instance_size = sizeof (MonoObject);
11334                 klass->min_align = 1;
11335         }
11336
11337         /* FIXME: handle packing_size and instance_size */
11338         typebuilder_setup_fields (klass, &error);
11339         if (!mono_error_ok (&error))
11340                 goto failure;
11341         typebuilder_setup_properties (klass, &error);
11342         if (!mono_error_ok (&error))
11343                 goto failure;
11344
11345         typebuilder_setup_events (klass, &error);
11346         if (!mono_error_ok (&error))
11347                 goto failure;
11348
11349         klass->wastypebuilder = TRUE;
11350
11351         /* 
11352          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11353          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11354          * we want to return normal System.MonoType objects, so clear these out from the cache.
11355          *
11356          * Together with this we must ensure the contents of all instances to match the created type.
11357          */
11358         if (domain->type_hash && klass->generic_container)
11359                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11360
11361         mono_domain_unlock (domain);
11362         mono_loader_unlock ();
11363
11364         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11365                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11366                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11367         }
11368
11369         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11370         g_assert (res != (MonoReflectionType*)tb);
11371
11372         return res;
11373
11374 failure:
11375         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11376         klass->wastypebuilder = TRUE;
11377         mono_domain_unlock (domain);
11378         mono_loader_unlock ();
11379         mono_error_raise_exception (&error);
11380         return NULL;
11381 }
11382
11383 void
11384 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11385 {
11386         MonoGenericParamFull *param;
11387         MonoImage *image;
11388         MonoClass *pklass;
11389         MonoError error;
11390
11391         MONO_ARCH_SAVE_REGS;
11392
11393         image = &gparam->tbuilder->module->dynamic_image->image;
11394
11395         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11396
11397         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11398         g_assert (mono_error_ok (&error));
11399         param->param.num = gparam->index;
11400
11401         if (gparam->mbuilder) {
11402                 if (!gparam->mbuilder->generic_container) {
11403                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11404                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11405                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11406                         gparam->mbuilder->generic_container->is_method = TRUE;
11407                         /* 
11408                          * Cannot set owner.method, since the MonoMethod is not created yet.
11409                          * Set the image field instead, so type_in_image () works.
11410                          */
11411                         gparam->mbuilder->generic_container->image = klass->image;
11412                 }
11413                 param->param.owner = gparam->mbuilder->generic_container;
11414         } else if (gparam->tbuilder) {
11415                 if (!gparam->tbuilder->generic_container) {
11416                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11417                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11418                         gparam->tbuilder->generic_container->owner.klass = klass;
11419                 }
11420                 param->param.owner = gparam->tbuilder->generic_container;
11421         }
11422
11423         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11424
11425         gparam->type.type = &pklass->byval_arg;
11426
11427         mono_class_set_ref_info (pklass, gparam);
11428         mono_image_lock (image);
11429         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11430         mono_image_unlock (image);
11431 }
11432
11433 MonoArray *
11434 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11435 {
11436         MonoReflectionModuleBuilder *module = sig->module;
11437         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11438         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11439         guint32 buflen, i;
11440         MonoArray *result;
11441         SigBuffer buf;
11442
11443         check_array_for_usertypes (sig->arguments);
11444
11445         sigbuffer_init (&buf, 32);
11446
11447         sigbuffer_add_value (&buf, 0x07);
11448         sigbuffer_add_value (&buf, na);
11449         if (assembly != NULL){
11450                 for (i = 0; i < na; ++i) {
11451                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11452                         encode_reflection_type (assembly, type, &buf);
11453                 }
11454         }
11455
11456         buflen = buf.p - buf.buf;
11457         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11458         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11459         sigbuffer_free (&buf);
11460
11461         return result;
11462 }
11463
11464 MonoArray *
11465 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11466 {
11467         MonoDynamicImage *assembly = sig->module->dynamic_image;
11468         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11469         guint32 buflen, i;
11470         MonoArray *result;
11471         SigBuffer buf;
11472
11473         check_array_for_usertypes (sig->arguments);
11474
11475         sigbuffer_init (&buf, 32);
11476
11477         sigbuffer_add_value (&buf, 0x06);
11478         for (i = 0; i < na; ++i) {
11479                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11480                 encode_reflection_type (assembly, type, &buf);
11481         }
11482
11483         buflen = buf.p - buf.buf;
11484         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11485         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11486         sigbuffer_free (&buf);
11487
11488         return result;
11489 }
11490
11491 typedef struct {
11492         MonoMethod *handle;
11493         MonoDomain *domain;
11494 } DynamicMethodReleaseData;
11495
11496 /*
11497  * The runtime automatically clean up those after finalization.
11498 */      
11499 static MonoReferenceQueue *dynamic_method_queue;
11500
11501 static void
11502 free_dynamic_method (void *dynamic_method)
11503 {
11504         DynamicMethodReleaseData *data = dynamic_method;
11505
11506         mono_runtime_free_method (data->domain, data->handle);
11507         g_free (data);
11508 }
11509
11510 void 
11511 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11512 {
11513         MonoReferenceQueue *queue;
11514         MonoMethod *handle;
11515         DynamicMethodReleaseData *release_data;
11516         ReflectionMethodBuilder rmb;
11517         MonoMethodSignature *sig;
11518         MonoClass *klass;
11519         GSList *l;
11520         int i;
11521
11522         if (mono_runtime_is_shutting_down ())
11523                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11524
11525         if (!(queue = dynamic_method_queue)) {
11526                 mono_loader_lock ();
11527                 if (!(queue = dynamic_method_queue))
11528                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11529                 mono_loader_unlock ();
11530         }
11531
11532         sig = dynamic_method_to_signature (mb);
11533
11534         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11535
11536         /*
11537          * Resolve references.
11538          */
11539         /* 
11540          * Every second entry in the refs array is reserved for storing handle_class,
11541          * which is needed by the ldtoken implementation in the JIT.
11542          */
11543         rmb.nrefs = mb->nrefs;
11544         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11545         for (i = 0; i < mb->nrefs; i += 2) {
11546                 MonoClass *handle_class;
11547                 gpointer ref;
11548                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11549
11550                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11551                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11552                         /*
11553                          * The referenced DynamicMethod should already be created by the managed
11554                          * code, except in the case of circular references. In that case, we store
11555                          * method in the refs array, and fix it up later when the referenced 
11556                          * DynamicMethod is created.
11557                          */
11558                         if (method->mhandle) {
11559                                 ref = method->mhandle;
11560                         } else {
11561                                 /* FIXME: GC object stored in unmanaged memory */
11562                                 ref = method;
11563
11564                                 /* FIXME: GC object stored in unmanaged memory */
11565                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11566                         }
11567                         handle_class = mono_defaults.methodhandle_class;
11568                 } else {
11569                         MonoException *ex = NULL;
11570                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11571                         if (!ref)
11572                                 ex = mono_get_exception_type_load (NULL, NULL);
11573                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11574                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11575
11576                         if (ex) {
11577                                 g_free (rmb.refs);
11578                                 mono_raise_exception (ex);
11579                                 return;
11580                         }
11581                 }
11582
11583                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11584                 rmb.refs [i + 1] = handle_class;
11585         }               
11586
11587         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11588
11589         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11590         release_data = g_new (DynamicMethodReleaseData, 1);
11591         release_data->handle = handle;
11592         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11593         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11594                 g_free (release_data);
11595
11596         /* Fix up refs entries pointing at us */
11597         for (l = mb->referenced_by; l; l = l->next) {
11598                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11599                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11600                 gpointer *data;
11601                 
11602                 g_assert (method->mhandle);
11603
11604                 data = (gpointer*)wrapper->method_data;
11605                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11606                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11607                                 data [i + 1] = mb->mhandle;
11608                 }
11609         }
11610         g_slist_free (mb->referenced_by);
11611
11612         g_free (rmb.refs);
11613
11614         /* ilgen is no longer needed */
11615         mb->ilgen = NULL;
11616 }
11617
11618 #endif /* DISABLE_REFLECTION_EMIT */
11619
11620 /**
11621  * 
11622  * mono_reflection_is_valid_dynamic_token:
11623  * 
11624  * Returns TRUE if token is valid.
11625  * 
11626  */
11627 gboolean
11628 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11629 {
11630         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11631 }
11632
11633 MonoMethodSignature *
11634 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11635 {
11636         MonoMethodSignature *sig;
11637         g_assert (image->dynamic);
11638
11639         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11640         if (sig)
11641                 return sig;
11642
11643         return mono_method_signature (method);
11644 }
11645
11646 #ifndef DISABLE_REFLECTION_EMIT
11647
11648 /**
11649  * mono_reflection_lookup_dynamic_token:
11650  *
11651  * Finish the Builder object pointed to by TOKEN and return the corresponding
11652  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11653  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11654  * mapping table.
11655  *
11656  * LOCKING: Take the loader lock
11657  */
11658 gpointer
11659 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11660 {
11661         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11662         MonoObject *obj;
11663         MonoClass *klass;
11664
11665         mono_loader_lock ();
11666         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11667         mono_loader_unlock ();
11668         if (!obj) {
11669                 if (valid_token)
11670                         g_error ("Could not find required dynamic token 0x%08x", token);
11671                 else
11672                         return NULL;
11673         }
11674
11675         if (!handle_class)
11676                 handle_class = &klass;
11677         return resolve_object (image, obj, handle_class, context);
11678 }
11679
11680 /*
11681  * ensure_complete_type:
11682  *
11683  *   Ensure that KLASS is completed if it is a dynamic type, or references
11684  * dynamic types.
11685  */
11686 static void
11687 ensure_complete_type (MonoClass *klass)
11688 {
11689         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11690                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11691
11692                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11693
11694                 // Asserting here could break a lot of code
11695                 //g_assert (klass->wastypebuilder);
11696         }
11697
11698         if (klass->generic_class) {
11699                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11700                 int i;
11701
11702                 for (i = 0; i < inst->type_argc; ++i) {
11703                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11704                 }
11705         }
11706 }
11707
11708 static gpointer
11709 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11710 {
11711         gpointer result = NULL;
11712
11713         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11714                 result = mono_string_intern ((MonoString*)obj);
11715                 *handle_class = mono_defaults.string_class;
11716                 g_assert (result);
11717         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11718                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11719                 MonoClass *mc = mono_class_from_mono_type (type);
11720                 if (!mono_class_init (mc))
11721                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11722
11723                 if (context) {
11724                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11725                         result = mono_class_from_mono_type (inflated);
11726                         mono_metadata_free_type (inflated);
11727                 } else {
11728                         result = mono_class_from_mono_type (type);
11729                 }
11730                 *handle_class = mono_defaults.typehandle_class;
11731                 g_assert (result);
11732         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11733                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11734                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11735                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11736                 result = ((MonoReflectionMethod*)obj)->method;
11737                 if (context)
11738                         result = mono_class_inflate_generic_method (result, context);
11739                 *handle_class = mono_defaults.methodhandle_class;
11740                 g_assert (result);
11741         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11742                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11743                 result = mb->mhandle;
11744                 if (!result) {
11745                         /* Type is not yet created */
11746                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11747
11748                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11749
11750                         /*
11751                          * Hopefully this has been filled in by calling CreateType() on the
11752                          * TypeBuilder.
11753                          */
11754                         /*
11755                          * TODO: This won't work if the application finishes another 
11756                          * TypeBuilder instance instead of this one.
11757                          */
11758                         result = mb->mhandle;
11759                 }
11760                 if (context)
11761                         result = mono_class_inflate_generic_method (result, context);
11762                 *handle_class = mono_defaults.methodhandle_class;
11763         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11764                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11765
11766                 result = cb->mhandle;
11767                 if (!result) {
11768                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11769
11770                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11771                         result = cb->mhandle;
11772                 }
11773                 if (context)
11774                         result = mono_class_inflate_generic_method (result, context);
11775                 *handle_class = mono_defaults.methodhandle_class;
11776         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11777                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11778
11779                 ensure_complete_type (field->parent);
11780                 if (context) {
11781                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11782                         MonoClass *class = mono_class_from_mono_type (inflated);
11783                         MonoClassField *inflated_field;
11784                         gpointer iter = NULL;
11785                         mono_metadata_free_type (inflated);
11786                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11787                                 if (!strcmp (field->name, inflated_field->name))
11788                                         break;
11789                         }
11790                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11791                         result = inflated_field;
11792                 } else {
11793                         result = field;
11794                 }
11795                 *handle_class = mono_defaults.fieldhandle_class;
11796                 g_assert (result);
11797         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11798                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11799                 result = fb->handle;
11800
11801                 if (!result) {
11802                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11803
11804                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11805                         result = fb->handle;
11806                 }
11807
11808                 if (fb->handle && fb->handle->parent->generic_container) {
11809                         MonoClass *klass = fb->handle->parent;
11810                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11811                         MonoClass *inflated = mono_class_from_mono_type (type);
11812
11813                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11814                         g_assert (result);
11815                         mono_metadata_free_type (type);
11816                 }
11817                 *handle_class = mono_defaults.fieldhandle_class;
11818         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11819                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11820                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11821                 MonoClass *klass;
11822
11823                 klass = type->data.klass;
11824                 if (klass->wastypebuilder) {
11825                         /* Already created */
11826                         result = klass;
11827                 }
11828                 else {
11829                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11830                         result = type->data.klass;
11831                         g_assert (result);
11832                 }
11833                 *handle_class = mono_defaults.typehandle_class;
11834         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11835                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11836                 MonoMethodSignature *sig;
11837                 int nargs, i;
11838
11839                 if (helper->arguments)
11840                         nargs = mono_array_length (helper->arguments);
11841                 else
11842                         nargs = 0;
11843
11844                 sig = mono_metadata_signature_alloc (image, nargs);
11845                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11846                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11847
11848                 if (helper->unmanaged_call_conv) { /* unmanaged */
11849                         sig->call_convention = helper->unmanaged_call_conv - 1;
11850                         sig->pinvoke = TRUE;
11851                 } else if (helper->call_conv & 0x02) {
11852                         sig->call_convention = MONO_CALL_VARARG;
11853                 } else {
11854                         sig->call_convention = MONO_CALL_DEFAULT;
11855                 }
11856
11857                 sig->param_count = nargs;
11858                 /* TODO: Copy type ? */
11859                 sig->ret = helper->return_type->type;
11860                 for (i = 0; i < nargs; ++i)
11861                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11862
11863                 result = sig;
11864                 *handle_class = NULL;
11865         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11866                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11867                 /* Already created by the managed code */
11868                 g_assert (method->mhandle);
11869                 result = method->mhandle;
11870                 *handle_class = mono_defaults.methodhandle_class;
11871         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11872                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11873                 type = mono_class_inflate_generic_type (type, context);
11874                 result = mono_class_from_mono_type (type);
11875                 *handle_class = mono_defaults.typehandle_class;
11876                 g_assert (result);
11877                 mono_metadata_free_type (type);
11878         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11879                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11880                 type = mono_class_inflate_generic_type (type, context);
11881                 result = mono_class_from_mono_type (type);
11882                 *handle_class = mono_defaults.typehandle_class;
11883                 g_assert (result);
11884                 mono_metadata_free_type (type);
11885         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11886                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11887                 MonoClass *inflated;
11888                 MonoType *type;
11889                 MonoClassField *field;
11890
11891                 if (is_sre_field_builder (mono_object_class (f->fb)))
11892                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11893                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11894                         field = ((MonoReflectionField*)f->fb)->field;
11895                 else
11896                         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)));
11897
11898                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11899                 inflated = mono_class_from_mono_type (type);
11900
11901                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11902                 ensure_complete_type (field->parent);
11903                 g_assert (result);
11904                 mono_metadata_free_type (type);
11905                 *handle_class = mono_defaults.fieldhandle_class;
11906         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11907                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11908                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11909                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11910                 MonoMethod *method;
11911
11912                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11913                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11914                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11915                         method = ((MonoReflectionMethod *)c->cb)->method;
11916                 else
11917                         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)));
11918
11919                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11920                 *handle_class = mono_defaults.methodhandle_class;
11921                 mono_metadata_free_type (type);
11922         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11923                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11924                 if (m->method_args) {
11925                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11926                         if (context)
11927                                 result = mono_class_inflate_generic_method (result, context);
11928                 } else {
11929                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11930                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11931                         MonoMethod *method;
11932
11933                         if (is_sre_method_builder (mono_object_class (m->mb)))
11934                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11935                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11936                                 method = ((MonoReflectionMethod *)m->mb)->method;
11937                         else
11938                                 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)));
11939
11940                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11941                         mono_metadata_free_type (type);
11942                 }
11943                 *handle_class = mono_defaults.methodhandle_class;
11944         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11945                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11946                 MonoType *mtype;
11947                 MonoClass *klass;
11948                 MonoMethod *method;
11949                 gpointer iter;
11950                 char *name;
11951
11952                 mtype = mono_reflection_type_get_handle (m->parent);
11953                 klass = mono_class_from_mono_type (mtype);
11954
11955                 /* Find the method */
11956
11957                 name = mono_string_to_utf8 (m->name);
11958                 iter = NULL;
11959                 while ((method = mono_class_get_methods (klass, &iter))) {
11960                         if (!strcmp (method->name, name))
11961                                 break;
11962                 }
11963                 g_free (name);
11964
11965                 // FIXME:
11966                 g_assert (method);
11967                 // FIXME: Check parameters/return value etc. match
11968
11969                 result = method;
11970                 *handle_class = mono_defaults.methodhandle_class;
11971         } else if (is_sre_array (mono_object_get_class(obj)) ||
11972                                 is_sre_byref (mono_object_get_class(obj)) ||
11973                                 is_sre_pointer (mono_object_get_class(obj))) {
11974                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11975                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11976
11977                 if (context) {
11978                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11979                         result = mono_class_from_mono_type (inflated);
11980                         mono_metadata_free_type (inflated);
11981                 } else {
11982                         result = mono_class_from_mono_type (type);
11983                 }
11984                 *handle_class = mono_defaults.typehandle_class;
11985         } else {
11986                 g_print ("%s\n", obj->vtable->klass->name);
11987                 g_assert_not_reached ();
11988         }
11989         return result;
11990 }
11991
11992 #else /* DISABLE_REFLECTION_EMIT */
11993
11994 MonoArray*
11995 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11996 {
11997         g_assert_not_reached ();
11998         return NULL;
11999 }
12000
12001 void
12002 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12003 {
12004         g_assert_not_reached ();
12005 }
12006
12007 void
12008 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12009 {
12010         g_assert_not_reached ();
12011 }
12012
12013 void
12014 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12015 {
12016         g_assert_not_reached ();
12017 }
12018
12019 void
12020 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12021 {
12022         g_assert_not_reached ();
12023 }
12024
12025 void
12026 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12027 {
12028         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12029 }
12030
12031 void
12032 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12033 {
12034         g_assert_not_reached ();
12035 }
12036
12037 void
12038 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12039 {
12040         g_assert_not_reached ();
12041 }
12042
12043 MonoReflectionModule *
12044 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12045 {
12046         g_assert_not_reached ();
12047         return NULL;
12048 }
12049
12050 guint32
12051 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12052 {
12053         g_assert_not_reached ();
12054         return 0;
12055 }
12056
12057 guint32
12058 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12059 {
12060         g_assert_not_reached ();
12061         return 0;
12062 }
12063
12064 guint32
12065 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12066                                                  gboolean create_open_instance, gboolean register_token)
12067 {
12068         g_assert_not_reached ();
12069         return 0;
12070 }
12071
12072 void
12073 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12074 {
12075 }
12076
12077 void
12078 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12079 {
12080         g_assert_not_reached ();
12081 }
12082
12083 void
12084 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12085 {
12086         *overrides = NULL;
12087         *num_overrides = 0;
12088 }
12089
12090 MonoReflectionEvent *
12091 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12092 {
12093         g_assert_not_reached ();
12094         return NULL;
12095 }
12096
12097 MonoReflectionType*
12098 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12099 {
12100         g_assert_not_reached ();
12101         return NULL;
12102 }
12103
12104 void
12105 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12106 {
12107         g_assert_not_reached ();
12108 }
12109
12110 MonoArray *
12111 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12112 {
12113         g_assert_not_reached ();
12114         return NULL;
12115 }
12116
12117 MonoArray *
12118 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12119 {
12120         g_assert_not_reached ();
12121         return NULL;
12122 }
12123
12124 void 
12125 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12126 {
12127 }
12128
12129 gpointer
12130 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12131 {
12132         return NULL;
12133 }
12134
12135 MonoType*
12136 mono_reflection_type_get_handle (MonoReflectionType* ref)
12137 {
12138         if (!ref)
12139                 return NULL;
12140         return ref->type;
12141 }
12142
12143 void
12144 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12145 {
12146         g_assert_not_reached ();
12147 }
12148
12149 #endif /* DISABLE_REFLECTION_EMIT */
12150
12151 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12152 const static guint32 declsec_flags_map[] = {
12153         0x00000000,                                     /* empty */
12154         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12155         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12156         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12157         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12158         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12159         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12160         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12161         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12162         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12163         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12164         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12165         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12166         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12167         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12168         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12169         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12170         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12171         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12172 };
12173
12174 /*
12175  * Returns flags that includes all available security action associated to the handle.
12176  * @token: metadata token (either for a class or a method)
12177  * @image: image where resides the metadata.
12178  */
12179 static guint32
12180 mono_declsec_get_flags (MonoImage *image, guint32 token)
12181 {
12182         int index = mono_metadata_declsec_from_index (image, token);
12183         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12184         guint32 result = 0;
12185         guint32 action;
12186         int i;
12187
12188         /* HasSecurity can be present for other, not specially encoded, attributes,
12189            e.g. SuppressUnmanagedCodeSecurityAttribute */
12190         if (index < 0)
12191                 return 0;
12192
12193         for (i = index; i < t->rows; i++) {
12194                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12195
12196                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12197                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12198                         break;
12199
12200                 action = cols [MONO_DECL_SECURITY_ACTION];
12201                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12202                         result |= declsec_flags_map [action];
12203                 } else {
12204                         g_assert_not_reached ();
12205                 }
12206         }
12207         return result;
12208 }
12209
12210 /*
12211  * Get the security actions (in the form of flags) associated with the specified method.
12212  *
12213  * @method: The method for which we want the declarative security flags.
12214  * Return the declarative security flags for the method (only).
12215  *
12216  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12217  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12218  */
12219 guint32
12220 mono_declsec_flags_from_method (MonoMethod *method)
12221 {
12222         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12223                 /* FIXME: No cache (for the moment) */
12224                 guint32 idx = mono_method_get_index (method);
12225                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12226                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12227                 return mono_declsec_get_flags (method->klass->image, idx);
12228         }
12229         return 0;
12230 }
12231
12232 /*
12233  * Get the security actions (in the form of flags) associated with the specified class.
12234  *
12235  * @klass: The class for which we want the declarative security flags.
12236  * Return the declarative security flags for the class.
12237  *
12238  * Note: We cache the flags inside the MonoClass structure as this will get 
12239  *       called very often (at least for each method).
12240  */
12241 guint32
12242 mono_declsec_flags_from_class (MonoClass *klass)
12243 {
12244         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12245                 if (!klass->ext || !klass->ext->declsec_flags) {
12246                         guint32 idx;
12247
12248                         idx = mono_metadata_token_index (klass->type_token);
12249                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12250                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12251                         mono_loader_lock ();
12252                         mono_class_alloc_ext (klass);
12253                         mono_loader_unlock ();
12254                         /* we cache the flags on classes */
12255                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12256                 }
12257                 return klass->ext->declsec_flags;
12258         }
12259         return 0;
12260 }
12261
12262 /*
12263  * Get the security actions (in the form of flags) associated with the specified assembly.
12264  *
12265  * @assembly: The assembly for which we want the declarative security flags.
12266  * Return the declarative security flags for the assembly.
12267  */
12268 guint32
12269 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12270 {
12271         guint32 idx = 1; /* there is only one assembly */
12272         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12273         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12274         return mono_declsec_get_flags (assembly->image, idx);
12275 }
12276
12277
12278 /*
12279  * Fill actions for the specific index (which may either be an encoded class token or
12280  * an encoded method token) from the metadata image.
12281  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12282  */
12283 static MonoBoolean
12284 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12285         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12286 {
12287         MonoBoolean result = FALSE;
12288         MonoTableInfo *t;
12289         guint32 cols [MONO_DECL_SECURITY_SIZE];
12290         int index = mono_metadata_declsec_from_index (image, token);
12291         int i;
12292
12293         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12294         for (i = index; i < t->rows; i++) {
12295                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12296
12297                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12298                         return result;
12299
12300                 /* if present only replace (class) permissions with method permissions */
12301                 /* if empty accept either class or method permissions */
12302                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12303                         if (!actions->demand.blob) {
12304                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12305                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12306                                 actions->demand.blob = (char*) (blob + 2);
12307                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12308                                 result = TRUE;
12309                         }
12310                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12311                         if (!actions->noncasdemand.blob) {
12312                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12313                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12314                                 actions->noncasdemand.blob = (char*) (blob + 2);
12315                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12316                                 result = TRUE;
12317                         }
12318                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12319                         if (!actions->demandchoice.blob) {
12320                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12321                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12322                                 actions->demandchoice.blob = (char*) (blob + 2);
12323                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12324                                 result = TRUE;
12325                         }
12326                 }
12327         }
12328
12329         return result;
12330 }
12331
12332 static MonoBoolean
12333 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12334         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12335 {
12336         guint32 idx = mono_metadata_token_index (klass->type_token);
12337         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12338         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12339         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12340 }
12341
12342 static MonoBoolean
12343 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12344         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12345 {
12346         guint32 idx = mono_method_get_index (method);
12347         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12348         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12349         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12350 }
12351
12352 /*
12353  * Collect all actions (that requires to generate code in mini) assigned for
12354  * the specified method.
12355  * Note: Don't use the content of actions if the function return FALSE.
12356  */
12357 MonoBoolean
12358 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12359 {
12360         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12361                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12362         MonoBoolean result = FALSE;
12363         guint32 flags;
12364
12365         /* quick exit if no declarative security is present in the metadata */
12366         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12367                 return FALSE;
12368
12369         /* we want the original as the wrapper is "free" of the security informations */
12370         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12371                 method = mono_marshal_method_from_wrapper (method);
12372                 if (!method)
12373                         return FALSE;
12374         }
12375
12376         /* First we look for method-level attributes */
12377         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12378                 mono_class_init (method->klass);
12379                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12380
12381                 result = mono_declsec_get_method_demands_params (method, demands, 
12382                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12383         }
12384
12385         /* Here we use (or create) the class declarative cache to look for demands */
12386         flags = mono_declsec_flags_from_class (method->klass);
12387         if (flags & mask) {
12388                 if (!result) {
12389                         mono_class_init (method->klass);
12390                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12391                 }
12392                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12393                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12394         }
12395
12396         /* The boolean return value is used as a shortcut in case nothing needs to
12397            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12398         return result;
12399 }
12400
12401
12402 /*
12403  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12404  *
12405  * Note: Don't use the content of actions if the function return FALSE.
12406  */
12407 MonoBoolean
12408 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12409 {
12410         MonoBoolean result = FALSE;
12411         guint32 flags;
12412
12413         /* quick exit if no declarative security is present in the metadata */
12414         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12415                 return FALSE;
12416
12417         /* we want the original as the wrapper is "free" of the security informations */
12418         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12419                 method = mono_marshal_method_from_wrapper (method);
12420                 if (!method)
12421                         return FALSE;
12422         }
12423
12424         /* results are independant - zeroize both */
12425         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12426         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12427
12428         /* First we look for method-level attributes */
12429         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12430                 mono_class_init (method->klass);
12431
12432                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12433                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12434         }
12435
12436         /* Here we use (or create) the class declarative cache to look for demands */
12437         flags = mono_declsec_flags_from_class (method->klass);
12438         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12439                 mono_class_init (method->klass);
12440
12441                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12442                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12443         }
12444
12445         return result;
12446 }
12447
12448 /*
12449  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12450  *
12451  * @klass       The inherited class - this is the class that provides the security check (attributes)
12452  * @demans      
12453  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12454  * 
12455  * Note: Don't use the content of actions if the function return FALSE.
12456  */
12457 MonoBoolean
12458 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12459 {
12460         MonoBoolean result = FALSE;
12461         guint32 flags;
12462
12463         /* quick exit if no declarative security is present in the metadata */
12464         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12465                 return FALSE;
12466
12467         /* Here we use (or create) the class declarative cache to look for demands */
12468         flags = mono_declsec_flags_from_class (klass);
12469         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12470                 mono_class_init (klass);
12471                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12472
12473                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12474                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12475         }
12476
12477         return result;
12478 }
12479
12480 /*
12481  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12482  *
12483  * Note: Don't use the content of actions if the function return FALSE.
12484  */
12485 MonoBoolean
12486 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12487 {
12488         /* quick exit if no declarative security is present in the metadata */
12489         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12490                 return FALSE;
12491
12492         /* we want the original as the wrapper is "free" of the security informations */
12493         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12494                 method = mono_marshal_method_from_wrapper (method);
12495                 if (!method)
12496                         return FALSE;
12497         }
12498
12499         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12500                 mono_class_init (method->klass);
12501                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12502
12503                 return mono_declsec_get_method_demands_params (method, demands, 
12504                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12505         }
12506         return FALSE;
12507 }
12508
12509
12510 static MonoBoolean
12511 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12512 {
12513         guint32 cols [MONO_DECL_SECURITY_SIZE];
12514         MonoTableInfo *t;
12515         int i;
12516
12517         int index = mono_metadata_declsec_from_index (image, token);
12518         if (index == -1)
12519                 return FALSE;
12520
12521         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12522         for (i = index; i < t->rows; i++) {
12523                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12524
12525                 /* shortcut - index are ordered */
12526                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12527                         return FALSE;
12528
12529                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12530                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12531                         entry->blob = (char*) (metadata + 2);
12532                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12533                         return TRUE;
12534                 }
12535         }
12536
12537         return FALSE;
12538 }
12539
12540 MonoBoolean
12541 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12542 {
12543         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12544                 guint32 idx = mono_method_get_index (method);
12545                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12546                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12547                 return get_declsec_action (method->klass->image, idx, action, entry);
12548         }
12549         return FALSE;
12550 }
12551
12552 MonoBoolean
12553 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12554 {
12555         /* use cache */
12556         guint32 flags = mono_declsec_flags_from_class (klass);
12557         if (declsec_flags_map [action] & flags) {
12558                 guint32 idx = mono_metadata_token_index (klass->type_token);
12559                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12560                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12561                 return get_declsec_action (klass->image, idx, action, entry);
12562         }
12563         return FALSE;
12564 }
12565
12566 MonoBoolean
12567 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12568 {
12569         guint32 idx = 1; /* there is only one assembly */
12570         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12571         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12572
12573         return get_declsec_action (assembly->image, idx, action, entry);
12574 }
12575
12576 gboolean
12577 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12578 {
12579         MonoObject *res, *exc;
12580         void *params [1];
12581         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12582         static MonoMethod *method = NULL;
12583
12584         if (!System_Reflection_Emit_TypeBuilder) {
12585                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12586                 g_assert (System_Reflection_Emit_TypeBuilder);
12587         }
12588         if (method == NULL) {
12589                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12590                 g_assert (method);
12591         }
12592
12593         /* 
12594          * The result of mono_type_get_object () might be a System.MonoType but we
12595          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12596          */
12597         g_assert (mono_class_get_ref_info (klass));
12598         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12599
12600         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12601
12602         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12603         if (exc)
12604                 return FALSE;
12605         else
12606                 return *(MonoBoolean*)mono_object_unbox (res);
12607 }
12608
12609 /**
12610  * mono_reflection_type_get_type:
12611  * @reftype: the System.Type object
12612  *
12613  * Returns the MonoType* associated with the C# System.Type object @reftype.
12614  */
12615 MonoType*
12616 mono_reflection_type_get_type (MonoReflectionType *reftype)
12617 {
12618         g_assert (reftype);
12619
12620         return mono_reflection_type_get_handle (reftype);
12621 }
12622