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