Merge branch 'master' of github.com:mono/mono
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  *
10  */
11 #include <config.h>
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include "image.h"
35 #include "cil-coff.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-ptr-array.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45
46
47 #if HAVE_SGEN_GC
48 static void* reflection_info_desc = NULL;
49 #define MOVING_GC_REGISTER(addr) do {   \
50                 if (!reflection_info_desc) {    \
51                         gsize bmap = 1;         \
52                         reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);       \
53                 }       \
54                 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
55         } while (0)
56 #else
57 #define MOVING_GC_REGISTER(addr)
58 #endif
59
60 static gboolean is_usertype (MonoReflectionType *ref);
61 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
62
63 typedef struct {
64         char *p;
65         char *buf;
66         char *end;
67 } SigBuffer;
68
69 #define TEXT_OFFSET 512
70 #define CLI_H_SIZE 136
71 #define FILE_ALIGN 512
72 #define VIRT_ALIGN 8192
73 #define START_TEXT_RVA  0x00002000
74
75 typedef struct {
76         MonoReflectionILGen *ilgen;
77         MonoReflectionType *rtype;
78         MonoArray *parameters;
79         MonoArray *generic_params;
80         MonoGenericContainer *generic_container;
81         MonoArray *pinfo;
82         MonoArray *opt_types;
83         guint32 attrs;
84         guint32 iattrs;
85         guint32 call_conv;
86         guint32 *table_idx; /* note: it's a pointer */
87         MonoArray *code;
88         MonoObject *type;
89         MonoString *name;
90         MonoBoolean init_locals;
91         MonoBoolean skip_visibility;
92         MonoArray *return_modreq;
93         MonoArray *return_modopt;
94         MonoArray *param_modreq;
95         MonoArray *param_modopt;
96         MonoArray *permissions;
97         MonoMethod *mhandle;
98         guint32 nrefs;
99         gpointer *refs;
100         /* for PInvoke */
101         int charset, extra_flags, native_cc;
102         MonoString *dll, *dllentry;
103 } ReflectionMethodBuilder;
104
105 typedef struct {
106         guint32 owner;
107         MonoReflectionGenericParam *gparam;
108 } GenericParamTableEntry;
109
110 const unsigned char table_sizes [MONO_TABLE_NUM] = {
111         MONO_MODULE_SIZE,
112         MONO_TYPEREF_SIZE,
113         MONO_TYPEDEF_SIZE,
114         0,
115         MONO_FIELD_SIZE,
116         0,
117         MONO_METHOD_SIZE,
118         0,
119         MONO_PARAM_SIZE,
120         MONO_INTERFACEIMPL_SIZE,
121         MONO_MEMBERREF_SIZE,    /* 0x0A */
122         MONO_CONSTANT_SIZE,
123         MONO_CUSTOM_ATTR_SIZE,
124         MONO_FIELD_MARSHAL_SIZE,
125         MONO_DECL_SECURITY_SIZE,
126         MONO_CLASS_LAYOUT_SIZE,
127         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
128         MONO_STAND_ALONE_SIGNATURE_SIZE,
129         MONO_EVENT_MAP_SIZE,
130         0,
131         MONO_EVENT_SIZE,
132         MONO_PROPERTY_MAP_SIZE,
133         0,
134         MONO_PROPERTY_SIZE,
135         MONO_METHOD_SEMA_SIZE,
136         MONO_METHODIMPL_SIZE,
137         MONO_MODULEREF_SIZE,    /* 0x1A */
138         MONO_TYPESPEC_SIZE,
139         MONO_IMPLMAP_SIZE,      
140         MONO_FIELD_RVA_SIZE,
141         0,
142         0,
143         MONO_ASSEMBLY_SIZE,     /* 0x20 */
144         MONO_ASSEMBLY_PROCESSOR_SIZE,
145         MONO_ASSEMBLYOS_SIZE,
146         MONO_ASSEMBLYREF_SIZE,
147         MONO_ASSEMBLYREFPROC_SIZE,
148         MONO_ASSEMBLYREFOS_SIZE,
149         MONO_FILE_SIZE,
150         MONO_EXP_TYPE_SIZE,
151         MONO_MANIFEST_SIZE,
152         MONO_NESTED_CLASS_SIZE,
153
154         MONO_GENERICPARAM_SIZE, /* 0x2A */
155         MONO_METHODSPEC_SIZE,
156         MONO_GENPARCONSTRAINT_SIZE
157
158 };
159
160 #ifndef DISABLE_REFLECTION_EMIT
161 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
162 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
163 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
164 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
165 static void    ensure_runtime_vtable (MonoClass *klass);
166 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
167 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
168 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
169 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
170 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
171 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
172 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
173 #endif
174
175 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
176 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
177 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
178 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
179 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
180 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
181 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
182 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
183 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
184 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
185 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
186 static gboolean is_sre_array (MonoClass *class);
187 static gboolean is_sre_byref (MonoClass *class);
188 static gboolean is_sre_pointer (MonoClass *class);
189 static gboolean is_sre_type_builder (MonoClass *class);
190 static gboolean is_sre_method_builder (MonoClass *class);
191 static gboolean is_sre_ctor_builder (MonoClass *class);
192 static gboolean is_sre_field_builder (MonoClass *class);
193 static gboolean is_sr_mono_method (MonoClass *class);
194 static gboolean is_sr_mono_cmethod (MonoClass *class);
195 static gboolean is_sr_mono_generic_method (MonoClass *class);
196 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
197 static gboolean is_sr_mono_field (MonoClass *class);
198 static gboolean is_sr_mono_property (MonoClass *class);
199 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
200 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
201
202 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
203 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
204 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
205
206 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
207 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
208         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
209         __type = mono_reflection_type_resolve_user_types (__type);      \
210         mono_array_set (arr, MonoReflectionType*, index, __type);       \
211 } while (0)
212
213 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
214
215 void
216 mono_reflection_init (void)
217 {
218 }
219
220 static void
221 sigbuffer_init (SigBuffer *buf, int size)
222 {
223         buf->buf = g_malloc (size);
224         buf->p = buf->buf;
225         buf->end = buf->buf + size;
226 }
227
228 static void
229 sigbuffer_make_room (SigBuffer *buf, int size)
230 {
231         if (buf->end - buf->p < size) {
232                 int new_size = buf->end - buf->buf + size + 32;
233                 char *p = g_realloc (buf->buf, new_size);
234                 size = buf->p - buf->buf;
235                 buf->buf = p;
236                 buf->p = p + size;
237                 buf->end = buf->buf + new_size;
238         }
239 }
240
241 static void
242 sigbuffer_add_value (SigBuffer *buf, guint32 val)
243 {
244         sigbuffer_make_room (buf, 6);
245         mono_metadata_encode_value (val, buf->p, &buf->p);
246 }
247
248 static void
249 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
250 {
251         sigbuffer_make_room (buf, 1);
252         buf->p [0] = val;
253         buf->p++;
254 }
255
256 static void
257 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
258 {
259         sigbuffer_make_room (buf, size);
260         memcpy (buf->p, p, size);
261         buf->p += size;
262 }
263
264 static void
265 sigbuffer_free (SigBuffer *buf)
266 {
267         g_free (buf->buf);
268 }
269
270 #ifndef DISABLE_REFLECTION_EMIT
271 /**
272  * mp_g_alloc:
273  *
274  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
275  * from the C heap.
276  */
277 static gpointer
278 image_g_malloc (MonoImage *image, guint size)
279 {
280         if (image)
281                 return mono_image_alloc (image, size);
282         else
283                 return g_malloc (size);
284 }
285 #endif /* !DISABLE_REFLECTION_EMIT */
286
287 /**
288  * image_g_alloc0:
289  *
290  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
291  * from the C heap.
292  */
293 static gpointer
294 image_g_malloc0 (MonoImage *image, guint size)
295 {
296         if (image)
297                 return mono_image_alloc0 (image, size);
298         else
299                 return g_malloc0 (size);
300 }
301
302 #ifndef DISABLE_REFLECTION_EMIT
303 static char*
304 image_strdup (MonoImage *image, const char *s)
305 {
306         if (image)
307                 return mono_image_strdup (image, s);
308         else
309                 return g_strdup (s);
310 }
311 #endif
312
313 #define image_g_new(image,struct_type, n_structs)               \
314     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
315
316 #define image_g_new0(image,struct_type, n_structs)              \
317     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
318
319
320 static void
321 alloc_table (MonoDynamicTable *table, guint nrows)
322 {
323         table->rows = nrows;
324         g_assert (table->columns);
325         if (nrows + 1 >= table->alloc_rows) {
326                 while (nrows + 1 >= table->alloc_rows) {
327                         if (table->alloc_rows == 0)
328                                 table->alloc_rows = 16;
329                         else
330                                 table->alloc_rows *= 2;
331                 }
332
333                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
334         }
335 }
336
337 static void
338 make_room_in_stream (MonoDynamicStream *stream, int size)
339 {
340         if (size <= stream->alloc_size)
341                 return;
342         
343         while (stream->alloc_size <= size) {
344                 if (stream->alloc_size < 4096)
345                         stream->alloc_size = 4096;
346                 else
347                         stream->alloc_size *= 2;
348         }
349         
350         stream->data = g_realloc (stream->data, stream->alloc_size);
351 }
352
353 static guint32
354 string_heap_insert (MonoDynamicStream *sh, const char *str)
355 {
356         guint32 idx;
357         guint32 len;
358         gpointer oldkey, oldval;
359
360         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
361                 return GPOINTER_TO_UINT (oldval);
362
363         len = strlen (str) + 1;
364         idx = sh->index;
365         
366         make_room_in_stream (sh, idx + len);
367
368         /*
369          * We strdup the string even if we already copy them in sh->data
370          * so that the string pointers in the hash remain valid even if
371          * we need to realloc sh->data. We may want to avoid that later.
372          */
373         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
374         memcpy (sh->data + idx, str, len);
375         sh->index += len;
376         return idx;
377 }
378
379 static guint32
380 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
381 {
382         char *name = mono_string_to_utf8 (str);
383         guint32 idx;
384         idx = string_heap_insert (sh, name);
385         g_free (name);
386         return idx;
387 }
388
389 #ifndef DISABLE_REFLECTION_EMIT
390 static void
391 string_heap_init (MonoDynamicStream *sh)
392 {
393         sh->index = 0;
394         sh->alloc_size = 4096;
395         sh->data = g_malloc (4096);
396         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
397         string_heap_insert (sh, "");
398 }
399 #endif
400
401 static guint32
402 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
403 {
404         guint32 idx;
405         
406         make_room_in_stream (stream, stream->index + len);
407         memcpy (stream->data + stream->index, data, len);
408         idx = stream->index;
409         stream->index += len;
410         /* 
411          * align index? Not without adding an additional param that controls it since
412          * we may store a blob value in pieces.
413          */
414         return idx;
415 }
416
417 static guint32
418 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
419 {
420         guint32 idx;
421         
422         make_room_in_stream (stream, stream->index + len);
423         memset (stream->data + stream->index, 0, len);
424         idx = stream->index;
425         stream->index += len;
426         return idx;
427 }
428
429 static void
430 stream_data_align (MonoDynamicStream *stream)
431 {
432         char buf [4] = {0};
433         guint32 count = stream->index % 4;
434
435         /* we assume the stream data will be aligned */
436         if (count)
437                 mono_image_add_stream_data (stream, buf, 4 - count);
438 }
439
440 #ifndef DISABLE_REFLECTION_EMIT
441 static int
442 mono_blob_entry_hash (const char* str)
443 {
444         guint len, h;
445         const char *end;
446         len = mono_metadata_decode_blob_size (str, &str);
447         if (len > 0) {
448                 end = str + len;
449                 h = *str;
450                 for (str += 1; str < end; str++)
451                         h = (h << 5) - h + *str;
452                 return h;
453         } else {
454                 return 0;
455         }
456 }
457
458 static gboolean
459 mono_blob_entry_equal (const char *str1, const char *str2) {
460         int len, len2;
461         const char *end1;
462         const char *end2;
463         len = mono_metadata_decode_blob_size (str1, &end1);
464         len2 = mono_metadata_decode_blob_size (str2, &end2);
465         if (len != len2)
466                 return 0;
467         return memcmp (end1, end2, len) == 0;
468 }
469 #endif
470 static guint32
471 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
472 {
473         guint32 idx;
474         char *copy;
475         gpointer oldkey, oldval;
476
477         copy = g_malloc (s1+s2);
478         memcpy (copy, b1, s1);
479         memcpy (copy + s1, b2, s2);
480         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
481                 g_free (copy);
482                 idx = GPOINTER_TO_UINT (oldval);
483         } else {
484                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
485                 mono_image_add_stream_data (&assembly->blob, b2, s2);
486                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
487         }
488         return idx;
489 }
490
491 static guint32
492 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
493 {
494         char blob_size [8];
495         char *b = blob_size;
496         guint32 size = buf->p - buf->buf;
497         /* store length */
498         g_assert (size <= (buf->end - buf->buf));
499         mono_metadata_encode_value (size, b, &b);
500         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
501 }
502
503 /*
504  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
505  * dest may be misaligned.
506  */
507 static void
508 swap_with_size (char *dest, const char* val, int len, int nelem) {
509 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
510         int elem;
511
512         for (elem = 0; elem < nelem; ++elem) {
513                 switch (len) {
514                 case 1:
515                         *dest = *val;
516                         break;
517                 case 2:
518                         dest [0] = val [1];
519                         dest [1] = val [0];
520                         break;
521                 case 4:
522                         dest [0] = val [3];
523                         dest [1] = val [2];
524                         dest [2] = val [1];
525                         dest [3] = val [0];
526                         break;
527                 case 8:
528                         dest [0] = val [7];
529                         dest [1] = val [6];
530                         dest [2] = val [5];
531                         dest [3] = val [4];
532                         dest [4] = val [3];
533                         dest [5] = val [2];
534                         dest [6] = val [1];
535                         dest [7] = val [0];
536                         break;
537                 default:
538                         g_assert_not_reached ();
539                 }
540                 dest += len;
541                 val += len;
542         }
543 #else
544         memcpy (dest, val, len * nelem);
545 #endif
546 }
547
548 static guint32
549 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
550 {
551         char blob_size [64];
552         char *b = blob_size;
553         guint32 idx = 0, len;
554
555         len = str->length * 2;
556         mono_metadata_encode_value (len, b, &b);
557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
558         {
559                 char *swapped = g_malloc (2 * mono_string_length (str));
560                 const char *p = (const char*)mono_string_chars (str);
561
562                 swap_with_size (swapped, p, 2, mono_string_length (str));
563                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
564                 g_free (swapped);
565         }
566 #else
567         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
568 #endif
569         return idx;
570 }
571
572 #ifndef DISABLE_REFLECTION_EMIT
573 static MonoClass *
574 default_class_from_mono_type (MonoType *type)
575 {
576         switch (type->type) {
577         case MONO_TYPE_OBJECT:
578                 return mono_defaults.object_class;
579         case MONO_TYPE_VOID:
580                 return mono_defaults.void_class;
581         case MONO_TYPE_BOOLEAN:
582                 return mono_defaults.boolean_class;
583         case MONO_TYPE_CHAR:
584                 return mono_defaults.char_class;
585         case MONO_TYPE_I1:
586                 return mono_defaults.sbyte_class;
587         case MONO_TYPE_U1:
588                 return mono_defaults.byte_class;
589         case MONO_TYPE_I2:
590                 return mono_defaults.int16_class;
591         case MONO_TYPE_U2:
592                 return mono_defaults.uint16_class;
593         case MONO_TYPE_I4:
594                 return mono_defaults.int32_class;
595         case MONO_TYPE_U4:
596                 return mono_defaults.uint32_class;
597         case MONO_TYPE_I:
598                 return mono_defaults.int_class;
599         case MONO_TYPE_U:
600                 return mono_defaults.uint_class;
601         case MONO_TYPE_I8:
602                 return mono_defaults.int64_class;
603         case MONO_TYPE_U8:
604                 return mono_defaults.uint64_class;
605         case MONO_TYPE_R4:
606                 return mono_defaults.single_class;
607         case MONO_TYPE_R8:
608                 return mono_defaults.double_class;
609         case MONO_TYPE_STRING:
610                 return mono_defaults.string_class;
611         default:
612                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
613                 g_assert_not_reached ();
614         }
615         
616         return NULL;
617 }
618 #endif
619
620 /*
621  * mono_class_get_ref_info:
622  *
623  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
624  */
625 gpointer
626 mono_class_get_ref_info (MonoClass *klass)
627 {
628         if (klass->ref_info_handle == 0)
629                 return NULL;
630         else
631                 return mono_gchandle_get_target (klass->ref_info_handle);
632 }
633
634 void
635 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
636 {
637         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
638         g_assert (klass->ref_info_handle != 0);
639 }
640
641 void
642 mono_class_free_ref_info (MonoClass *klass)
643 {
644         if (klass->ref_info_handle) {
645                 mono_gchandle_free (klass->ref_info_handle);
646                 klass->ref_info_handle = 0;
647         }
648 }
649
650 static void
651 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
652 {
653         int i;
654         MonoGenericInst *class_inst;
655         MonoClass *klass;
656
657         g_assert (gclass);
658
659         class_inst = gclass->context.class_inst;
660
661         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
662         klass = gclass->container_class;
663         sigbuffer_add_value (buf, klass->byval_arg.type);
664         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
665
666         sigbuffer_add_value (buf, class_inst->type_argc);
667         for (i = 0; i < class_inst->type_argc; ++i)
668                 encode_type (assembly, class_inst->type_argv [i], buf);
669
670 }
671
672 static void
673 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
674 {
675         if (!type) {
676                 g_assert_not_reached ();
677                 return;
678         }
679                 
680         if (type->byref)
681                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
682
683         switch (type->type){
684         case MONO_TYPE_VOID:
685         case MONO_TYPE_BOOLEAN:
686         case MONO_TYPE_CHAR:
687         case MONO_TYPE_I1:
688         case MONO_TYPE_U1:
689         case MONO_TYPE_I2:
690         case MONO_TYPE_U2:
691         case MONO_TYPE_I4:
692         case MONO_TYPE_U4:
693         case MONO_TYPE_I8:
694         case MONO_TYPE_U8:
695         case MONO_TYPE_R4:
696         case MONO_TYPE_R8:
697         case MONO_TYPE_I:
698         case MONO_TYPE_U:
699         case MONO_TYPE_STRING:
700         case MONO_TYPE_OBJECT:
701         case MONO_TYPE_TYPEDBYREF:
702                 sigbuffer_add_value (buf, type->type);
703                 break;
704         case MONO_TYPE_PTR:
705                 sigbuffer_add_value (buf, type->type);
706                 encode_type (assembly, type->data.type, buf);
707                 break;
708         case MONO_TYPE_SZARRAY:
709                 sigbuffer_add_value (buf, type->type);
710                 encode_type (assembly, &type->data.klass->byval_arg, buf);
711                 break;
712         case MONO_TYPE_VALUETYPE:
713         case MONO_TYPE_CLASS: {
714                 MonoClass *k = mono_class_from_mono_type (type);
715
716                 if (k->generic_container) {
717                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
718                         encode_generic_class (assembly, gclass, buf);
719                 } else {
720                         /*
721                          * Make sure we use the correct type.
722                          */
723                         sigbuffer_add_value (buf, k->byval_arg.type);
724                         /*
725                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
726                          * otherwise two typerefs could point to the same type, leading to
727                          * verification errors.
728                          */
729                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
730                 }
731                 break;
732         }
733         case MONO_TYPE_ARRAY:
734                 sigbuffer_add_value (buf, type->type);
735                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
736                 sigbuffer_add_value (buf, type->data.array->rank);
737                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
738                 sigbuffer_add_value (buf, 0);
739                 break;
740         case MONO_TYPE_GENERICINST:
741                 encode_generic_class (assembly, type->data.generic_class, buf);
742                 break;
743         case MONO_TYPE_VAR:
744         case MONO_TYPE_MVAR:
745                 sigbuffer_add_value (buf, type->type);
746                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
747                 break;
748         default:
749                 g_error ("need to encode type %x", type->type);
750         }
751 }
752
753 static void
754 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
755 {
756         if (!type) {
757                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
758                 return;
759         }
760
761         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
762 }
763
764 static void
765 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
766 {
767         int i;
768
769         if (modreq) {
770                 for (i = 0; i < mono_array_length (modreq); ++i) {
771                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
772                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
773                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
774                 }
775         }
776         if (modopt) {
777                 for (i = 0; i < mono_array_length (modopt); ++i) {
778                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
779                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
780                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
781                 }
782         }
783 }
784
785 #ifndef DISABLE_REFLECTION_EMIT
786 static guint32
787 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
788 {
789         SigBuffer buf;
790         int i;
791         guint32 nparams =  sig->param_count;
792         guint32 idx;
793
794         if (!assembly->save)
795                 return 0;
796
797         sigbuffer_init (&buf, 32);
798         /*
799          * FIXME: vararg, explicit_this, differenc call_conv values...
800          */
801         idx = sig->call_convention;
802         if (sig->hasthis)
803                 idx |= 0x20; /* hasthis */
804         if (sig->generic_param_count)
805                 idx |= 0x10; /* generic */
806         sigbuffer_add_byte (&buf, idx);
807         if (sig->generic_param_count)
808                 sigbuffer_add_value (&buf, sig->generic_param_count);
809         sigbuffer_add_value (&buf, nparams);
810         encode_type (assembly, sig->ret, &buf);
811         for (i = 0; i < nparams; ++i) {
812                 if (i == sig->sentinelpos)
813                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
814                 encode_type (assembly, sig->params [i], &buf);
815         }
816         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
817         sigbuffer_free (&buf);
818         return idx;
819 }
820 #endif
821
822 static guint32
823 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
824 {
825         /*
826          * FIXME: reuse code from method_encode_signature().
827          */
828         SigBuffer buf;
829         int i;
830         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
831         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
832         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
833         guint32 idx;
834
835         sigbuffer_init (&buf, 32);
836         /* LAMESPEC: all the call conv spec is foobared */
837         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
838         if (mb->call_conv & 2)
839                 idx |= 0x5; /* vararg */
840         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
841                 idx |= 0x20; /* hasthis */
842         if (ngparams)
843                 idx |= 0x10; /* generic */
844         sigbuffer_add_byte (&buf, idx);
845         if (ngparams)
846                 sigbuffer_add_value (&buf, ngparams);
847         sigbuffer_add_value (&buf, nparams + notypes);
848         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
849         encode_reflection_type (assembly, mb->rtype, &buf);
850         for (i = 0; i < nparams; ++i) {
851                 MonoArray *modreq = NULL;
852                 MonoArray *modopt = NULL;
853                 MonoReflectionType *pt;
854
855                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
856                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
857                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
858                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
859                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
860                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
861                 encode_reflection_type (assembly, pt, &buf);
862         }
863         if (notypes)
864                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
865         for (i = 0; i < notypes; ++i) {
866                 MonoReflectionType *pt;
867
868                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
869                 encode_reflection_type (assembly, pt, &buf);
870         }
871
872         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
873         sigbuffer_free (&buf);
874         return idx;
875 }
876
877 static guint32
878 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
879 {
880         MonoDynamicTable *table;
881         guint32 *values;
882         guint32 idx, sig_idx;
883         guint nl = mono_array_length (ilgen->locals);
884         SigBuffer buf;
885         int i;
886
887         sigbuffer_init (&buf, 32);
888         sigbuffer_add_value (&buf, 0x07);
889         sigbuffer_add_value (&buf, nl);
890         for (i = 0; i < nl; ++i) {
891                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
892                 
893                 if (lb->is_pinned)
894                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
895                 
896                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
897         }
898         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
899         sigbuffer_free (&buf);
900
901         if (assembly->standalonesig_cache == NULL)
902                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
903         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
904         if (idx)
905                 return idx;
906
907         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
908         idx = table->next_idx ++;
909         table->rows ++;
910         alloc_table (table, table->rows);
911         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
912
913         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
914
915         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
916
917         return idx;
918 }
919
920 static guint32
921 method_count_clauses (MonoReflectionILGen *ilgen)
922 {
923         guint32 num_clauses = 0;
924         int i;
925
926         MonoILExceptionInfo *ex_info;
927         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
928                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
929                 if (ex_info->handlers)
930                         num_clauses += mono_array_length (ex_info->handlers);
931                 else
932                         num_clauses++;
933         }
934
935         return num_clauses;
936 }
937
938 #ifndef DISABLE_REFLECTION_EMIT
939 static MonoExceptionClause*
940 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
941 {
942         MonoExceptionClause *clauses;
943         MonoExceptionClause *clause;
944         MonoILExceptionInfo *ex_info;
945         MonoILExceptionBlock *ex_block;
946         guint32 finally_start;
947         int i, j, clause_index;;
948
949         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
950
951         clause_index = 0;
952         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
953                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
954                 finally_start = ex_info->start + ex_info->len;
955                 if (!ex_info->handlers)
956                         continue;
957                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
958                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
959                         clause = &(clauses [clause_index]);
960
961                         clause->flags = ex_block->type;
962                         clause->try_offset = ex_info->start;
963
964                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
965                                 clause->try_len = finally_start - ex_info->start;
966                         else
967                                 clause->try_len = ex_info->len;
968                         clause->handler_offset = ex_block->start;
969                         clause->handler_len = ex_block->len;
970                         if (ex_block->extype) {
971                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
972                         } else {
973                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
974                                         clause->data.filter_offset = ex_block->filter_offset;
975                                 else
976                                         clause->data.filter_offset = 0;
977                         }
978                         finally_start = ex_block->start + ex_block->len;
979
980                         clause_index ++;
981                 }
982         }
983
984         return clauses;
985 }
986 #endif /* !DISABLE_REFLECTION_EMIT */
987
988 static guint32
989 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
990 {
991         char flags = 0;
992         guint32 idx;
993         guint32 code_size;
994         gint32 max_stack, i;
995         gint32 num_locals = 0;
996         gint32 num_exception = 0;
997         gint maybe_small;
998         guint32 fat_flags;
999         char fat_header [12];
1000         guint32 int_value;
1001         guint16 short_value;
1002         guint32 local_sig = 0;
1003         guint32 header_size = 12;
1004         MonoArray *code;
1005
1006         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1007                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1008                 return 0;
1009
1010         /*if (mb->name)
1011                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1012         if (mb->ilgen) {
1013                 code = mb->ilgen->code;
1014                 code_size = mb->ilgen->code_len;
1015                 max_stack = mb->ilgen->max_stack;
1016                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1017                 if (mb->ilgen->ex_handlers)
1018                         num_exception = method_count_clauses (mb->ilgen);
1019         } else {
1020                 code = mb->code;
1021                 if (code == NULL){
1022                         char *name = mono_string_to_utf8 (mb->name);
1023                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1024                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1025                         g_free (str);
1026                         g_free (name);
1027                         mono_raise_exception (exception);
1028                 }
1029
1030                 code_size = mono_array_length (code);
1031                 max_stack = 8; /* we probably need to run a verifier on the code... */
1032         }
1033
1034         stream_data_align (&assembly->code);
1035
1036         /* check for exceptions, maxstack, locals */
1037         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1038         if (maybe_small) {
1039                 if (code_size < 64 && !(code_size & 1)) {
1040                         flags = (code_size << 2) | 0x2;
1041                 } else if (code_size < 32 && (code_size & 1)) {
1042                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1043                 } else {
1044                         goto fat_header;
1045                 }
1046                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1047                 /* add to the fixup todo list */
1048                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1049                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1050                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1051                 return assembly->text_rva + idx;
1052         } 
1053 fat_header:
1054         if (num_locals)
1055                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1056         /* 
1057          * FIXME: need to set also the header size in fat_flags.
1058          * (and more sects and init locals flags)
1059          */
1060         fat_flags =  0x03;
1061         if (num_exception)
1062                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1063         if (mb->init_locals)
1064                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1065         fat_header [0] = fat_flags;
1066         fat_header [1] = (header_size / 4 ) << 4;
1067         short_value = GUINT16_TO_LE (max_stack);
1068         memcpy (fat_header + 2, &short_value, 2);
1069         int_value = GUINT32_TO_LE (code_size);
1070         memcpy (fat_header + 4, &int_value, 4);
1071         int_value = GUINT32_TO_LE (local_sig);
1072         memcpy (fat_header + 8, &int_value, 4);
1073         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1074         /* add to the fixup todo list */
1075         if (mb->ilgen && mb->ilgen->num_token_fixups)
1076                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1077         
1078         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1079         if (num_exception) {
1080                 unsigned char sheader [4];
1081                 MonoILExceptionInfo * ex_info;
1082                 MonoILExceptionBlock * ex_block;
1083                 int j;
1084
1085                 stream_data_align (&assembly->code);
1086                 /* always use fat format for now */
1087                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1088                 num_exception *= 6 * sizeof (guint32);
1089                 num_exception += 4; /* include the size of the header */
1090                 sheader [1] = num_exception & 0xff;
1091                 sheader [2] = (num_exception >> 8) & 0xff;
1092                 sheader [3] = (num_exception >> 16) & 0xff;
1093                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1094                 /* fat header, so we are already aligned */
1095                 /* reverse order */
1096                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1097                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1098                         if (ex_info->handlers) {
1099                                 int finally_start = ex_info->start + ex_info->len;
1100                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1101                                         guint32 val;
1102                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1103                                         /* the flags */
1104                                         val = GUINT32_TO_LE (ex_block->type);
1105                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1106                                         /* try offset */
1107                                         val = GUINT32_TO_LE (ex_info->start);
1108                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1109                                         /* need fault, too, probably */
1110                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1111                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1112                                         else
1113                                                 val = GUINT32_TO_LE (ex_info->len);
1114                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1115                                         /* handler offset */
1116                                         val = GUINT32_TO_LE (ex_block->start);
1117                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118                                         /* handler len */
1119                                         val = GUINT32_TO_LE (ex_block->len);
1120                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1121                                         finally_start = ex_block->start + ex_block->len;
1122                                         if (ex_block->extype) {
1123                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1124                                         } else {
1125                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1126                                                         val = ex_block->filter_offset;
1127                                                 else
1128                                                         val = 0;
1129                                         }
1130                                         val = GUINT32_TO_LE (val);
1131                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1132                                         /*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", 
1133                                                         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);*/
1134                                 }
1135                         } else {
1136                                 g_error ("No clauses for ex info block %d", i);
1137                         }
1138                 }
1139         }
1140         return assembly->text_rva + idx;
1141 }
1142
1143 static guint32
1144 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1145 {
1146         int i;
1147         MonoDynamicTable *table;
1148         guint32 *values;
1149         
1150         table = &assembly->tables [table_idx];
1151
1152         g_assert (col < table->columns);
1153
1154         values = table->values + table->columns;
1155         for (i = 1; i <= table->rows; ++i) {
1156                 if (values [col] == token)
1157                         return i;
1158                 values += table->columns;
1159         }
1160         return 0;
1161 }
1162
1163 /*
1164  * LOCKING: Acquires the loader lock. 
1165  */
1166 static MonoCustomAttrInfo*
1167 lookup_custom_attr (MonoImage *image, gpointer member)
1168 {
1169         MonoCustomAttrInfo* res;
1170
1171         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1172
1173         if (!res)
1174                 return NULL;
1175
1176         return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1177 }
1178
1179 static gboolean
1180 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1181 {
1182         /* FIXME: Need to do more checks */
1183         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1184                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1185
1186                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1187                         return FALSE;
1188         }
1189
1190         return TRUE;
1191 }
1192
1193 static MonoCustomAttrInfo*
1194 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1195 {
1196         int i, index, count, not_visible;
1197         MonoCustomAttrInfo *ainfo;
1198         MonoReflectionCustomAttr *cattr;
1199
1200         if (!cattrs)
1201                 return NULL;
1202         /* FIXME: check in assembly the Run flag is set */
1203
1204         count = mono_array_length (cattrs);
1205
1206         /* Skip nonpublic attributes since MS.NET seems to do the same */
1207         /* FIXME: This needs to be done more globally */
1208         not_visible = 0;
1209         for (i = 0; i < count; ++i) {
1210                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1211                 if (!custom_attr_visible (image, cattr))
1212                         not_visible ++;
1213         }
1214         count -= not_visible;
1215
1216         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1217
1218         ainfo->image = image;
1219         ainfo->num_attrs = count;
1220         ainfo->cached = alloc_img != NULL;
1221         index = 0;
1222         for (i = 0; i < count; ++i) {
1223                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1224                 if (custom_attr_visible (image, cattr)) {
1225                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1226                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1227                         ainfo->attrs [index].ctor = cattr->ctor->method;
1228                         ainfo->attrs [index].data = saved;
1229                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1230                         index ++;
1231                 }
1232         }
1233
1234         return ainfo;
1235 }
1236
1237 #ifndef DISABLE_REFLECTION_EMIT
1238 /*
1239  * LOCKING: Acquires the loader lock. 
1240  */
1241 static void
1242 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1243 {
1244         MonoCustomAttrInfo *ainfo, *tmp;
1245
1246         if (!cattrs || !mono_array_length (cattrs))
1247                 return;
1248
1249         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1250
1251         mono_loader_lock ();
1252         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1253         if (tmp)
1254                 mono_custom_attrs_free (tmp);
1255         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1256         mono_loader_unlock ();
1257
1258 }
1259 #endif
1260
1261 void
1262 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1263 {
1264         if (!ainfo->cached)
1265                 g_free (ainfo);
1266 }
1267
1268 /*
1269  * idx is the table index of the object
1270  * type is one of MONO_CUSTOM_ATTR_*
1271  */
1272 static void
1273 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1274 {
1275         MonoDynamicTable *table;
1276         MonoReflectionCustomAttr *cattr;
1277         guint32 *values;
1278         guint32 count, i, token;
1279         char blob_size [6];
1280         char *p = blob_size;
1281         
1282         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1283         if (!cattrs)
1284                 return;
1285         count = mono_array_length (cattrs);
1286         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1287         table->rows += count;
1288         alloc_table (table, table->rows);
1289         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1290         idx <<= MONO_CUSTOM_ATTR_BITS;
1291         idx |= type;
1292         for (i = 0; i < count; ++i) {
1293                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1294                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1295                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1296                 type = mono_metadata_token_index (token);
1297                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1298                 switch (mono_metadata_token_table (token)) {
1299                 case MONO_TABLE_METHOD:
1300                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1301                         break;
1302                 case MONO_TABLE_MEMBERREF:
1303                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1304                         break;
1305                 default:
1306                         g_warning ("got wrong token in custom attr");
1307                         continue;
1308                 }
1309                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1310                 p = blob_size;
1311                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1312                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1313                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1314                 values += MONO_CUSTOM_ATTR_SIZE;
1315                 ++table->next_idx;
1316         }
1317 }
1318
1319 static void
1320 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1321 {
1322         MonoDynamicTable *table;
1323         guint32 *values;
1324         guint32 count, i, idx;
1325         MonoReflectionPermissionSet *perm;
1326
1327         if (!permissions)
1328                 return;
1329
1330         count = mono_array_length (permissions);
1331         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1332         table->rows += count;
1333         alloc_table (table, table->rows);
1334
1335         for (i = 0; i < mono_array_length (permissions); ++i) {
1336                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1337
1338                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1339
1340                 idx = mono_metadata_token_index (parent_token);
1341                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1342                 switch (mono_metadata_token_table (parent_token)) {
1343                 case MONO_TABLE_TYPEDEF:
1344                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1345                         break;
1346                 case MONO_TABLE_METHOD:
1347                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1348                         break;
1349                 case MONO_TABLE_ASSEMBLY:
1350                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1351                         break;
1352                 default:
1353                         g_assert_not_reached ();
1354                 }
1355
1356                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1357                 values [MONO_DECL_SECURITY_PARENT] = idx;
1358                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1359
1360                 ++table->next_idx;
1361         }
1362 }
1363
1364 /*
1365  * Fill in the MethodDef and ParamDef tables for a method.
1366  * This is used for both normal methods and constructors.
1367  */
1368 static void
1369 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1370 {
1371         MonoDynamicTable *table;
1372         guint32 *values;
1373         guint i, count;
1374
1375         /* room in this table is already allocated */
1376         table = &assembly->tables [MONO_TABLE_METHOD];
1377         *mb->table_idx = table->next_idx ++;
1378         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1379         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1380         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1381         values [MONO_METHOD_FLAGS] = mb->attrs;
1382         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1383         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1384         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1385         
1386         table = &assembly->tables [MONO_TABLE_PARAM];
1387         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1388
1389         mono_image_add_decl_security (assembly, 
1390                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1391
1392         if (mb->pinfo) {
1393                 MonoDynamicTable *mtable;
1394                 guint32 *mvalues;
1395                 
1396                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1397                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1398                 
1399                 count = 0;
1400                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1401                         if (mono_array_get (mb->pinfo, gpointer, i))
1402                                 count++;
1403                 }
1404                 table->rows += count;
1405                 alloc_table (table, table->rows);
1406                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1407                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1408                         MonoReflectionParamBuilder *pb;
1409                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1410                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1411                                 values [MONO_PARAM_SEQUENCE] = i;
1412                                 if (pb->name != NULL) {
1413                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1414                                 } else {
1415                                         values [MONO_PARAM_NAME] = 0;
1416                                 }
1417                                 values += MONO_PARAM_SIZE;
1418                                 if (pb->marshal_info) {
1419                                         mtable->rows++;
1420                                         alloc_table (mtable, mtable->rows);
1421                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1422                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1423                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1424                                 }
1425                                 pb->table_idx = table->next_idx++;
1426                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1427                                         guint32 field_type = 0;
1428                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1429                                         mtable->rows ++;
1430                                         alloc_table (mtable, mtable->rows);
1431                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1432                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1433                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1434                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1435                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1436                                 }
1437                         }
1438                 }
1439         }
1440 }
1441
1442 #ifndef DISABLE_REFLECTION_EMIT
1443 static void
1444 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1445 {
1446         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1447
1448         rmb->ilgen = mb->ilgen;
1449         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1450         rmb->parameters = mb->parameters;
1451         rmb->generic_params = mb->generic_params;
1452         rmb->generic_container = mb->generic_container;
1453         rmb->opt_types = NULL;
1454         rmb->pinfo = mb->pinfo;
1455         rmb->attrs = mb->attrs;
1456         rmb->iattrs = mb->iattrs;
1457         rmb->call_conv = mb->call_conv;
1458         rmb->code = mb->code;
1459         rmb->type = mb->type;
1460         rmb->name = mb->name;
1461         rmb->table_idx = &mb->table_idx;
1462         rmb->init_locals = mb->init_locals;
1463         rmb->skip_visibility = FALSE;
1464         rmb->return_modreq = mb->return_modreq;
1465         rmb->return_modopt = mb->return_modopt;
1466         rmb->param_modreq = mb->param_modreq;
1467         rmb->param_modopt = mb->param_modopt;
1468         rmb->permissions = mb->permissions;
1469         rmb->mhandle = mb->mhandle;
1470         rmb->nrefs = 0;
1471         rmb->refs = NULL;
1472
1473         if (mb->dll) {
1474                 rmb->charset = mb->charset;
1475                 rmb->extra_flags = mb->extra_flags;
1476                 rmb->native_cc = mb->native_cc;
1477                 rmb->dllentry = mb->dllentry;
1478                 rmb->dll = mb->dll;
1479         }
1480 }
1481
1482 static void
1483 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1484 {
1485         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1486
1487         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1488
1489         rmb->ilgen = mb->ilgen;
1490         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1491         rmb->parameters = mb->parameters;
1492         rmb->generic_params = NULL;
1493         rmb->generic_container = NULL;
1494         rmb->opt_types = NULL;
1495         rmb->pinfo = mb->pinfo;
1496         rmb->attrs = mb->attrs;
1497         rmb->iattrs = mb->iattrs;
1498         rmb->call_conv = mb->call_conv;
1499         rmb->code = NULL;
1500         rmb->type = mb->type;
1501         rmb->name = mono_string_new (mono_domain_get (), name);
1502         rmb->table_idx = &mb->table_idx;
1503         rmb->init_locals = mb->init_locals;
1504         rmb->skip_visibility = FALSE;
1505         rmb->return_modreq = NULL;
1506         rmb->return_modopt = NULL;
1507         rmb->param_modreq = mb->param_modreq;
1508         rmb->param_modopt = mb->param_modopt;
1509         rmb->permissions = mb->permissions;
1510         rmb->mhandle = mb->mhandle;
1511         rmb->nrefs = 0;
1512         rmb->refs = NULL;
1513 }
1514
1515 static void
1516 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1517 {
1518         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1519
1520         rmb->ilgen = mb->ilgen;
1521         rmb->rtype = mb->rtype;
1522         rmb->parameters = mb->parameters;
1523         rmb->generic_params = NULL;
1524         rmb->generic_container = NULL;
1525         rmb->opt_types = NULL;
1526         rmb->pinfo = NULL;
1527         rmb->attrs = mb->attrs;
1528         rmb->iattrs = 0;
1529         rmb->call_conv = mb->call_conv;
1530         rmb->code = NULL;
1531         rmb->type = (MonoObject *) mb->owner;
1532         rmb->name = mb->name;
1533         rmb->table_idx = NULL;
1534         rmb->init_locals = mb->init_locals;
1535         rmb->skip_visibility = mb->skip_visibility;
1536         rmb->return_modreq = NULL;
1537         rmb->return_modopt = NULL;
1538         rmb->param_modreq = NULL;
1539         rmb->param_modopt = NULL;
1540         rmb->permissions = NULL;
1541         rmb->mhandle = mb->mhandle;
1542         rmb->nrefs = 0;
1543         rmb->refs = NULL;
1544 }       
1545 #endif
1546
1547 static void
1548 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1549 {
1550         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1551         MonoDynamicTable *table;
1552         guint32 *values;
1553         guint32 tok;
1554
1555         if (!mb->override_method)
1556                 return;
1557
1558         table = &assembly->tables [MONO_TABLE_METHODIMPL];
1559         table->rows ++;
1560         alloc_table (table, table->rows);
1561         values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1562         values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1563         values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1564
1565         tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1566         switch (mono_metadata_token_table (tok)) {
1567         case MONO_TABLE_MEMBERREF:
1568                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1569                 break;
1570         case MONO_TABLE_METHOD:
1571                 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1572                 break;
1573         default:
1574                 g_assert_not_reached ();
1575         }
1576         values [MONO_METHODIMPL_DECLARATION] = tok;
1577 }
1578
1579 #ifndef DISABLE_REFLECTION_EMIT
1580 static void
1581 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1582 {
1583         MonoDynamicTable *table;
1584         guint32 *values;
1585         ReflectionMethodBuilder rmb;
1586         int i;
1587
1588         reflection_methodbuilder_from_method_builder (&rmb, mb);
1589
1590         mono_image_basic_method (&rmb, assembly);
1591         mb->table_idx = *rmb.table_idx;
1592
1593         if (mb->dll) { /* It's a P/Invoke method */
1594                 guint32 moduleref;
1595                 /* map CharSet values to on-disk values */
1596                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1597                 int extra_flags = mb->extra_flags;
1598                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1599                 table->rows ++;
1600                 alloc_table (table, table->rows);
1601                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1602                 
1603                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1604                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1605                 if (mb->dllentry)
1606                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1607                 else
1608                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1610                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1611                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1612                         table->rows ++;
1613                         alloc_table (table, table->rows);
1614                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1615                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1616                 }
1617         }
1618
1619         if (mb->generic_params) {
1620                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1621                 table->rows += mono_array_length (mb->generic_params);
1622                 alloc_table (table, table->rows);
1623                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1624                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1625
1626                         mono_image_get_generic_param_info (
1627                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1628                 }
1629         }
1630
1631 }
1632
1633 static void
1634 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1635 {
1636         ReflectionMethodBuilder rmb;
1637
1638         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1639
1640         mono_image_basic_method (&rmb, assembly);
1641         mb->table_idx = *rmb.table_idx;
1642 }
1643 #endif
1644
1645 static char*
1646 type_get_fully_qualified_name (MonoType *type)
1647 {
1648         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1649 }
1650
1651 static char*
1652 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1653         MonoClass *klass;
1654         MonoAssembly *ta;
1655
1656         klass = mono_class_from_mono_type (type);
1657         if (!klass) 
1658                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1659         ta = klass->image->assembly;
1660         if (ta->dynamic || (ta == ass)) {
1661                 if (klass->generic_class || klass->generic_container)
1662                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1663                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1664                 else
1665                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1666         }
1667
1668         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1669 }
1670
1671 #ifndef DISABLE_REFLECTION_EMIT
1672 /*field_image is the image to which the eventual custom mods have been encoded against*/
1673 static guint32
1674 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1675 {
1676         SigBuffer buf;
1677         guint32 idx, i, token;
1678
1679         if (!assembly->save)
1680                 return 0;
1681
1682         sigbuffer_init (&buf, 32);
1683         
1684         sigbuffer_add_value (&buf, 0x06);
1685         /* encode custom attributes before the type */
1686         if (type->num_mods) {
1687                 for (i = 0; i < type->num_mods; ++i) {
1688                         if (field_image) {
1689                                 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1690                                 g_assert (class);
1691                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1692                         } else {
1693                                 token = type->modifiers [i].token;
1694                         }
1695
1696                         if (type->modifiers [i].required)
1697                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1698                         else
1699                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1700
1701                         sigbuffer_add_value (&buf, token);
1702                 }
1703         }
1704         encode_type (assembly, type, &buf);
1705         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1706         sigbuffer_free (&buf);
1707         return idx;
1708 }
1709 #endif
1710
1711 static guint32
1712 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1713 {
1714         SigBuffer buf;
1715         guint32 idx;
1716
1717         sigbuffer_init (&buf, 32);
1718         
1719         sigbuffer_add_value (&buf, 0x06);
1720         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1721         /* encode custom attributes before the type */
1722         encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1723         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1724         sigbuffer_free (&buf);
1725         return idx;
1726 }
1727
1728 static guint32
1729 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1730         char blob_size [64];
1731         char *b = blob_size;
1732         char *p, *box_val;
1733         char* buf;
1734         guint32 idx = 0, len = 0, dummy = 0;
1735 #ifdef ARM_FPU_FPA
1736 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1737         guint32 fpa_double [2];
1738         guint32 *fpa_p;
1739 #endif
1740 #endif
1741         
1742         p = buf = g_malloc (64);
1743         if (!val) {
1744                 *ret_type = MONO_TYPE_CLASS;
1745                 len = 4;
1746                 box_val = (char*)&dummy;
1747         } else {
1748                 box_val = ((char*)val) + sizeof (MonoObject);
1749                 *ret_type = val->vtable->klass->byval_arg.type;
1750         }
1751 handle_enum:
1752         switch (*ret_type) {
1753         case MONO_TYPE_BOOLEAN:
1754         case MONO_TYPE_U1:
1755         case MONO_TYPE_I1:
1756                 len = 1;
1757                 break;
1758         case MONO_TYPE_CHAR:
1759         case MONO_TYPE_U2:
1760         case MONO_TYPE_I2:
1761                 len = 2;
1762                 break;
1763         case MONO_TYPE_U4:
1764         case MONO_TYPE_I4:
1765         case MONO_TYPE_R4:
1766                 len = 4;
1767                 break;
1768         case MONO_TYPE_U8:
1769         case MONO_TYPE_I8:
1770                 len = 8;
1771                 break;
1772         case MONO_TYPE_R8:
1773                 len = 8;
1774 #ifdef ARM_FPU_FPA
1775 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1776                 fpa_p = (guint32*)box_val;
1777                 fpa_double [0] = fpa_p [1];
1778                 fpa_double [1] = fpa_p [0];
1779                 box_val = (char*)fpa_double;
1780 #endif
1781 #endif
1782                 break;
1783         case MONO_TYPE_VALUETYPE: {
1784                 MonoClass *klass = val->vtable->klass;
1785                 
1786                 if (klass->enumtype) {
1787                         *ret_type = mono_class_enum_basetype (klass)->type;
1788                         goto handle_enum;
1789                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1790                         len = 8;
1791                 } else 
1792                         g_error ("we can't encode valuetypes, we should have never reached this line");
1793                 break;
1794         }
1795         case MONO_TYPE_CLASS:
1796                 break;
1797         case MONO_TYPE_STRING: {
1798                 MonoString *str = (MonoString*)val;
1799                 /* there is no signature */
1800                 len = str->length * 2;
1801                 mono_metadata_encode_value (len, b, &b);
1802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1803                 {
1804                         char *swapped = g_malloc (2 * mono_string_length (str));
1805                         const char *p = (const char*)mono_string_chars (str);
1806
1807                         swap_with_size (swapped, p, 2, mono_string_length (str));
1808                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1809                         g_free (swapped);
1810                 }
1811 #else
1812                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1813 #endif
1814
1815                 g_free (buf);
1816                 return idx;
1817         }
1818         case MONO_TYPE_GENERICINST:
1819                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1820                 goto handle_enum;
1821         default:
1822                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1823         }
1824
1825         /* there is no signature */
1826         mono_metadata_encode_value (len, b, &b);
1827 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1828         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1829         swap_with_size (blob_size, box_val, len, 1);
1830         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1831 #else
1832         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1833 #endif
1834
1835         g_free (buf);
1836         return idx;
1837 }
1838
1839 static guint32
1840 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1841         char *str;
1842         SigBuffer buf;
1843         guint32 idx, len;
1844
1845         sigbuffer_init (&buf, 32);
1846
1847         sigbuffer_add_value (&buf, minfo->type);
1848
1849         switch (minfo->type) {
1850         case MONO_NATIVE_BYVALTSTR:
1851         case MONO_NATIVE_BYVALARRAY:
1852                 sigbuffer_add_value (&buf, minfo->count);
1853                 break;
1854         case MONO_NATIVE_LPARRAY:
1855                 if (minfo->eltype || minfo->has_size) {
1856                         sigbuffer_add_value (&buf, minfo->eltype);
1857                         if (minfo->has_size) {
1858                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1859                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1860
1861                                 /* LAMESPEC: ElemMult is undocumented */
1862                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1863                         }
1864                 }
1865                 break;
1866         case MONO_NATIVE_SAFEARRAY:
1867                 if (minfo->eltype)
1868                         sigbuffer_add_value (&buf, minfo->eltype);
1869                 break;
1870         case MONO_NATIVE_CUSTOM:
1871                 if (minfo->guid) {
1872                         str = mono_string_to_utf8 (minfo->guid);
1873                         len = strlen (str);
1874                         sigbuffer_add_value (&buf, len);
1875                         sigbuffer_add_mem (&buf, str, len);
1876                         g_free (str);
1877                 } else {
1878                         sigbuffer_add_value (&buf, 0);
1879                 }
1880                 /* native type name */
1881                 sigbuffer_add_value (&buf, 0);
1882                 /* custom marshaler type name */
1883                 if (minfo->marshaltype || minfo->marshaltyperef) {
1884                         if (minfo->marshaltyperef)
1885                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1886                         else
1887                                 str = mono_string_to_utf8 (minfo->marshaltype);
1888                         len = strlen (str);
1889                         sigbuffer_add_value (&buf, len);
1890                         sigbuffer_add_mem (&buf, str, len);
1891                         g_free (str);
1892                 } else {
1893                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1894                         sigbuffer_add_value (&buf, 0);
1895                 }
1896                 if (minfo->mcookie) {
1897                         str = mono_string_to_utf8 (minfo->mcookie);
1898                         len = strlen (str);
1899                         sigbuffer_add_value (&buf, len);
1900                         sigbuffer_add_mem (&buf, str, len);
1901                         g_free (str);
1902                 } else {
1903                         sigbuffer_add_value (&buf, 0);
1904                 }
1905                 break;
1906         default:
1907                 break;
1908         }
1909         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1910         sigbuffer_free (&buf);
1911         return idx;
1912 }
1913
1914 static void
1915 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1916 {
1917         MonoDynamicTable *table;
1918         guint32 *values;
1919
1920         /* maybe this fixup should be done in the C# code */
1921         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1922                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1923         table = &assembly->tables [MONO_TABLE_FIELD];
1924         fb->table_idx = table->next_idx ++;
1925         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1926         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1927         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1928         values [MONO_FIELD_FLAGS] = fb->attrs;
1929         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1930
1931         if (fb->offset != -1) {
1932                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1933                 table->rows ++;
1934                 alloc_table (table, table->rows);
1935                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1936                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1937                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1938         }
1939         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1940                 guint32 field_type = 0;
1941                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1942                 table->rows ++;
1943                 alloc_table (table, table->rows);
1944                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1945                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1946                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1947                 values [MONO_CONSTANT_TYPE] = field_type;
1948                 values [MONO_CONSTANT_PADDING] = 0;
1949         }
1950         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1951                 guint32 rva_idx;
1952                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1953                 table->rows ++;
1954                 alloc_table (table, table->rows);
1955                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1956                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1957                 /*
1958                  * We store it in the code section because it's simpler for now.
1959                  */
1960                 if (fb->rva_data) {
1961                         if (mono_array_length (fb->rva_data) >= 10)
1962                                 stream_data_align (&assembly->code);
1963                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1964                 } else
1965                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1966                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1967         }
1968         if (fb->marshal_info) {
1969                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1970                 table->rows ++;
1971                 alloc_table (table, table->rows);
1972                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1973                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1974                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1975         }
1976 }
1977
1978 static guint32
1979 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1980 {
1981         SigBuffer buf;
1982         guint32 nparams = 0;
1983         MonoReflectionMethodBuilder *mb = fb->get_method;
1984         MonoReflectionMethodBuilder *smb = fb->set_method;
1985         guint32 idx, i;
1986
1987         if (mb && mb->parameters)
1988                 nparams = mono_array_length (mb->parameters);
1989         if (!mb && smb && smb->parameters)
1990                 nparams = mono_array_length (smb->parameters) - 1;
1991         sigbuffer_init (&buf, 32);
1992         if (fb->call_conv & 0x20)
1993                 sigbuffer_add_byte (&buf, 0x28);
1994         else
1995                 sigbuffer_add_byte (&buf, 0x08);
1996         sigbuffer_add_value (&buf, nparams);
1997         if (mb) {
1998                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1999                 for (i = 0; i < nparams; ++i) {
2000                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2001                         encode_reflection_type (assembly, pt, &buf);
2002                 }
2003         } else if (smb && smb->parameters) {
2004                 /* the property type is the last param */
2005                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2006                 for (i = 0; i < nparams; ++i) {
2007                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2008                         encode_reflection_type (assembly, pt, &buf);
2009                 }
2010         } else {
2011                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2012         }
2013
2014         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2015         sigbuffer_free (&buf);
2016         return idx;
2017 }
2018
2019 static void
2020 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2021 {
2022         MonoDynamicTable *table;
2023         guint32 *values;
2024         guint num_methods = 0;
2025         guint32 semaidx;
2026
2027         /* 
2028          * we need to set things in the following tables:
2029          * PROPERTYMAP (info already filled in _get_type_info ())
2030          * PROPERTY    (rows already preallocated in _get_type_info ())
2031          * METHOD      (method info already done with the generic method code)
2032          * METHODSEMANTICS
2033          * CONSTANT
2034          */
2035         table = &assembly->tables [MONO_TABLE_PROPERTY];
2036         pb->table_idx = table->next_idx ++;
2037         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2038         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2039         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2040         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2041
2042         /* FIXME: we still don't handle 'other' methods */
2043         if (pb->get_method) num_methods ++;
2044         if (pb->set_method) num_methods ++;
2045
2046         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2047         table->rows += num_methods;
2048         alloc_table (table, table->rows);
2049
2050         if (pb->get_method) {
2051                 semaidx = table->next_idx ++;
2052                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2053                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2054                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2055                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2056         }
2057         if (pb->set_method) {
2058                 semaidx = table->next_idx ++;
2059                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2060                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2061                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2062                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2063         }
2064         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2065                 guint32 field_type = 0;
2066                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2067                 table->rows ++;
2068                 alloc_table (table, table->rows);
2069                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2070                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2071                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2072                 values [MONO_CONSTANT_TYPE] = field_type;
2073                 values [MONO_CONSTANT_PADDING] = 0;
2074         }
2075 }
2076
2077 static void
2078 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2079 {
2080         MonoDynamicTable *table;
2081         guint32 *values;
2082         guint num_methods = 0;
2083         guint32 semaidx;
2084
2085         /* 
2086          * we need to set things in the following tables:
2087          * EVENTMAP (info already filled in _get_type_info ())
2088          * EVENT    (rows already preallocated in _get_type_info ())
2089          * METHOD      (method info already done with the generic method code)
2090          * METHODSEMANTICS
2091          */
2092         table = &assembly->tables [MONO_TABLE_EVENT];
2093         eb->table_idx = table->next_idx ++;
2094         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2095         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2096         values [MONO_EVENT_FLAGS] = eb->attrs;
2097         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2098
2099         /*
2100          * FIXME: we still don't handle 'other' methods 
2101          */
2102         if (eb->add_method) num_methods ++;
2103         if (eb->remove_method) num_methods ++;
2104         if (eb->raise_method) num_methods ++;
2105
2106         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2107         table->rows += num_methods;
2108         alloc_table (table, table->rows);
2109
2110         if (eb->add_method) {
2111                 semaidx = table->next_idx ++;
2112                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2113                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2114                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2115                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2116         }
2117         if (eb->remove_method) {
2118                 semaidx = table->next_idx ++;
2119                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2120                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2121                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2122                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2123         }
2124         if (eb->raise_method) {
2125                 semaidx = table->next_idx ++;
2126                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2127                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2128                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2129                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2130         }
2131 }
2132
2133 static void
2134 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2135 {
2136         MonoDynamicTable *table;
2137         guint32 num_constraints, i;
2138         guint32 *values;
2139         guint32 table_idx;
2140
2141         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2142         num_constraints = gparam->iface_constraints ?
2143                 mono_array_length (gparam->iface_constraints) : 0;
2144         table->rows += num_constraints;
2145         if (gparam->base_type)
2146                 table->rows++;
2147         alloc_table (table, table->rows);
2148
2149         if (gparam->base_type) {
2150                 table_idx = table->next_idx ++;
2151                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2152
2153                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2154                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2155                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2156         }
2157
2158         for (i = 0; i < num_constraints; i++) {
2159                 MonoReflectionType *constraint = mono_array_get (
2160                         gparam->iface_constraints, gpointer, i);
2161
2162                 table_idx = table->next_idx ++;
2163                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2164
2165                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2166                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2167                         assembly, mono_reflection_type_get_handle (constraint));
2168         }
2169 }
2170
2171 static void
2172 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2173 {
2174         GenericParamTableEntry *entry;
2175
2176         /*
2177          * The GenericParam table must be sorted according to the `owner' field.
2178          * We need to do this sorting prior to writing the GenericParamConstraint
2179          * table, since we have to use the final GenericParam table indices there
2180          * and they must also be sorted.
2181          */
2182
2183         entry = g_new0 (GenericParamTableEntry, 1);
2184         entry->owner = owner;
2185         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2186         MOVING_GC_REGISTER (&entry->gparam);
2187         entry->gparam = gparam;
2188         
2189         g_ptr_array_add (assembly->gen_params, entry);
2190 }
2191
2192 static void
2193 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2194 {
2195         MonoDynamicTable *table;
2196         MonoGenericParam *param;
2197         guint32 *values;
2198         guint32 table_idx;
2199
2200         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2201         table_idx = table->next_idx ++;
2202         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2203
2204         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2205
2206         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2207         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2208         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2209         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2210
2211         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2212
2213         encode_constraints (entry->gparam, table_idx, assembly);
2214 }
2215
2216 static guint32
2217 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2218 {
2219         MonoDynamicTable *table;
2220         guint32 token;
2221         guint32 *values;
2222         guint32 cols [MONO_ASSEMBLY_SIZE];
2223         const char *pubkey;
2224         guint32 publen;
2225
2226         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2227                 return token;
2228
2229         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2230                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2231                 token = table->next_idx ++;
2232                 table->rows ++;
2233                 alloc_table (table, table->rows);
2234                 values = table->values + token * MONO_MODULEREF_SIZE;
2235                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2236
2237                 token <<= MONO_RESOLTION_SCOPE_BITS;
2238                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2239                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2240
2241                 return token;
2242         }
2243         
2244         if (image->assembly->dynamic)
2245                 /* FIXME: */
2246                 memset (cols, 0, sizeof (cols));
2247         else {
2248                 /* image->assembly->image is the manifest module */
2249                 image = image->assembly->image;
2250                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2251         }
2252
2253         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2254         token = table->next_idx ++;
2255         table->rows ++;
2256         alloc_table (table, table->rows);
2257         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2258         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2259         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2260         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2261         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2262         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2263         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2264         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2265         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2266
2267         if (strcmp ("", image->assembly->aname.culture)) {
2268                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2269                                 image->assembly->aname.culture);
2270         }
2271
2272         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2273                 guchar pubtoken [9];
2274                 pubtoken [0] = 8;
2275                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2276                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2277         } else {
2278                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2279         }
2280         token <<= MONO_RESOLTION_SCOPE_BITS;
2281         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2282         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2283         return token;
2284 }
2285
2286 static guint32
2287 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2288 {
2289         MonoDynamicTable *table;
2290         guint32 *values;
2291         guint32 token;
2292         SigBuffer buf;
2293
2294         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2295                 return token;
2296
2297         sigbuffer_init (&buf, 32);
2298         switch (type->type) {
2299         case MONO_TYPE_FNPTR:
2300         case MONO_TYPE_PTR:
2301         case MONO_TYPE_SZARRAY:
2302         case MONO_TYPE_ARRAY:
2303         case MONO_TYPE_VAR:
2304         case MONO_TYPE_MVAR:
2305         case MONO_TYPE_GENERICINST:
2306                 encode_type (assembly, type, &buf);
2307                 break;
2308         case MONO_TYPE_CLASS:
2309         case MONO_TYPE_VALUETYPE: {
2310                 MonoClass *k = mono_class_from_mono_type (type);
2311                 if (!k || !k->generic_container) {
2312                         sigbuffer_free (&buf);
2313                         return 0;
2314                 }
2315                 encode_type (assembly, type, &buf);
2316                 break;
2317         }
2318         default:
2319                 sigbuffer_free (&buf);
2320                 return 0;
2321         }
2322
2323         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2324         if (assembly->save) {
2325                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2326                 alloc_table (table, table->rows + 1);
2327                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2328                 values [MONO_TYPESPEC_SIGNATURE] = token;
2329         }
2330         sigbuffer_free (&buf);
2331
2332         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2333         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2334         table->next_idx ++;
2335         return token;
2336 }
2337
2338 static guint32
2339 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2340 {
2341         MonoDynamicTable *table;
2342         guint32 *values;
2343         guint32 token, scope, enclosing;
2344         MonoClass *klass;
2345
2346         /* if the type requires a typespec, we must try that first*/
2347         if (try_typespec && (token = create_typespec (assembly, type)))
2348                 return token;
2349         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2350         if (token)
2351                 return token;
2352         klass = mono_class_from_mono_type (type);
2353         if (!klass)
2354                 klass = mono_class_from_mono_type (type);
2355
2356         /*
2357          * If it's in the same module and not a generic type parameter:
2358          */
2359         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2360                         (type->type != MONO_TYPE_MVAR)) {
2361                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2362                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2363                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2364                 return token;
2365         }
2366
2367         if (klass->nested_in) {
2368                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2369                 /* get the typeref idx of the enclosing type */
2370                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2371                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2372         } else {
2373                 scope = resolution_scope_from_image (assembly, klass->image);
2374         }
2375         table = &assembly->tables [MONO_TABLE_TYPEREF];
2376         if (assembly->save) {
2377                 alloc_table (table, table->rows + 1);
2378                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2379                 values [MONO_TYPEREF_SCOPE] = scope;
2380                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2381                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2382         }
2383         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2384         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2385         table->next_idx ++;
2386         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2387         return token;
2388 }
2389
2390 /*
2391  * Despite the name, we handle also TypeSpec (with the above helper).
2392  */
2393 static guint32
2394 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2395 {
2396         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2397 }
2398
2399 #ifndef DISABLE_REFLECTION_EMIT
2400 static guint32
2401 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2402 {
2403         MonoDynamicTable *table;
2404         guint32 *values;
2405         guint32 token, pclass;
2406
2407         switch (parent & MONO_TYPEDEFORREF_MASK) {
2408         case MONO_TYPEDEFORREF_TYPEREF:
2409                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2410                 break;
2411         case MONO_TYPEDEFORREF_TYPESPEC:
2412                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2413                 break;
2414         case MONO_TYPEDEFORREF_TYPEDEF:
2415                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2416                 break;
2417         default:
2418                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2419                 return 0;
2420         }
2421         /* extract the index */
2422         parent >>= MONO_TYPEDEFORREF_BITS;
2423
2424         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2425
2426         if (assembly->save) {
2427                 alloc_table (table, table->rows + 1);
2428                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2429                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2430                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2431                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2432         }
2433
2434         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2435         table->next_idx ++;
2436
2437         return token;
2438 }
2439
2440 /*
2441  * Insert a memberef row into the metadata: the token that point to the memberref
2442  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2443  * mono_image_get_fieldref_token()).
2444  * The sig param is an index to an already built signature.
2445  */
2446 static guint32
2447 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2448 {
2449         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2450         return mono_image_add_memberef_row (assembly, parent, name, sig);
2451 }
2452
2453
2454 static guint32
2455 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2456 {
2457         guint32 token;
2458         MonoMethodSignature *sig;
2459         
2460         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2461
2462         if (create_typespec) {
2463                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2464                 if (token)
2465                         return token;
2466         } 
2467
2468         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2469         if (token && !create_typespec)
2470                 return token;
2471
2472         g_assert (!method->is_inflated);
2473         if (!token) {
2474                 /*
2475                  * A methodref signature can't contain an unmanaged calling convention.
2476                  */
2477                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2478                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2479                         sig->call_convention = MONO_CALL_DEFAULT;
2480                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2481                         method->name,  method_encode_signature (assembly, sig));
2482                 g_free (sig);
2483                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2484         }
2485
2486         if (create_typespec) {
2487                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2488                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2489                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2490
2491                 if (assembly->save) {
2492                         guint32 *values;
2493
2494                         alloc_table (table, table->rows + 1);
2495                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2496                         values [MONO_METHODSPEC_METHOD] = token;
2497                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2498                 }
2499
2500                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2501                 table->next_idx ++;
2502                 /*methodspec and memberef tokens are diferent, */
2503                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2504                 return token;
2505         }
2506         return token;
2507 }
2508
2509 static guint32
2510 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2511 {
2512         guint32 token, parent, sig;
2513         ReflectionMethodBuilder rmb;
2514         char *name;
2515         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2516         
2517         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2518         if (token)
2519                 return token;
2520
2521         name = mono_string_to_utf8 (method->name);
2522         reflection_methodbuilder_from_method_builder (&rmb, method);
2523
2524         /*
2525          * A methodref signature can't contain an unmanaged calling convention.
2526          * Since some flags are encoded as part of call_conv, we need to check against it.
2527         */
2528         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2529                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2530
2531         sig = method_builder_encode_signature (assembly, &rmb);
2532
2533         if (tb->generic_params)
2534                 parent = create_generic_typespec (assembly, tb);
2535         else
2536                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2537
2538         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2539
2540         g_free (name);
2541         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2542         return token;
2543 }
2544
2545 static guint32
2546 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2547                                      const gchar *name, guint32 sig)
2548 {
2549         MonoDynamicTable *table;
2550         guint32 token;
2551         guint32 *values;
2552         
2553         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2554
2555         if (assembly->save) {
2556                 alloc_table (table, table->rows + 1);
2557                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2558                 values [MONO_MEMBERREF_CLASS] = original;
2559                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2560                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2561         }
2562
2563         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2564         table->next_idx ++;
2565
2566         return token;
2567 }
2568
2569 static guint32
2570 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2571 {
2572         SigBuffer buf;
2573         int i;
2574         guint32 nparams = mono_array_length (mb->generic_params);
2575         guint32 idx;
2576
2577         if (!assembly->save)
2578                 return 0;
2579
2580         sigbuffer_init (&buf, 32);
2581
2582         sigbuffer_add_value (&buf, 0xa);
2583         sigbuffer_add_value (&buf, nparams);
2584
2585         for (i = 0; i < nparams; i++) {
2586                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2587                 sigbuffer_add_value (&buf, i);
2588         }
2589
2590         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2591         sigbuffer_free (&buf);
2592         return idx;
2593 }
2594
2595 static guint32
2596 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2597 {
2598         MonoDynamicTable *table;
2599         guint32 *values;
2600         guint32 token, mtoken = 0;
2601
2602         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2603         if (token)
2604                 return token;
2605
2606         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2607
2608         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2609         switch (mono_metadata_token_table (mtoken)) {
2610         case MONO_TABLE_MEMBERREF:
2611                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2612                 break;
2613         case MONO_TABLE_METHOD:
2614                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2615                 break;
2616         default:
2617                 g_assert_not_reached ();
2618         }
2619
2620         if (assembly->save) {
2621                 alloc_table (table, table->rows + 1);
2622                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2623                 values [MONO_METHODSPEC_METHOD] = mtoken;
2624                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2625         }
2626
2627         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2628         table->next_idx ++;
2629
2630         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2631         return token;
2632 }
2633
2634 static guint32
2635 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2636 {
2637         guint32 token;
2638
2639         if (mb->generic_params && create_methodspec) 
2640                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2641
2642         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2643         if (token)
2644                 return token;
2645
2646         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2647         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2648         return token;
2649 }
2650
2651 static guint32
2652 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2653 {
2654         guint32 token, parent, sig;
2655         ReflectionMethodBuilder rmb;
2656         char *name;
2657         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2658         
2659         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2660         if (token)
2661                 return token;
2662
2663         g_assert (tb->generic_params);
2664
2665         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2666
2667         parent = create_generic_typespec (assembly, tb);
2668         name = mono_string_to_utf8 (rmb.name);
2669         sig = method_builder_encode_signature (assembly, &rmb);
2670
2671         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2672
2673         g_free (name);
2674         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2675         return token;
2676 }
2677 #endif
2678
2679 static gboolean
2680 is_field_on_inst (MonoClassField *field)
2681 {
2682         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2683 }
2684
2685 /*
2686  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2687  */
2688 static MonoType*
2689 get_field_on_inst_generic_type (MonoClassField *field)
2690 {
2691         MonoClass *class, *gtd;
2692         MonoDynamicGenericClass *dgclass;
2693         int field_index;
2694
2695         g_assert (is_field_on_inst (field));
2696
2697         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2698
2699         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2700                 field_index = field - dgclass->fields;
2701                 return dgclass->field_generic_types [field_index];              
2702         }
2703
2704         class = field->parent;
2705         gtd = class->generic_class->container_class;
2706
2707         if (field >= class->fields && field - class->fields < class->field.count) {
2708                 field_index = field - class->fields;
2709                 return gtd->fields [field_index].type;
2710         }
2711
2712         g_assert_not_reached ();
2713         return 0;
2714 }
2715
2716 #ifndef DISABLE_REFLECTION_EMIT
2717 static guint32
2718 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2719 {
2720         MonoType *type;
2721         guint32 token;
2722
2723         g_assert (field);
2724         g_assert (field->parent);
2725
2726         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2727         if (token)
2728                 return token;
2729
2730         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2731                 int index = field - field->parent->fields;
2732                 type = field->parent->generic_class->container_class->fields [index].type;
2733         } else {
2734                 if (is_field_on_inst (field))
2735                         type = get_field_on_inst_generic_type (field);
2736                 else
2737                         type = field->type;
2738         }
2739         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2740                                                                                         mono_field_get_name (field),
2741                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2742         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2743         return token;
2744 }
2745
2746 static guint32
2747 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2748 {
2749         guint32 token;
2750         MonoClass *klass;
2751         MonoGenericClass *gclass;
2752         MonoDynamicGenericClass *dgclass;
2753         MonoType *type;
2754         char *name;
2755
2756         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2757         if (token)
2758                 return token;
2759         if (is_sre_field_builder (mono_object_class (f->fb))) {
2760                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2761                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2762                 klass = mono_class_from_mono_type (type);
2763                 gclass = type->data.generic_class;
2764                 g_assert (gclass->is_dynamic);
2765                 dgclass = (MonoDynamicGenericClass *) gclass;
2766
2767                 name = mono_string_to_utf8 (fb->name);
2768                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2769                                                                                                 field_encode_signature (assembly, fb));
2770                 g_free (name);          
2771         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2772                 guint32 sig;
2773                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2774
2775                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2776                 klass = mono_class_from_mono_type (type);
2777
2778                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2779                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2780         } else {
2781                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2782                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2783         }
2784
2785         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2786         return token;
2787 }
2788
2789 static guint32
2790 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2791 {
2792         guint32 sig, token;
2793         MonoClass *klass;
2794         MonoGenericClass *gclass;
2795         MonoType *type;
2796
2797         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2798
2799         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2800         if (token)
2801                 return token;
2802
2803         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2804                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2805                 MonoDynamicGenericClass *dgclass;
2806                 ReflectionMethodBuilder rmb;
2807                 char *name;
2808
2809                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2810                 klass = mono_class_from_mono_type (type);
2811
2812                 gclass = type->data.generic_class;
2813                 g_assert (gclass->is_dynamic);
2814                 dgclass = (MonoDynamicGenericClass *) gclass;
2815
2816                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2817
2818                 name = mono_string_to_utf8 (rmb.name);
2819
2820                 sig = method_builder_encode_signature (assembly, &rmb);
2821
2822                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2823                 g_free (name);
2824         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2825                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2826
2827                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2828                 klass = mono_class_from_mono_type (type);
2829
2830                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2831                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2832         } else {
2833                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2834                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2835         }
2836
2837
2838         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2839         return token;
2840 }
2841
2842 static MonoMethod*
2843 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2844 {
2845         MonoClass *klass;
2846         MonoGenericContext tmp_context;
2847         MonoType **type_argv;
2848         MonoGenericInst *ginst;
2849         MonoMethod *method, *inflated;
2850         int count, i;
2851
2852         method = inflate_method (m->inst, (MonoObject*)m->mb);
2853
2854         klass = method->klass;
2855
2856         if (m->method_args == NULL)
2857                 return method;
2858
2859         if (method->is_inflated)
2860                 method = ((MonoMethodInflated *) method)->declaring;
2861
2862         count = mono_array_length (m->method_args);
2863
2864         type_argv = g_new0 (MonoType *, count);
2865         for (i = 0; i < count; i++) {
2866                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2867                 type_argv [i] = mono_reflection_type_get_handle (garg);
2868         }
2869         ginst = mono_metadata_get_generic_inst (count, type_argv);
2870         g_free (type_argv);
2871
2872         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2873         tmp_context.method_inst = ginst;
2874
2875         inflated = mono_class_inflate_generic_method (method, &tmp_context);
2876         return inflated;
2877 }
2878
2879 static guint32
2880 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2881 {
2882         guint32 sig, token = 0;
2883         MonoType *type;
2884         MonoClass *klass;
2885
2886         if (m->method_args) {
2887                 MonoMethod *inflated;
2888
2889                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2890                 if (create_methodspec)
2891                         token = mono_image_get_methodspec_token (assembly, inflated);
2892                 else
2893                         token = mono_image_get_inflated_method_token (assembly, inflated);
2894                 return token;
2895         }
2896
2897         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2898         if (token)
2899                 return token;
2900
2901         if (is_sre_method_builder (mono_object_class (m->mb))) {
2902                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2903                 MonoGenericClass *gclass;
2904                 ReflectionMethodBuilder rmb;
2905                 char *name;
2906
2907                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2908                 klass = mono_class_from_mono_type (type);
2909                 gclass = type->data.generic_class;
2910                 g_assert (gclass->is_dynamic);
2911
2912                 reflection_methodbuilder_from_method_builder (&rmb, mb);
2913
2914                 name = mono_string_to_utf8 (rmb.name);
2915
2916                 sig = method_builder_encode_signature (assembly, &rmb);
2917
2918                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2919                 g_free (name);          
2920         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2921                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2922
2923                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2924                 klass = mono_class_from_mono_type (type);
2925
2926                 sig = method_encode_signature (assembly, mono_method_signature (mm));
2927                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2928         } else {
2929                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2930                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2931         }
2932
2933         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2934         return token;
2935 }
2936
2937 static guint32
2938 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2939 {
2940         SigBuffer buf;
2941         int i;
2942         guint32 nparams = context->method_inst->type_argc;
2943         guint32 idx;
2944
2945         if (!assembly->save)
2946                 return 0;
2947
2948         sigbuffer_init (&buf, 32);
2949         /*
2950          * FIXME: vararg, explicit_this, differenc call_conv values...
2951          */
2952         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2953         sigbuffer_add_value (&buf, nparams);
2954
2955         for (i = 0; i < nparams; i++)
2956                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2957
2958         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2959         sigbuffer_free (&buf);
2960         return idx;
2961 }
2962
2963 static guint32
2964 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2965 {
2966         MonoDynamicTable *table;
2967         guint32 *values;
2968         guint32 token, mtoken = 0, sig;
2969         MonoMethodInflated *imethod;
2970         MonoMethod *declaring;
2971
2972         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2973
2974         g_assert (method->is_inflated);
2975         imethod = (MonoMethodInflated *) method;
2976         declaring = imethod->declaring;
2977
2978         sig = method_encode_signature (assembly, mono_method_signature (declaring));
2979         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2980
2981         if (!mono_method_signature (declaring)->generic_param_count)
2982                 return mtoken;
2983
2984         switch (mono_metadata_token_table (mtoken)) {
2985         case MONO_TABLE_MEMBERREF:
2986                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2987                 break;
2988         case MONO_TABLE_METHOD:
2989                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2990                 break;
2991         default:
2992                 g_assert_not_reached ();
2993         }
2994
2995         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2996
2997         if (assembly->save) {
2998                 alloc_table (table, table->rows + 1);
2999                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3000                 values [MONO_METHODSPEC_METHOD] = mtoken;
3001                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3002         }
3003
3004         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3005         table->next_idx ++;
3006
3007         return token;
3008 }
3009
3010 static guint32
3011 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3012 {
3013         MonoMethodInflated *imethod;
3014         guint32 token;
3015         
3016         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3017         if (token)
3018                 return token;
3019
3020         g_assert (method->is_inflated);
3021         imethod = (MonoMethodInflated *) method;
3022
3023         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3024                 token = method_encode_methodspec (assembly, method);
3025         } else {
3026                 guint32 sig = method_encode_signature (
3027                         assembly, mono_method_signature (imethod->declaring));
3028                 token = mono_image_get_memberref_token (
3029                         assembly, &method->klass->byval_arg, method->name, sig);
3030         }
3031
3032         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3033         return token;
3034 }
3035
3036 static guint32
3037 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3038 {
3039         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3040         guint32 sig, token;
3041
3042         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3043         token = mono_image_get_memberref_token (
3044                 assembly, &m->klass->byval_arg, m->name, sig);
3045
3046         return token;
3047 }
3048
3049 static guint32
3050 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3051 {
3052         MonoDynamicTable *table;
3053         MonoClass *klass;
3054         MonoType *type;
3055         guint32 *values;
3056         guint32 token;
3057         SigBuffer buf;
3058         int count, i;
3059
3060         /*
3061          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3062          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3063          * Because of this, we must not insert it into the `typeref' hash table.
3064          */
3065         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3066         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3067         if (token)
3068                 return token;
3069
3070         sigbuffer_init (&buf, 32);
3071
3072         g_assert (tb->generic_params);
3073         klass = mono_class_from_mono_type (type);
3074
3075         if (tb->generic_container)
3076                 mono_reflection_create_generic_class (tb);
3077
3078         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3079         g_assert (klass->generic_container);
3080         sigbuffer_add_value (&buf, klass->byval_arg.type);
3081         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3082
3083         count = mono_array_length (tb->generic_params);
3084         sigbuffer_add_value (&buf, count);
3085         for (i = 0; i < count; i++) {
3086                 MonoReflectionGenericParam *gparam;
3087
3088                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3089
3090                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3091         }
3092
3093         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3094
3095         if (assembly->save) {
3096                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3097                 alloc_table (table, table->rows + 1);
3098                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3099                 values [MONO_TYPESPEC_SIGNATURE] = token;
3100         }
3101         sigbuffer_free (&buf);
3102
3103         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3104         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3105         table->next_idx ++;
3106         return token;
3107 }
3108
3109 /*
3110  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3111  */
3112 static MonoType*
3113 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3114 {
3115         int i, count, len, pos;
3116         MonoType *t;
3117
3118         count = 0;
3119         if (modreq)
3120                 count += mono_array_length (modreq);
3121         if (modopt)
3122                 count += mono_array_length (modopt);
3123
3124         if (count == 0)
3125                 return mono_metadata_type_dup (NULL, type);
3126
3127         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3128         t = g_malloc (len);
3129         memcpy (t, type, MONO_SIZEOF_TYPE);
3130
3131         t->num_mods = count;
3132         pos = 0;
3133         if (modreq) {
3134                 for (i = 0; i < mono_array_length (modreq); ++i) {
3135                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3136                         t->modifiers [pos].required = 1;
3137                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3138                         pos ++;
3139                 }
3140         }
3141         if (modopt) {
3142                 for (i = 0; i < mono_array_length (modopt); ++i) {
3143                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3144                         t->modifiers [pos].required = 0;
3145                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3146                         pos ++;
3147                 }
3148         }
3149
3150         return t;
3151 }
3152
3153 static guint32
3154 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3155 {
3156         MonoDynamicTable *table;
3157         MonoClass *klass;
3158         MonoType *custom = NULL;
3159         guint32 *values;
3160         guint32 token, pclass, parent, sig;
3161         gchar *name;
3162
3163         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3164         if (token)
3165                 return token;
3166
3167         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3168         name = mono_string_to_utf8 (fb->name);
3169
3170         /* fb->type does not include the custom modifiers */
3171         /* FIXME: We should do this in one place when a fieldbuilder is created */
3172         if (fb->modreq || fb->modopt) {
3173                 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3174                 sig = fieldref_encode_signature (assembly, NULL, custom);
3175                 g_free (custom);
3176         } else {
3177                 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3178         }
3179
3180         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3181         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3182         
3183         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3184         parent >>= MONO_TYPEDEFORREF_BITS;
3185
3186         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3187
3188         if (assembly->save) {
3189                 alloc_table (table, table->rows + 1);
3190                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3191                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3192                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3193                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3194         }
3195
3196         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3197         table->next_idx ++;
3198         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3199         g_free (name);
3200         return token;
3201 }
3202
3203 static guint32
3204 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3205 {
3206         SigBuffer buf;
3207         guint32 nargs;
3208         guint32 size;
3209         guint32 i, idx;
3210
3211         if (!assembly->save)
3212                 return 0;
3213
3214         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3215         g_assert (helper->type == 2);
3216
3217         if (helper->arguments)
3218                 nargs = mono_array_length (helper->arguments);
3219         else
3220                 nargs = 0;
3221
3222         size = 10 + (nargs * 10);
3223         
3224         sigbuffer_init (&buf, 32);
3225
3226         /* Encode calling convention */
3227         /* Change Any to Standard */
3228         if ((helper->call_conv & 0x03) == 0x03)
3229                 helper->call_conv = 0x01;
3230         /* explicit_this implies has_this */
3231         if (helper->call_conv & 0x40)
3232                 helper->call_conv &= 0x20;
3233
3234         if (helper->call_conv == 0) { /* Unmanaged */
3235                 idx = helper->unmanaged_call_conv - 1;
3236         } else {
3237                 /* Managed */
3238                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3239                 if (helper->call_conv & 0x02) /* varargs */
3240                         idx += 0x05;
3241         }
3242
3243         sigbuffer_add_byte (&buf, idx);
3244         sigbuffer_add_value (&buf, nargs);
3245         encode_reflection_type (assembly, helper->return_type, &buf);
3246         for (i = 0; i < nargs; ++i) {
3247                 MonoArray *modreqs = NULL;
3248                 MonoArray *modopts = NULL;
3249                 MonoReflectionType *pt;
3250
3251                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3252                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3253                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3254                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3255
3256                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3257                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3258                 encode_reflection_type (assembly, pt, &buf);
3259         }
3260         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3261         sigbuffer_free (&buf);
3262
3263         return idx;
3264 }
3265
3266 static guint32 
3267 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3268 {
3269         guint32 idx;
3270         MonoDynamicTable *table;
3271         guint32 *values;
3272
3273         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3274         idx = table->next_idx ++;
3275         table->rows ++;
3276         alloc_table (table, table->rows);
3277         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3278
3279         values [MONO_STAND_ALONE_SIGNATURE] =
3280                 mono_reflection_encode_sighelper (assembly, helper);
3281
3282         return idx;
3283 }
3284
3285 static int
3286 reflection_cc_to_file (int call_conv) {
3287         switch (call_conv & 0x3) {
3288         case 0:
3289         case 1: return MONO_CALL_DEFAULT;
3290         case 2: return MONO_CALL_VARARG;
3291         default:
3292                 g_assert_not_reached ();
3293         }
3294         return 0;
3295 }
3296 #endif /* !DISABLE_REFLECTION_EMIT */
3297
3298 typedef struct {
3299         MonoType *parent;
3300         MonoMethodSignature *sig;
3301         char *name;
3302         guint32 token;
3303 } ArrayMethod;
3304
3305 #ifndef DISABLE_REFLECTION_EMIT
3306 static guint32
3307 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3308 {
3309         guint32 nparams, i;
3310         GList *tmp;
3311         char *name;
3312         MonoMethodSignature *sig;
3313         ArrayMethod *am;
3314         MonoType *mtype;
3315
3316         name = mono_string_to_utf8 (m->name);
3317         nparams = mono_array_length (m->parameters);
3318         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3319         sig->hasthis = 1;
3320         sig->sentinelpos = -1;
3321         sig->call_convention = reflection_cc_to_file (m->call_conv);
3322         sig->param_count = nparams;
3323         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3324         mtype = mono_reflection_type_get_handle (m->parent);
3325         for (i = 0; i < nparams; ++i)
3326                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3327
3328         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3329                 am = tmp->data;
3330                 if (strcmp (name, am->name) == 0 && 
3331                                 mono_metadata_type_equal (am->parent, mtype) &&
3332                                 mono_metadata_signature_equal (am->sig, sig)) {
3333                         g_free (name);
3334                         g_free (sig);
3335                         m->table_idx = am->token & 0xffffff;
3336                         return am->token;
3337                 }
3338         }
3339         am = g_new0 (ArrayMethod, 1);
3340         am->name = name;
3341         am->sig = sig;
3342         am->parent = mtype;
3343         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3344                 method_encode_signature (assembly, sig));
3345         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3346         m->table_idx = am->token & 0xffffff;
3347         return am->token;
3348 }
3349
3350 /*
3351  * Insert into the metadata tables all the info about the TypeBuilder tb.
3352  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3353  */
3354 static void
3355 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3356 {
3357         MonoDynamicTable *table;
3358         guint *values;
3359         int i, is_object = 0, is_system = 0;
3360         char *n;
3361
3362         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3363         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3364         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3365         n = mono_string_to_utf8 (tb->name);
3366         if (strcmp (n, "Object") == 0)
3367                 is_object++;
3368         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3369         g_free (n);
3370         n = mono_string_to_utf8 (tb->nspace);
3371         if (strcmp (n, "System") == 0)
3372                 is_system++;
3373         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3374         g_free (n);
3375         if (tb->parent && !(is_system && is_object) && 
3376                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3377                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3378         } else {
3379                 values [MONO_TYPEDEF_EXTENDS] = 0;
3380         }
3381         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3382         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3383
3384         /*
3385          * if we have explicitlayout or sequentiallayouts, output data in the
3386          * ClassLayout table.
3387          */
3388         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3389                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3390                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3391                 table->rows++;
3392                 alloc_table (table, table->rows);
3393                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3394                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3395                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3396                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3397         }
3398
3399         /* handle interfaces */
3400         if (tb->interfaces) {
3401                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3402                 i = table->rows;
3403                 table->rows += mono_array_length (tb->interfaces);
3404                 alloc_table (table, table->rows);
3405                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3406                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3407                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3408                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3409                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3410                         values += MONO_INTERFACEIMPL_SIZE;
3411                 }
3412         }
3413
3414         /* handle fields */
3415         if (tb->fields) {
3416                 table = &assembly->tables [MONO_TABLE_FIELD];
3417                 table->rows += tb->num_fields;
3418                 alloc_table (table, table->rows);
3419                 for (i = 0; i < tb->num_fields; ++i)
3420                         mono_image_get_field_info (
3421                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3422         }
3423
3424         /* handle constructors */
3425         if (tb->ctors) {
3426                 table = &assembly->tables [MONO_TABLE_METHOD];
3427                 table->rows += mono_array_length (tb->ctors);
3428                 alloc_table (table, table->rows);
3429                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3430                         mono_image_get_ctor_info (domain,
3431                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3432         }
3433
3434         /* handle methods */
3435         if (tb->methods) {
3436                 table = &assembly->tables [MONO_TABLE_METHOD];
3437                 table->rows += tb->num_methods;
3438                 alloc_table (table, table->rows);
3439                 for (i = 0; i < tb->num_methods; ++i)
3440                         mono_image_get_method_info (
3441                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3442         }
3443
3444         /* Do the same with properties etc.. */
3445         if (tb->events && mono_array_length (tb->events)) {
3446                 table = &assembly->tables [MONO_TABLE_EVENT];
3447                 table->rows += mono_array_length (tb->events);
3448                 alloc_table (table, table->rows);
3449                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3450                 table->rows ++;
3451                 alloc_table (table, table->rows);
3452                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3453                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3454                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3455                 for (i = 0; i < mono_array_length (tb->events); ++i)
3456                         mono_image_get_event_info (
3457                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3458         }
3459         if (tb->properties && mono_array_length (tb->properties)) {
3460                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3461                 table->rows += mono_array_length (tb->properties);
3462                 alloc_table (table, table->rows);
3463                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3464                 table->rows ++;
3465                 alloc_table (table, table->rows);
3466                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3467                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3468                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3469                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3470                         mono_image_get_property_info (
3471                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3472         }
3473
3474         /* handle generic parameters */
3475         if (tb->generic_params) {
3476                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3477                 table->rows += mono_array_length (tb->generic_params);
3478                 alloc_table (table, table->rows);
3479                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3480                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3481
3482                         mono_image_get_generic_param_info (
3483                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3484                 }
3485         }
3486
3487         mono_image_add_decl_security (assembly, 
3488                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3489
3490         if (tb->subtypes) {
3491                 MonoDynamicTable *ntable;
3492                 
3493                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3494                 ntable->rows += mono_array_length (tb->subtypes);
3495                 alloc_table (ntable, ntable->rows);
3496                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3497
3498                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3499                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3500
3501                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3502                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3503                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3504                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3505                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3506                                 ntable->next_idx, ntable->rows);*/
3507                         values += MONO_NESTED_CLASS_SIZE;
3508                         ntable->next_idx++;
3509                 }
3510         }
3511 }
3512 #endif
3513
3514 static void
3515 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3516 {
3517         int i;
3518
3519         mono_ptr_array_append (*types, type);
3520
3521         if (!type->subtypes)
3522                 return;
3523
3524         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3525                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3526                 collect_types (types, subtype);
3527         }
3528 }
3529
3530 static gint
3531 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3532 {
3533         if ((*type1)->table_idx < (*type2)->table_idx)
3534                 return -1;
3535         else
3536                 if ((*type1)->table_idx > (*type2)->table_idx)
3537                         return 1;
3538         else
3539                 return 0;
3540 }
3541
3542 static void
3543 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3544         int i;
3545
3546         if (!pinfo)
3547                 return;
3548         for (i = 0; i < mono_array_length (pinfo); ++i) {
3549                 MonoReflectionParamBuilder *pb;
3550                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3551                 if (!pb)
3552                         continue;
3553                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3554         }
3555 }
3556
3557 static void
3558 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3559         int i;
3560         
3561         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3562         if (tb->fields) {
3563                 for (i = 0; i < tb->num_fields; ++i) {
3564                         MonoReflectionFieldBuilder* fb;
3565                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3566                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3567                 }
3568         }
3569         if (tb->events) {
3570                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3571                         MonoReflectionEventBuilder* eb;
3572                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3573                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3574                 }
3575         }
3576         if (tb->properties) {
3577                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3578                         MonoReflectionPropertyBuilder* pb;
3579                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3580                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3581                 }
3582         }
3583         if (tb->ctors) {
3584                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3585                         MonoReflectionCtorBuilder* cb;
3586                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3587                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3588                         params_add_cattrs (assembly, cb->pinfo);
3589                 }
3590         }
3591
3592         if (tb->methods) {
3593                 for (i = 0; i < tb->num_methods; ++i) {
3594                         MonoReflectionMethodBuilder* mb;
3595                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3596                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3597                         params_add_cattrs (assembly, mb->pinfo);
3598                 }
3599         }
3600
3601         if (tb->subtypes) {
3602                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3603                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3604         }
3605 }
3606
3607 static void
3608 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3609 {
3610         int i;
3611         
3612         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3613
3614         if (moduleb->global_methods) {
3615                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3616                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3617                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3618                         params_add_cattrs (assembly, mb->pinfo);
3619                 }
3620         }
3621
3622         if (moduleb->global_fields) {
3623                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3624                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3625                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3626                 }
3627         }
3628         
3629         if (moduleb->types) {
3630                 for (i = 0; i < moduleb->num_types; ++i)
3631                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3632         }
3633 }
3634
3635 static void
3636 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3637 {
3638         MonoDynamicTable *table;
3639         guint32 *values;
3640         char blob_size [6];
3641         guchar hash [20];
3642         char *b = blob_size;
3643         char *dir, *path;
3644
3645         table = &assembly->tables [MONO_TABLE_FILE];
3646         table->rows++;
3647         alloc_table (table, table->rows);
3648         values = table->values + table->next_idx * MONO_FILE_SIZE;
3649         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3650         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3651         if (module->image->dynamic) {
3652                 /* This depends on the fact that the main module is emitted last */
3653                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3654                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3655         } else {
3656                 dir = NULL;
3657                 path = g_strdup (module->image->name);
3658         }
3659         mono_sha1_get_digest_from_file (path, hash);
3660         g_free (dir);
3661         g_free (path);
3662         mono_metadata_encode_value (20, b, &b);
3663         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3664         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3665         table->next_idx ++;
3666 }
3667
3668 static void
3669 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3670 {
3671         MonoDynamicTable *table;
3672         int i;
3673
3674         table = &assembly->tables [MONO_TABLE_MODULE];
3675         mb->table_idx = table->next_idx ++;
3676         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3677         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3678         i /= 16;
3679         ++i;
3680         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3681         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3682         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3683         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3684 }
3685
3686 static guint32
3687 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3688         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3689 {
3690         MonoDynamicTable *table;
3691         guint32 *values;
3692         guint32 visib, res;
3693
3694         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3695         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3696                 return 0;
3697
3698         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3699         table->rows++;
3700         alloc_table (table, table->rows);
3701         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3702
3703         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3704         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3705         if (klass->nested_in)
3706                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3707         else
3708                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3709         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3710         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3711
3712         res = table->next_idx;
3713
3714         table->next_idx ++;
3715
3716         /* Emit nested types */
3717         if (klass->ext && klass->ext->nested_classes) {
3718                 GList *tmp;
3719
3720                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3721                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3722         }
3723
3724         return res;
3725 }
3726
3727 static void
3728 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3729         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3730 {
3731         MonoClass *klass;
3732         guint32 idx, i;
3733
3734         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3735
3736         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3737
3738         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3739                                                                                                    parent_index, assembly);
3740
3741         /* 
3742          * Emit nested types
3743          * We need to do this ourselves since klass->nested_classes is not set up.
3744          */
3745         if (tb->subtypes) {
3746                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3747                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3748         }
3749 }
3750
3751 static void
3752 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3753         guint32 module_index, MonoDynamicImage *assembly)
3754 {
3755         MonoImage *image = module->image;
3756         MonoTableInfo  *t;
3757         guint32 i;
3758
3759         t = &image->tables [MONO_TABLE_TYPEDEF];
3760
3761         for (i = 0; i < t->rows; ++i) {
3762                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3763
3764                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3765                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3766         }
3767 }
3768
3769 static void
3770 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3771 {
3772         MonoDynamicTable *table;
3773         guint32 *values;
3774         guint32 scope, scope_idx, impl, current_idx;
3775         gboolean forwarder = TRUE;
3776         gpointer iter = NULL;
3777         MonoClass *nested;
3778
3779         if (klass->nested_in) {
3780                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3781                 forwarder = FALSE;
3782         } else {
3783                 scope = resolution_scope_from_image (assembly, klass->image);
3784                 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3785                 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3786                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3787         }
3788
3789         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3790
3791         table->rows++;
3792         alloc_table (table, table->rows);
3793         current_idx = table->next_idx;
3794         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3795
3796         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3797         values [MONO_EXP_TYPE_TYPEDEF] = 0;
3798         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3799         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3800         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3801
3802         table->next_idx++;
3803
3804         while ((nested = mono_class_get_nested_types (klass, &iter)))
3805                 add_exported_type (assemblyb, assembly, nested, current_idx);
3806 }
3807
3808 static void
3809 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3810 {
3811         MonoClass *klass;
3812         int i;
3813
3814         if (!assemblyb->type_forwarders)
3815                 return;
3816
3817         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3818                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3819                 MonoType *type;
3820                 if (!t)
3821                         continue;
3822
3823                 type = mono_reflection_type_get_handle (t);
3824                 g_assert (type);
3825
3826                 klass = mono_class_from_mono_type (type);
3827
3828                 add_exported_type (assemblyb, assembly, klass, 0);
3829         }
3830 }
3831
3832 #define align_pointer(base,p)\
3833         do {\
3834                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3835                 if (__diff & 3)\
3836                         (p) += 4 - (__diff & 3);\
3837         } while (0)
3838
3839 static int
3840 compare_constants (const void *a, const void *b)
3841 {
3842         const guint32 *a_values = a;
3843         const guint32 *b_values = b;
3844         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3845 }
3846
3847 static int
3848 compare_semantics (const void *a, const void *b)
3849 {
3850         const guint32 *a_values = a;
3851         const guint32 *b_values = b;
3852         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3853         if (assoc)
3854                 return assoc;
3855         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3856 }
3857
3858 static int
3859 compare_custom_attrs (const void *a, const void *b)
3860 {
3861         const guint32 *a_values = a;
3862         const guint32 *b_values = b;
3863
3864         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3865 }
3866
3867 static int
3868 compare_field_marshal (const void *a, const void *b)
3869 {
3870         const guint32 *a_values = a;
3871         const guint32 *b_values = b;
3872
3873         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3874 }
3875
3876 static int
3877 compare_nested (const void *a, const void *b)
3878 {
3879         const guint32 *a_values = a;
3880         const guint32 *b_values = b;
3881
3882         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3883 }
3884
3885 static int
3886 compare_genericparam (const void *a, const void *b)
3887 {
3888         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3889         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3890
3891         if ((*b_entry)->owner == (*a_entry)->owner)
3892                 return 
3893                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3894                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3895         else
3896                 return (*a_entry)->owner - (*b_entry)->owner;
3897 }
3898
3899 static int
3900 compare_declsecurity_attrs (const void *a, const void *b)
3901 {
3902         const guint32 *a_values = a;
3903         const guint32 *b_values = b;
3904
3905         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3906 }
3907
3908 static int
3909 compare_interface_impl (const void *a, const void *b)
3910 {
3911         const guint32 *a_values = a;
3912         const guint32 *b_values = b;
3913
3914         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3915         if (klass)
3916                 return klass;
3917
3918         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3919 }
3920
3921 static void
3922 pad_heap (MonoDynamicStream *sh)
3923 {
3924         if (sh->index & 3) {
3925                 int sz = 4 - (sh->index & 3);
3926                 memset (sh->data + sh->index, 0, sz);
3927                 sh->index += sz;
3928         }
3929 }
3930
3931 struct StreamDesc {
3932         const char *name;
3933         MonoDynamicStream *stream;
3934 };
3935
3936 /*
3937  * build_compressed_metadata() fills in the blob of data that represents the 
3938  * raw metadata as it will be saved in the PE file. The five streams are output 
3939  * and the metadata tables are comnpressed from the guint32 array representation, 
3940  * to the compressed on-disk format.
3941  */
3942 static void
3943 build_compressed_metadata (MonoDynamicImage *assembly)
3944 {
3945         MonoDynamicTable *table;
3946         int i;
3947         guint64 valid_mask = 0;
3948         guint64 sorted_mask;
3949         guint32 heapt_size = 0;
3950         guint32 meta_size = 256; /* allow for header and other stuff */
3951         guint32 table_offset;
3952         guint32 ntables = 0;
3953         guint64 *int64val;
3954         guint32 *int32val;
3955         guint16 *int16val;
3956         MonoImage *meta;
3957         unsigned char *p;
3958         struct StreamDesc stream_desc [5];
3959
3960         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3961         for (i = 0; i < assembly->gen_params->len; i++){
3962                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3963                 write_generic_param_entry (assembly, entry);
3964         }
3965
3966         stream_desc [0].name  = "#~";
3967         stream_desc [0].stream = &assembly->tstream;
3968         stream_desc [1].name  = "#Strings";
3969         stream_desc [1].stream = &assembly->sheap;
3970         stream_desc [2].name  = "#US";
3971         stream_desc [2].stream = &assembly->us;
3972         stream_desc [3].name  = "#Blob";
3973         stream_desc [3].stream = &assembly->blob;
3974         stream_desc [4].name  = "#GUID";
3975         stream_desc [4].stream = &assembly->guid;
3976         
3977         /* tables that are sorted */
3978         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3979                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3980                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3981                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3982                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3983                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3984                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3985         
3986         /* Compute table sizes */
3987         /* the MonoImage has already been created in mono_image_basic_init() */
3988         meta = &assembly->image;
3989
3990         /* sizes should be multiple of 4 */
3991         pad_heap (&assembly->blob);
3992         pad_heap (&assembly->guid);
3993         pad_heap (&assembly->sheap);
3994         pad_heap (&assembly->us);
3995
3996         /* Setup the info used by compute_sizes () */
3997         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3998         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3999         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4000
4001         meta_size += assembly->blob.index;
4002         meta_size += assembly->guid.index;
4003         meta_size += assembly->sheap.index;
4004         meta_size += assembly->us.index;
4005
4006         for (i=0; i < MONO_TABLE_NUM; ++i)
4007                 meta->tables [i].rows = assembly->tables [i].rows;
4008         
4009         for (i = 0; i < MONO_TABLE_NUM; i++){
4010                 if (meta->tables [i].rows == 0)
4011                         continue;
4012                 valid_mask |= (guint64)1 << i;
4013                 ntables ++;
4014                 meta->tables [i].row_size = mono_metadata_compute_size (
4015                         meta, i, &meta->tables [i].size_bitfield);
4016                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4017         }
4018         heapt_size += 24; /* #~ header size */
4019         heapt_size += ntables * 4;
4020         /* make multiple of 4 */
4021         heapt_size += 3;
4022         heapt_size &= ~3;
4023         meta_size += heapt_size;
4024         meta->raw_metadata = g_malloc0 (meta_size);
4025         p = (unsigned char*)meta->raw_metadata;
4026         /* the metadata signature */
4027         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4028         /* version numbers and 4 bytes reserved */
4029         int16val = (guint16*)p;
4030         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4031         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4032         p += 8;
4033         /* version string */
4034         int32val = (guint32*)p;
4035         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4036         p += 4;
4037         memcpy (p, meta->version, strlen (meta->version));
4038         p += GUINT32_FROM_LE (*int32val);
4039         align_pointer (meta->raw_metadata, p);
4040         int16val = (guint16*)p;
4041         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4042         *int16val = GUINT16_TO_LE (5); /* number of streams */
4043         p += 4;
4044
4045         /*
4046          * write the stream info.
4047          */
4048         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4049         table_offset += 3; table_offset &= ~3;
4050
4051         assembly->tstream.index = heapt_size;
4052         for (i = 0; i < 5; ++i) {
4053                 int32val = (guint32*)p;
4054                 stream_desc [i].stream->offset = table_offset;
4055                 *int32val++ = GUINT32_TO_LE (table_offset);
4056                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4057                 table_offset += GUINT32_FROM_LE (*int32val);
4058                 table_offset += 3; table_offset &= ~3;
4059                 p += 8;
4060                 strcpy ((char*)p, stream_desc [i].name);
4061                 p += strlen (stream_desc [i].name) + 1;
4062                 align_pointer (meta->raw_metadata, p);
4063         }
4064         /* 
4065          * now copy the data, the table stream header and contents goes first.
4066          */
4067         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4068         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4069         int32val = (guint32*)p;
4070         *int32val = GUINT32_TO_LE (0); /* reserved */
4071         p += 4;
4072
4073         *p++ = 2; /* version */
4074         *p++ = 0;
4075
4076         if (meta->idx_string_wide)
4077                 *p |= 0x01;
4078         if (meta->idx_guid_wide)
4079                 *p |= 0x02;
4080         if (meta->idx_blob_wide)
4081                 *p |= 0x04;
4082         ++p;
4083         *p++ = 1; /* reserved */
4084         int64val = (guint64*)p;
4085         *int64val++ = GUINT64_TO_LE (valid_mask);
4086         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4087         p += 16;
4088         int32val = (guint32*)p;
4089         for (i = 0; i < MONO_TABLE_NUM; i++){
4090                 if (meta->tables [i].rows == 0)
4091                         continue;
4092                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4093         }
4094         p = (unsigned char*)int32val;
4095
4096         /* sort the tables that still need sorting */
4097         table = &assembly->tables [MONO_TABLE_CONSTANT];
4098         if (table->rows)
4099                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4100         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4101         if (table->rows)
4102                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4103         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4104         if (table->rows)
4105                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4106         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4107         if (table->rows)
4108                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4109         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4110         if (table->rows)
4111                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4112         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4113         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4114         if (table->rows)
4115                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4116         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4117         if (table->rows)
4118                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4119
4120         /* compress the tables */
4121         for (i = 0; i < MONO_TABLE_NUM; i++){
4122                 int row, col;
4123                 guint32 *values;
4124                 guint32 bitfield = meta->tables [i].size_bitfield;
4125                 if (!meta->tables [i].rows)
4126                         continue;
4127                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4128                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4129                 meta->tables [i].base = (char*)p;
4130                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4131                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4132                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4133                                 switch (mono_metadata_table_size (bitfield, col)) {
4134                                 case 1:
4135                                         *p++ = values [col];
4136                                         break;
4137                                 case 2:
4138                                         *p++ = values [col] & 0xff;
4139                                         *p++ = (values [col] >> 8) & 0xff;
4140                                         break;
4141                                 case 4:
4142                                         *p++ = values [col] & 0xff;
4143                                         *p++ = (values [col] >> 8) & 0xff;
4144                                         *p++ = (values [col] >> 16) & 0xff;
4145                                         *p++ = (values [col] >> 24) & 0xff;
4146                                         break;
4147                                 default:
4148                                         g_assert_not_reached ();
4149                                 }
4150                         }
4151                 }
4152                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4153         }
4154         
4155         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4156         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4157         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4158         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4159         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4160
4161         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4162 }
4163
4164 /*
4165  * Some tables in metadata need to be sorted according to some criteria, but
4166  * when methods and fields are first created with reflection, they may be assigned a token
4167  * that doesn't correspond to the final token they will get assigned after the sorting.
4168  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4169  * with the reflection objects that represent them. Once all the tables are set up, the 
4170  * reflection objects will contains the correct table index. fixup_method() will fixup the
4171  * tokens for the method with ILGenerator @ilgen.
4172  */
4173 static void
4174 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4175 {
4176         guint32 code_idx = GPOINTER_TO_UINT (value);
4177         MonoReflectionILTokenInfo *iltoken;
4178         MonoReflectionFieldBuilder *field;
4179         MonoReflectionCtorBuilder *ctor;
4180         MonoReflectionMethodBuilder *method;
4181         MonoReflectionTypeBuilder *tb;
4182         MonoReflectionArrayMethod *am;
4183         guint32 i, idx = 0;
4184         unsigned char *target;
4185
4186         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4187                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4188                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4189                 switch (target [3]) {
4190                 case MONO_TABLE_FIELD:
4191                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4192                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4193                                 idx = field->table_idx;
4194                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4195                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4196                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4197                         } else {
4198                                 g_assert_not_reached ();
4199                         }
4200                         break;
4201                 case MONO_TABLE_METHOD:
4202                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4203                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4204                                 idx = method->table_idx;
4205                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4206                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4207                                 idx = ctor->table_idx;
4208                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4209                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4210                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4211                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4212                         } else {
4213                                 g_assert_not_reached ();
4214                         }
4215                         break;
4216                 case MONO_TABLE_TYPEDEF:
4217                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4218                                 g_assert_not_reached ();
4219                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4220                         idx = tb->table_idx;
4221                         break;
4222                 case MONO_TABLE_MEMBERREF:
4223                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4224                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4225                                 idx = am->table_idx;
4226                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4227                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4228                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4229                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4230                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4231                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4232                                 continue;
4233                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4234                                 continue;
4235                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4236                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4237                                 g_assert (is_field_on_inst (f));
4238                                 continue;
4239                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4240                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4241                                 continue;
4242                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4243                                 continue;
4244                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4245                                 continue;
4246                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4247                                 continue;
4248                         } else {
4249                                 g_assert_not_reached ();
4250                         }
4251                         break;
4252                 case MONO_TABLE_METHODSPEC:
4253                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4254                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4255                                 g_assert (mono_method_signature (m)->generic_param_count);
4256                                 continue;
4257                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4258                                 continue;
4259                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4260                                 continue;
4261                         } else {
4262                                 g_assert_not_reached ();
4263                         }
4264                         break;
4265                 default:
4266                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4267                 }
4268                 target [0] = idx & 0xff;
4269                 target [1] = (idx >> 8) & 0xff;
4270                 target [2] = (idx >> 16) & 0xff;
4271         }
4272 }
4273
4274 /*
4275  * fixup_cattrs:
4276  *
4277  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4278  * value is not known when the table is emitted.
4279  */
4280 static void
4281 fixup_cattrs (MonoDynamicImage *assembly)
4282 {
4283         MonoDynamicTable *table;
4284         guint32 *values;
4285         guint32 type, i, idx, token;
4286         MonoObject *ctor;
4287
4288         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4289
4290         for (i = 0; i < table->rows; ++i) {
4291                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4292
4293                 type = values [MONO_CUSTOM_ATTR_TYPE];
4294                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4295                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4296                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4297                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4298                         g_assert (ctor);
4299
4300                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4301                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4302                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4303                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4304                         }
4305                 }
4306         }
4307 }
4308
4309 static void
4310 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4311 {
4312         MonoDynamicTable *table;
4313         guint32 *values;
4314
4315         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4316         table->rows++;
4317         alloc_table (table, table->rows);
4318         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4319         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4320         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4321         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4322         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4323         table->next_idx++;
4324 }
4325
4326 static void
4327 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4328 {
4329         MonoDynamicTable *table;
4330         guint32 *values;
4331         char blob_size [6];
4332         guchar hash [20];
4333         char *b = blob_size;
4334         char *name, *sname;
4335         guint32 idx, offset;
4336
4337         if (rsrc->filename) {
4338                 name = mono_string_to_utf8 (rsrc->filename);
4339                 sname = g_path_get_basename (name);
4340         
4341                 table = &assembly->tables [MONO_TABLE_FILE];
4342                 table->rows++;
4343                 alloc_table (table, table->rows);
4344                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4345                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4346                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4347                 g_free (sname);
4348
4349                 mono_sha1_get_digest_from_file (name, hash);
4350                 mono_metadata_encode_value (20, b, &b);
4351                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4352                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4353                 g_free (name);
4354                 idx = table->next_idx++;
4355                 rsrc->offset = 0;
4356                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4357         } else {
4358                 char sizebuf [4];
4359                 char *data;
4360                 guint len;
4361                 if (rsrc->data) {
4362                         data = mono_array_addr (rsrc->data, char, 0);
4363                         len = mono_array_length (rsrc->data);
4364                 } else {
4365                         data = NULL;
4366                         len = 0;
4367                 }
4368                 offset = len;
4369                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4370                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4371                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4372                 mono_image_add_stream_data (&assembly->resources, data, len);
4373
4374                 if (!mb->is_main)
4375                         /* 
4376                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4377                          * the main module, but that needs to reference the FILE table
4378                          * which isn't emitted yet.
4379                          */
4380                         return;
4381                 else
4382                         idx = 0;
4383         }
4384
4385         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4386 }
4387
4388 static void
4389 set_version_from_string (MonoString *version, guint32 *values)
4390 {
4391         gchar *ver, *p, *str;
4392         guint32 i;
4393         
4394         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4395         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4396         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4397         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4398         if (!version)
4399                 return;
4400         ver = str = mono_string_to_utf8 (version);
4401         for (i = 0; i < 4; ++i) {
4402                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4403                 switch (*p) {
4404                 case '.':
4405                         p++;
4406                         break;
4407                 case '*':
4408                         /* handle Revision and Build */
4409                         p++;
4410                         break;
4411                 }
4412                 ver = p;
4413         }
4414         g_free (str);
4415 }
4416
4417 static guint32
4418 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4419         gsize len;
4420         guint32 token = 0;
4421         char blob_size [6];
4422         char *b = blob_size;
4423
4424         if (!pkey)
4425                 return token;
4426
4427         len = mono_array_length (pkey);
4428         mono_metadata_encode_value (len, b, &b);
4429         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4430         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4431
4432         assembly->public_key = g_malloc (len);
4433         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4434         assembly->public_key_len = len;
4435
4436         /* Special case: check for ECMA key (16 bytes) */
4437         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4438                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4439                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4440         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4441                 /* minimum key size (in 2.0) is 384 bits */
4442                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4443         } else {
4444                 /* FIXME - verifier */
4445                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4446                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4447         }
4448         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4449
4450         return token;
4451 }
4452
4453 static void
4454 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4455 {
4456         MonoDynamicTable *table;
4457         MonoDynamicImage *assembly;
4458         MonoReflectionAssemblyBuilder *assemblyb;
4459         MonoDomain *domain;
4460         guint32 *values;
4461         int i;
4462         guint32 module_index;
4463
4464         assemblyb = moduleb->assemblyb;
4465         assembly = moduleb->dynamic_image;
4466         domain = mono_object_domain (assemblyb);
4467
4468         /* Emit ASSEMBLY table */
4469         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4470         alloc_table (table, 1);
4471         values = table->values + MONO_ASSEMBLY_SIZE;
4472         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4473         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4474         if (assemblyb->culture) {
4475                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4476         } else {
4477                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4478         }
4479         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4480         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4481         set_version_from_string (assemblyb->version, values);
4482
4483         /* Emit FILE + EXPORTED_TYPE table */
4484         module_index = 0;
4485         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4486                 int j;
4487                 MonoReflectionModuleBuilder *file_module = 
4488                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4489                 if (file_module != moduleb) {
4490                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4491                         module_index ++;
4492                         if (file_module->types) {
4493                                 for (j = 0; j < file_module->num_types; ++j) {
4494                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4495                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4496                                 }
4497                         }
4498                 }
4499         }
4500         if (assemblyb->loaded_modules) {
4501                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4502                         MonoReflectionModule *file_module = 
4503                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4504                         mono_image_fill_file_table (domain, file_module, assembly);
4505                         module_index ++;
4506                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4507                 }
4508         }
4509         if (assemblyb->type_forwarders)
4510                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4511
4512         /* Emit MANIFESTRESOURCE table */
4513         module_index = 0;
4514         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4515                 int j;
4516                 MonoReflectionModuleBuilder *file_module = 
4517                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4518                 /* The table for the main module is emitted later */
4519                 if (file_module != moduleb) {
4520                         module_index ++;
4521                         if (file_module->resources) {
4522                                 int len = mono_array_length (file_module->resources);
4523                                 for (j = 0; j < len; ++j) {
4524                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4525                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4526                                 }
4527                         }
4528                 }
4529         }               
4530 }
4531
4532 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4533
4534 /*
4535  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4536  * for the modulebuilder @moduleb.
4537  * At the end of the process, method and field tokens are fixed up and the 
4538  * on-disk compressed metadata representation is created.
4539  */
4540 void
4541 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4542 {
4543         MonoDynamicTable *table;
4544         MonoDynamicImage *assembly;
4545         MonoReflectionAssemblyBuilder *assemblyb;
4546         MonoDomain *domain;
4547         MonoPtrArray types;
4548         guint32 *values;
4549         int i, j;
4550
4551         assemblyb = moduleb->assemblyb;
4552         assembly = moduleb->dynamic_image;
4553         domain = mono_object_domain (assemblyb);
4554
4555         if (assembly->text_rva)
4556                 return;
4557
4558         assembly->text_rva = START_TEXT_RVA;
4559
4560         if (moduleb->is_main) {
4561                 mono_image_emit_manifest (moduleb);
4562         }
4563
4564         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4565         table->rows = 1; /* .<Module> */
4566         table->next_idx++;
4567         alloc_table (table, table->rows);
4568         /*
4569          * Set the first entry.
4570          */
4571         values = table->values + table->columns;
4572         values [MONO_TYPEDEF_FLAGS] = 0;
4573         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4574         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4575         values [MONO_TYPEDEF_EXTENDS] = 0;
4576         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4577         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4578
4579         /* 
4580          * handle global methods 
4581          * FIXME: test what to do when global methods are defined in multiple modules.
4582          */
4583         if (moduleb->global_methods) {
4584                 table = &assembly->tables [MONO_TABLE_METHOD];
4585                 table->rows += mono_array_length (moduleb->global_methods);
4586                 alloc_table (table, table->rows);
4587                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4588                         mono_image_get_method_info (
4589                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4590         }
4591         if (moduleb->global_fields) {
4592                 table = &assembly->tables [MONO_TABLE_FIELD];
4593                 table->rows += mono_array_length (moduleb->global_fields);
4594                 alloc_table (table, table->rows);
4595                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4596                         mono_image_get_field_info (
4597                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4598         }
4599
4600         table = &assembly->tables [MONO_TABLE_MODULE];
4601         alloc_table (table, 1);
4602         mono_image_fill_module_table (domain, moduleb, assembly);
4603
4604         /* Collect all types into a list sorted by their table_idx */
4605         mono_ptr_array_init (types, moduleb->num_types);
4606
4607         if (moduleb->types)
4608                 for (i = 0; i < moduleb->num_types; ++i) {
4609                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4610                         collect_types (&types, type);
4611                 }
4612
4613         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4614         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4615         table->rows += mono_ptr_array_size (types);
4616         alloc_table (table, table->rows);
4617
4618         /*
4619          * Emit type names + namespaces at one place inside the string heap,
4620          * so load_class_names () needs to touch fewer pages.
4621          */
4622         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4623                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4624                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4625         }
4626         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4627                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4628                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4629         }
4630
4631         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4632                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4633                 mono_image_get_type_info (domain, type, assembly);
4634         }
4635
4636         /* 
4637          * table->rows is already set above and in mono_image_fill_module_table.
4638          */
4639         /* add all the custom attributes at the end, once all the indexes are stable */
4640         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4641
4642         /* CAS assembly permissions */
4643         if (assemblyb->permissions_minimum)
4644                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4645         if (assemblyb->permissions_optional)
4646                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4647         if (assemblyb->permissions_refused)
4648                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4649
4650         module_add_cattrs (assembly, moduleb);
4651
4652         /* fixup tokens */
4653         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4654
4655         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4656          * the final tokens and don't need another fixup pass. */
4657
4658         if (moduleb->global_methods) {
4659                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4660                         MonoReflectionMethodBuilder *mb = mono_array_get (
4661                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4662                         mono_image_add_methodimpl (assembly, mb);
4663                 }
4664         }
4665
4666         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4667                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4668                 if (type->methods) {
4669                         for (j = 0; j < type->num_methods; ++j) {
4670                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4671                                         type->methods, MonoReflectionMethodBuilder*, j);
4672
4673                                 mono_image_add_methodimpl (assembly, mb);
4674                         }
4675                 }
4676         }
4677
4678         mono_ptr_array_destroy (types);
4679
4680         fixup_cattrs (assembly);
4681 }
4682
4683 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4684
4685 void
4686 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4687 {
4688         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4689 }
4690
4691 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4692
4693
4694 typedef struct {
4695         guint32 import_lookup_table;
4696         guint32 timestamp;
4697         guint32 forwarder;
4698         guint32 name_rva;
4699         guint32 import_address_table_rva;
4700 } MonoIDT;
4701
4702 typedef struct {
4703         guint32 name_rva;
4704         guint32 flags;
4705 } MonoILT;
4706
4707 #ifndef DISABLE_REFLECTION_EMIT
4708
4709 /*
4710  * mono_image_insert_string:
4711  * @module: module builder object
4712  * @str: a string
4713  *
4714  * Insert @str into the user string stream of @module.
4715  */
4716 guint32
4717 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4718 {
4719         MonoDynamicImage *assembly;
4720         guint32 idx;
4721         char buf [16];
4722         char *b = buf;
4723         
4724         MONO_ARCH_SAVE_REGS;
4725
4726         if (!module->dynamic_image)
4727                 mono_image_module_basic_init (module);
4728
4729         assembly = module->dynamic_image;
4730         
4731         if (assembly->save) {
4732                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4733                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4734 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4735         {
4736                 char *swapped = g_malloc (2 * mono_string_length (str));
4737                 const char *p = (const char*)mono_string_chars (str);
4738
4739                 swap_with_size (swapped, p, 2, mono_string_length (str));
4740                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4741                 g_free (swapped);
4742         }
4743 #else
4744                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4745 #endif
4746                 mono_image_add_stream_data (&assembly->us, "", 1);
4747         } else {
4748                 idx = assembly->us.index ++;
4749         }
4750
4751         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4752
4753         return MONO_TOKEN_STRING | idx;
4754 }
4755
4756 guint32
4757 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4758 {
4759         MonoClass *klass;
4760         guint32 token = 0;
4761         MonoMethodSignature *sig;
4762
4763         klass = obj->vtable->klass;
4764         if (strcmp (klass->name, "MonoMethod") == 0) {
4765                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4766                 MonoMethodSignature *old;
4767                 guint32 sig_token, parent;
4768                 int nargs, i;
4769
4770                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4771
4772                 nargs = mono_array_length (opt_param_types);
4773                 old = mono_method_signature (method);
4774                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4775
4776                 sig->hasthis = old->hasthis;
4777                 sig->explicit_this = old->explicit_this;
4778                 sig->call_convention = old->call_convention;
4779                 sig->generic_param_count = old->generic_param_count;
4780                 sig->param_count = old->param_count + nargs;
4781                 sig->sentinelpos = old->param_count;
4782                 sig->ret = old->ret;
4783
4784                 for (i = 0; i < old->param_count; i++)
4785                         sig->params [i] = old->params [i];
4786
4787                 for (i = 0; i < nargs; i++) {
4788                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4789                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4790                 }
4791
4792                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4793                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4794                 parent >>= MONO_TYPEDEFORREF_BITS;
4795
4796                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4797                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4798
4799                 sig_token = method_encode_signature (assembly, sig);
4800                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4801         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4802                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4803                 ReflectionMethodBuilder rmb;
4804                 guint32 parent, sig_token;
4805                 int nopt_args, nparams, ngparams, i;
4806                 char *name;
4807
4808                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4809                 rmb.opt_types = opt_param_types;
4810                 nopt_args = mono_array_length (opt_param_types);
4811
4812                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4813                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4814                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4815
4816                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4817                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4818                 sig->call_convention = rmb.call_conv;
4819                 sig->generic_param_count = ngparams;
4820                 sig->param_count = nparams + nopt_args;
4821                 sig->sentinelpos = nparams;
4822                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4823
4824                 for (i = 0; i < nparams; i++) {
4825                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4826                         sig->params [i] = mono_reflection_type_get_handle (rt);
4827                 }
4828
4829                 for (i = 0; i < nopt_args; i++) {
4830                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4831                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4832                 }
4833
4834                 sig_token = method_builder_encode_signature (assembly, &rmb);
4835
4836                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4837                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4838
4839                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4840                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4841
4842                 name = mono_string_to_utf8 (rmb.name);
4843                 token = mono_image_get_varargs_method_token (
4844                         assembly, parent, name, sig_token);
4845                 g_free (name);
4846         } else {
4847                 g_error ("requested method token for %s\n", klass->name);
4848         }
4849
4850         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4851         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4852         return token;
4853 }
4854
4855 /*
4856  * mono_image_create_token:
4857  * @assembly: a dynamic assembly
4858  * @obj:
4859  * @register_token: Whenever to register the token in the assembly->tokens hash. 
4860  *
4861  * Get a token to insert in the IL code stream for the given MemberInfo.
4862  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
4863  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
4864  * entry.
4865  */
4866 guint32
4867 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
4868                                                  gboolean create_methodspec, gboolean register_token)
4869 {
4870         MonoClass *klass;
4871         guint32 token = 0;
4872
4873         klass = obj->vtable->klass;
4874
4875         /* Check for user defined reflection objects */
4876         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4877         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4878                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4879
4880         if (strcmp (klass->name, "MethodBuilder") == 0) {
4881                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4882                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4883
4884                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4885                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4886                 else
4887                         token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4888                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4889         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4890                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4891                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4892
4893                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4894                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4895                 else
4896                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4897                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4898         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4899                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4900                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4901                 if (tb->generic_params) {
4902                         token = mono_image_get_generic_field_token (assembly, fb);
4903                 } else {
4904                         if ((tb->module->dynamic_image == assembly)) {
4905                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4906                         } else {
4907                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4908                         }
4909                 }
4910         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4911                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4912                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4913         } else if (strcmp (klass->name, "MonoType") == 0) {
4914                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4915                 MonoClass *mc = mono_class_from_mono_type (type);
4916                 if (!mono_class_init (mc))
4917                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
4918
4919                 token = mono_metadata_token_from_dor (
4920                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4921         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4922                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4923                 token = mono_metadata_token_from_dor (
4924                         mono_image_typedef_or_ref (assembly, type));
4925         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4926                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4927                 token = mono_metadata_token_from_dor (
4928                         mono_image_typedef_or_ref (assembly, type));
4929         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4930                    strcmp (klass->name, "MonoMethod") == 0 ||
4931                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
4932                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
4933                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4934                 if (m->method->is_inflated) {
4935                         if (create_methodspec)
4936                                 token = mono_image_get_methodspec_token (assembly, m->method);
4937                         else
4938                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4939                 } else if ((m->method->klass->image == &assembly->image) &&
4940                          !m->method->klass->generic_class) {
4941                         static guint32 method_table_idx = 0xffffff;
4942                         if (m->method->klass->wastypebuilder) {
4943                                 /* we use the same token as the one that was assigned
4944                                  * to the Methodbuilder.
4945                                  * FIXME: do the equivalent for Fields.
4946                                  */
4947                                 token = m->method->token;
4948                         } else {
4949                                 /*
4950                                  * Each token should have a unique index, but the indexes are
4951                                  * assigned by managed code, so we don't know about them. An
4952                                  * easy solution is to count backwards...
4953                                  */
4954                                 method_table_idx --;
4955                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4956                         }
4957                 } else {
4958                         token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4959                 }
4960                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4961         } else if (strcmp (klass->name, "MonoField") == 0) {
4962                 MonoReflectionField *f = (MonoReflectionField *)obj;
4963                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4964                         static guint32 field_table_idx = 0xffffff;
4965                         field_table_idx --;
4966                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4967                 } else {
4968                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
4969                 }
4970                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4971         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4972                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4973                 token = mono_image_get_array_token (assembly, m);
4974         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4975                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4976                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4977         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4978                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4979                 token = mono_metadata_token_from_dor (
4980                         mono_image_typedef_or_ref (assembly, type));
4981         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4982                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4983                 token = mono_image_get_field_on_inst_token (assembly, f);
4984         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4985                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4986                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4987         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4988                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4989                 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4990         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4991                 MonoReflectionType *type = (MonoReflectionType *)obj;
4992                 token = mono_metadata_token_from_dor (
4993                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4994         } else {
4995                 g_error ("requested token for %s\n", klass->name);
4996         }
4997
4998         if (register_token)
4999                 mono_image_register_token (assembly, token, obj);
5000
5001         return token;
5002 }
5003
5004 /*
5005  * mono_image_register_token:
5006  *
5007  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5008  * the Module.ResolveXXXToken () methods to work.
5009  */
5010 void
5011 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5012 {
5013         MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5014         if (prev) {
5015                 /* There could be multiple MethodInfo objects with the same token */
5016                 //g_assert (prev == obj);
5017         } else {
5018                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5019         }
5020 }
5021
5022 static MonoDynamicImage*
5023 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5024 {
5025         static const guchar entrycode [16] = {0xff, 0x25, 0};
5026         MonoDynamicImage *image;
5027         int i;
5028
5029         const char *version;
5030
5031         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5032                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5033         else
5034                 version = mono_get_runtime_info ()->runtime_version;
5035
5036 #if HAVE_BOEHM_GC
5037         /* The MonoGHashTable's need GC tracking */
5038         image = GC_MALLOC (sizeof (MonoDynamicImage));
5039 #else
5040         image = g_new0 (MonoDynamicImage, 1);
5041 #endif
5042         
5043         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5044         
5045         /*g_print ("created image %p\n", image);*/
5046         /* keep in sync with image.c */
5047         image->image.name = assembly_name;
5048         image->image.assembly_name = image->image.name; /* they may be different */
5049         image->image.module_name = module_name;
5050         image->image.version = g_strdup (version);
5051         image->image.md_version_major = 1;
5052         image->image.md_version_minor = 1;
5053         image->image.dynamic = TRUE;
5054
5055         image->image.references = g_new0 (MonoAssembly*, 1);
5056         image->image.references [0] = NULL;
5057
5058         mono_image_init (&image->image);
5059
5060         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5061         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5062         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5063         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5064         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5065         image->handleref = g_hash_table_new (NULL, NULL);
5066         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5067         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5068         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5069         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5070         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5071         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5072         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5073         image->gen_params = g_ptr_array_new ();
5074
5075         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5076         string_heap_init (&image->sheap);
5077         mono_image_add_stream_data (&image->us, "", 1);
5078         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5079         /* import tables... */
5080         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5081         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5082         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5083         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5084         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5085         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5086         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5087         stream_data_align (&image->code);
5088
5089         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5090
5091         for (i=0; i < MONO_TABLE_NUM; ++i) {
5092                 image->tables [i].next_idx = 1;
5093                 image->tables [i].columns = table_sizes [i];
5094         }
5095
5096         image->image.assembly = (MonoAssembly*)assembly;
5097         image->run = assembly->run;
5098         image->save = assembly->save;
5099         image->pe_kind = 0x1; /* ILOnly */
5100         image->machine = 0x14c; /* I386 */
5101         
5102         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5103
5104         return image;
5105 }
5106 #endif
5107
5108 static void
5109 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5110 {
5111         g_free (key);
5112 }
5113
5114 void
5115 mono_dynamic_image_free (MonoDynamicImage *image)
5116 {
5117         MonoDynamicImage *di = image;
5118         GList *list;
5119         int i;
5120
5121         if (di->methodspec)
5122                 mono_g_hash_table_destroy (di->methodspec);
5123         if (di->typespec)
5124                 g_hash_table_destroy (di->typespec);
5125         if (di->typeref)
5126                 g_hash_table_destroy (di->typeref);
5127         if (di->handleref)
5128                 g_hash_table_destroy (di->handleref);
5129         if (di->handleref_managed)
5130                 mono_g_hash_table_destroy (di->handleref_managed);
5131         if (di->tokens)
5132                 mono_g_hash_table_destroy (di->tokens);
5133         if (di->generic_def_objects)
5134                 mono_g_hash_table_destroy (di->generic_def_objects);
5135         if (di->blob_cache) {
5136                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5137                 g_hash_table_destroy (di->blob_cache);
5138         }
5139         if (di->standalonesig_cache)
5140                 g_hash_table_destroy (di->standalonesig_cache);
5141         for (list = di->array_methods; list; list = list->next) {
5142                 ArrayMethod *am = (ArrayMethod *)list->data;
5143                 g_free (am->sig);
5144                 g_free (am->name);
5145                 g_free (am);
5146         }
5147         g_list_free (di->array_methods);
5148         if (di->gen_params) {
5149                 for (i = 0; i < di->gen_params->len; i++) {
5150                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5151                         if (entry->gparam->type.type) {
5152                                 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5153                                 g_free ((char*)mono_generic_param_info (param)->name);
5154                                 g_free (param);
5155                         }
5156                         mono_gc_deregister_root ((char*) &entry->gparam);
5157                         g_free (entry);
5158                 }
5159                 g_ptr_array_free (di->gen_params, TRUE);
5160         }
5161         if (di->token_fixups)
5162                 mono_g_hash_table_destroy (di->token_fixups);
5163         if (di->method_to_table_idx)
5164                 g_hash_table_destroy (di->method_to_table_idx);
5165         if (di->field_to_table_idx)
5166                 g_hash_table_destroy (di->field_to_table_idx);
5167         if (di->method_aux_hash)
5168                 g_hash_table_destroy (di->method_aux_hash);
5169         if (di->vararg_aux_hash)
5170                 g_hash_table_destroy (di->vararg_aux_hash);
5171         g_free (di->strong_name);
5172         g_free (di->win32_res);
5173         if (di->public_key)
5174                 g_free (di->public_key);
5175
5176         /*g_print ("string heap destroy for image %p\n", di);*/
5177         mono_dynamic_stream_reset (&di->sheap);
5178         mono_dynamic_stream_reset (&di->code);
5179         mono_dynamic_stream_reset (&di->resources);
5180         mono_dynamic_stream_reset (&di->us);
5181         mono_dynamic_stream_reset (&di->blob);
5182         mono_dynamic_stream_reset (&di->tstream);
5183         mono_dynamic_stream_reset (&di->guid);
5184         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5185                 g_free (di->tables [i].values);
5186         }
5187 }       
5188
5189 #ifndef DISABLE_REFLECTION_EMIT
5190
5191 /*
5192  * mono_image_basic_init:
5193  * @assembly: an assembly builder object
5194  *
5195  * Create the MonoImage that represents the assembly builder and setup some
5196  * of the helper hash table and the basic metadata streams.
5197  */
5198 void
5199 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5200 {
5201         MonoDynamicAssembly *assembly;
5202         MonoDynamicImage *image;
5203         MonoDomain *domain = mono_object_domain (assemblyb);
5204         
5205         MONO_ARCH_SAVE_REGS;
5206
5207         if (assemblyb->dynamic_assembly)
5208                 return;
5209
5210 #if HAVE_BOEHM_GC
5211         /* assembly->assembly.image might be GC allocated */
5212         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5213 #else
5214         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5215 #endif
5216
5217         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5218         
5219         assembly->assembly.ref_count = 1;
5220         assembly->assembly.dynamic = TRUE;
5221         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5222         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5223         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5224         if (assemblyb->culture)
5225                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5226         else
5227                 assembly->assembly.aname.culture = g_strdup ("");
5228
5229         if (assemblyb->version) {
5230                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5231                         char **version = g_strsplit (vstr, ".", 4);
5232                         char **parts = version;
5233                         assembly->assembly.aname.major = atoi (*parts++);
5234                         assembly->assembly.aname.minor = atoi (*parts++);
5235                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5236                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5237
5238                         g_strfreev (version);
5239                         g_free (vstr);
5240         } else {
5241                         assembly->assembly.aname.major = 0;
5242                         assembly->assembly.aname.minor = 0;
5243                         assembly->assembly.aname.build = 0;
5244                         assembly->assembly.aname.revision = 0;
5245         }
5246
5247         assembly->run = assemblyb->access != 2;
5248         assembly->save = assemblyb->access != 1;
5249         assembly->domain = domain;
5250
5251         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5252         image->initial_image = TRUE;
5253         assembly->assembly.aname.name = image->image.name;
5254         assembly->assembly.image = &image->image;
5255         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5256                 /* -1 to correct for the trailing NULL byte */
5257                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5258                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5259                 }
5260                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5261         }
5262
5263         mono_domain_assemblies_lock (domain);
5264         domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5265         mono_domain_assemblies_unlock (domain);
5266
5267         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5268         
5269         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5270         
5271         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5272 }
5273
5274 #endif /* !DISABLE_REFLECTION_EMIT */
5275
5276 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5277
5278 static int
5279 calc_section_size (MonoDynamicImage *assembly)
5280 {
5281         int nsections = 0;
5282
5283         /* alignment constraints */
5284         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5285         g_assert ((assembly->code.index % 4) == 0);
5286         assembly->meta_size += 3;
5287         assembly->meta_size &= ~3;
5288         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5289         g_assert ((assembly->resources.index % 4) == 0);
5290
5291         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5292         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5293         nsections++;
5294
5295         if (assembly->win32_res) {
5296                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5297
5298                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5299                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5300                 nsections++;
5301         }
5302
5303         assembly->sections [MONO_SECTION_RELOC].size = 12;
5304         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5305         nsections++;
5306
5307         return nsections;
5308 }
5309
5310 typedef struct {
5311         guint32 id;
5312         guint32 offset;
5313         GSList *children;
5314         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5315 } ResTreeNode;
5316
5317 static int
5318 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5319 {
5320         ResTreeNode *t1 = (ResTreeNode*)a;
5321         ResTreeNode *t2 = (ResTreeNode*)b;
5322
5323         return t1->id - t2->id;
5324 }
5325
5326 /*
5327  * resource_tree_create:
5328  *
5329  *  Organize the resources into a resource tree.
5330  */
5331 static ResTreeNode *
5332 resource_tree_create (MonoArray *win32_resources)
5333 {
5334         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5335         GSList *l;
5336         int i;
5337
5338         tree = g_new0 (ResTreeNode, 1);
5339         
5340         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5341                 MonoReflectionWin32Resource *win32_res =
5342                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5343
5344                 /* Create node */
5345
5346                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5347                 lang_node = g_new0 (ResTreeNode, 1);
5348                 lang_node->id = win32_res->lang_id;
5349                 lang_node->win32_res = win32_res;
5350
5351                 /* Create type node if neccesary */
5352                 type_node = NULL;
5353                 for (l = tree->children; l; l = l->next)
5354                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5355                                 type_node = (ResTreeNode*)l->data;
5356                                 break;
5357                         }
5358
5359                 if (!type_node) {
5360                         type_node = g_new0 (ResTreeNode, 1);
5361                         type_node->id = win32_res->res_type;
5362
5363                         /* 
5364                          * The resource types have to be sorted otherwise
5365                          * Windows Explorer can't display the version information.
5366                          */
5367                         tree->children = g_slist_insert_sorted (tree->children, 
5368                                 type_node, resource_tree_compare_by_id);
5369                 }
5370
5371                 /* Create res node if neccesary */
5372                 res_node = NULL;
5373                 for (l = type_node->children; l; l = l->next)
5374                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5375                                 res_node = (ResTreeNode*)l->data;
5376                                 break;
5377                         }
5378
5379                 if (!res_node) {
5380                         res_node = g_new0 (ResTreeNode, 1);
5381                         res_node->id = win32_res->res_id;
5382                         type_node->children = g_slist_append (type_node->children, res_node);
5383                 }
5384
5385                 res_node->children = g_slist_append (res_node->children, lang_node);
5386         }
5387
5388         return tree;
5389 }
5390
5391 /*
5392  * resource_tree_encode:
5393  * 
5394  *   Encode the resource tree into the format used in the PE file.
5395  */
5396 static void
5397 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5398 {
5399         char *entries;
5400         MonoPEResourceDir dir;
5401         MonoPEResourceDirEntry dir_entry;
5402         MonoPEResourceDataEntry data_entry;
5403         GSList *l;
5404         guint32 res_id_entries;
5405
5406         /*
5407          * For the format of the resource directory, see the article
5408          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5409          * Matt Pietrek
5410          */
5411
5412         memset (&dir, 0, sizeof (dir));
5413         memset (&dir_entry, 0, sizeof (dir_entry));
5414         memset (&data_entry, 0, sizeof (data_entry));
5415
5416         g_assert (sizeof (dir) == 16);
5417         g_assert (sizeof (dir_entry) == 8);
5418         g_assert (sizeof (data_entry) == 16);
5419
5420         node->offset = p - begin;
5421
5422         /* IMAGE_RESOURCE_DIRECTORY */
5423         res_id_entries = g_slist_length (node->children);
5424         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5425
5426         memcpy (p, &dir, sizeof (dir));
5427         p += sizeof (dir);
5428
5429         /* Reserve space for entries */
5430         entries = p;
5431         p += sizeof (dir_entry) * res_id_entries;
5432
5433         /* Write children */
5434         for (l = node->children; l; l = l->next) {
5435                 ResTreeNode *child = (ResTreeNode*)l->data;
5436
5437                 if (child->win32_res) {
5438                         guint32 size;
5439
5440                         child->offset = p - begin;
5441
5442                         /* IMAGE_RESOURCE_DATA_ENTRY */
5443                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5444                         size = mono_array_length (child->win32_res->res_data);
5445                         data_entry.rde_size = GUINT32_TO_LE (size);
5446
5447                         memcpy (p, &data_entry, sizeof (data_entry));
5448                         p += sizeof (data_entry);
5449
5450                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5451                         p += size;
5452                 } else {
5453                         resource_tree_encode (child, begin, p, &p);
5454                 }
5455         }
5456
5457         /* IMAGE_RESOURCE_ENTRY */
5458         for (l = node->children; l; l = l->next) {
5459                 ResTreeNode *child = (ResTreeNode*)l->data;
5460
5461                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5462                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5463
5464                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5465                 entries += sizeof (dir_entry);
5466         }
5467
5468         *endbuf = p;
5469 }
5470
5471 static void
5472 resource_tree_free (ResTreeNode * node)
5473 {
5474         GSList * list;
5475         for (list = node->children; list; list = list->next)
5476                 resource_tree_free ((ResTreeNode*)list->data);
5477         g_slist_free(node->children);
5478         g_free (node);
5479 }
5480
5481 static void
5482 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5483 {
5484         char *buf;
5485         char *p;
5486         guint32 size, i;
5487         MonoReflectionWin32Resource *win32_res;
5488         ResTreeNode *tree;
5489
5490         if (!assemblyb->win32_resources)
5491                 return;
5492
5493         /*
5494          * Resources are stored in a three level tree inside the PE file.
5495          * - level one contains a node for each type of resource
5496          * - level two contains a node for each resource
5497          * - level three contains a node for each instance of a resource for a
5498          *   specific language.
5499          */
5500
5501         tree = resource_tree_create (assemblyb->win32_resources);
5502
5503         /* Estimate the size of the encoded tree */
5504         size = 0;
5505         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5506                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5507                 size += mono_array_length (win32_res->res_data);
5508         }
5509         /* Directory structure */
5510         size += mono_array_length (assemblyb->win32_resources) * 256;
5511         p = buf = g_malloc (size);
5512
5513         resource_tree_encode (tree, p, p, &p);
5514
5515         g_assert (p - buf <= size);
5516
5517         assembly->win32_res = g_malloc (p - buf);
5518         assembly->win32_res_size = p - buf;
5519         memcpy (assembly->win32_res, buf, p - buf);
5520
5521         g_free (buf);
5522         resource_tree_free (tree);
5523 }
5524
5525 static void
5526 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5527 {
5528         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5529         int i;
5530
5531         p += sizeof (MonoPEResourceDir);
5532         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5533                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5534                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5535                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5536                         fixup_resource_directory (res_section, child, rva);
5537                 } else {
5538                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5539                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5540                 }
5541
5542                 p += sizeof (MonoPEResourceDirEntry);
5543         }
5544 }
5545
5546 static void
5547 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5548 {
5549         guint32 dummy;
5550         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5551                 g_error ("WriteFile returned %d\n", GetLastError ());
5552 }
5553
5554 /*
5555  * mono_image_create_pefile:
5556  * @mb: a module builder object
5557  * 
5558  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5559  * assembly->pefile where it can be easily retrieved later in chunks.
5560  */
5561 void
5562 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5563 {
5564         MonoMSDOSHeader *msdos;
5565         MonoDotNetHeader *header;
5566         MonoSectionTable *section;
5567         MonoCLIHeader *cli_header;
5568         guint32 size, image_size, virtual_base, text_offset;
5569         guint32 header_start, section_start, file_offset, virtual_offset;
5570         MonoDynamicImage *assembly;
5571         MonoReflectionAssemblyBuilder *assemblyb;
5572         MonoDynamicStream pefile_stream = {0};
5573         MonoDynamicStream *pefile = &pefile_stream;
5574         int i, nsections;
5575         guint32 *rva, value;
5576         guchar *p;
5577         static const unsigned char msheader[] = {
5578                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5579                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5580                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5581                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5582                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5583                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5584                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5585                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5586         };
5587
5588         assemblyb = mb->assemblyb;
5589
5590         mono_image_basic_init (assemblyb);
5591         assembly = mb->dynamic_image;
5592
5593         assembly->pe_kind = assemblyb->pe_kind;
5594         assembly->machine = assemblyb->machine;
5595         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5596         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5597         
5598         mono_image_build_metadata (mb);
5599
5600         if (mb->is_main && assemblyb->resources) {
5601                 int len = mono_array_length (assemblyb->resources);
5602                 for (i = 0; i < len; ++i)
5603                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5604         }
5605
5606         if (mb->resources) {
5607                 int len = mono_array_length (mb->resources);
5608                 for (i = 0; i < len; ++i)
5609                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5610         }
5611
5612         build_compressed_metadata (assembly);
5613
5614         if (mb->is_main)
5615                 assembly_add_win32_resources (assembly, assemblyb);
5616
5617         nsections = calc_section_size (assembly);
5618         
5619         /* The DOS header and stub */
5620         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5621         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5622
5623         /* the dotnet header */
5624         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5625
5626         /* the section tables */
5627         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5628
5629         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5630         virtual_offset = VIRT_ALIGN;
5631         image_size = 0;
5632
5633         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5634                 if (!assembly->sections [i].size)
5635                         continue;
5636                 /* align offsets */
5637                 file_offset += FILE_ALIGN - 1;
5638                 file_offset &= ~(FILE_ALIGN - 1);
5639                 virtual_offset += VIRT_ALIGN - 1;
5640                 virtual_offset &= ~(VIRT_ALIGN - 1);
5641
5642                 assembly->sections [i].offset = file_offset;
5643                 assembly->sections [i].rva = virtual_offset;
5644
5645                 file_offset += assembly->sections [i].size;
5646                 virtual_offset += assembly->sections [i].size;
5647                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5648         }
5649
5650         file_offset += FILE_ALIGN - 1;
5651         file_offset &= ~(FILE_ALIGN - 1);
5652
5653         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5654
5655         /* back-patch info */
5656         msdos = (MonoMSDOSHeader*)pefile->data;
5657         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5658
5659         header = (MonoDotNetHeader*)(pefile->data + header_start);
5660         header->pesig [0] = 'P';
5661         header->pesig [1] = 'E';
5662         
5663         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5664         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5665         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5666         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5667         if (assemblyb->pekind == 1) {
5668                 /* it's a dll */
5669                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5670         } else {
5671                 /* it's an exe */
5672                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5673         }
5674
5675         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5676
5677         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5678         header->pe.pe_major = 6;
5679         header->pe.pe_minor = 0;
5680         size = assembly->sections [MONO_SECTION_TEXT].size;
5681         size += FILE_ALIGN - 1;
5682         size &= ~(FILE_ALIGN - 1);
5683         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5684         size = assembly->sections [MONO_SECTION_RSRC].size;
5685         size += FILE_ALIGN - 1;
5686         size &= ~(FILE_ALIGN - 1);
5687         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5688         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5689         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5690         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5691         /* pe_rva_entry_point always at the beginning of the text section */
5692         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5693
5694         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5695         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5696         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5697         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5698         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5699         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5700         size = section_start;
5701         size += FILE_ALIGN - 1;
5702         size &= ~(FILE_ALIGN - 1);
5703         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5704         size = image_size;
5705         size += VIRT_ALIGN - 1;
5706         size &= ~(VIRT_ALIGN - 1);
5707         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5708
5709         /*
5710         // Translate the PEFileKind value to the value expected by the Windows loader
5711         */
5712         {
5713                 short kind;
5714
5715                 /*
5716                 // PEFileKinds.Dll == 1
5717                 // PEFileKinds.ConsoleApplication == 2
5718                 // PEFileKinds.WindowApplication == 3
5719                 //
5720                 // need to get:
5721                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5722                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5723                 */
5724                 if (assemblyb->pekind == 3)
5725                         kind = 2;
5726                 else
5727                         kind = 3;
5728                 
5729                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5730         }    
5731         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5732         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5733         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5734         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5735         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5736         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5737
5738         /* fill data directory entries */
5739
5740         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5741         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5742
5743         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5744         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5745
5746         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5747         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5748         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5749         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5750         /* patch entrypoint name */
5751         if (assemblyb->pekind == 1)
5752                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5753         else
5754                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5755         /* patch imported function RVA name */
5756         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5757         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5758
5759         /* the import table */
5760         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5761         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5762         /* patch imported dll RVA name and other entries in the dir */
5763         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5764         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5765         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5766         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5767         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5768         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5769
5770         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5771         value = (assembly->text_rva + assembly->imp_names_offset);
5772         *p++ = (value) & 0xff;
5773         *p++ = (value >> 8) & (0xff);
5774         *p++ = (value >> 16) & (0xff);
5775         *p++ = (value >> 24) & (0xff);
5776
5777         /* the CLI header info */
5778         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5779         cli_header->ch_size = GUINT32_FROM_LE (72);
5780         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5781         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5782         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5783         if (assemblyb->entry_point) {
5784                 guint32 table_idx = 0;
5785                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5786                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5787                         table_idx = methodb->table_idx;
5788                 } else {
5789                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5790                 }
5791                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5792         } else {
5793                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5794         }
5795         /* The embedded managed resources */
5796         text_offset = assembly->text_rva + assembly->code.index;
5797         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5798         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5799         text_offset += assembly->resources.index;
5800         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5801         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5802         text_offset += assembly->meta_size;
5803         if (assembly->strong_name_size) {
5804                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5805                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5806                 text_offset += assembly->strong_name_size;
5807         }
5808
5809         /* write the section tables and section content */
5810         section = (MonoSectionTable*)(pefile->data + section_start);
5811         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5812                 static const char section_names [][7] = {
5813                         ".text", ".rsrc", ".reloc"
5814                 };
5815                 if (!assembly->sections [i].size)
5816                         continue;
5817                 strcpy (section->st_name, section_names [i]);
5818                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5819                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5820                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5821                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5822                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5823                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5824                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5825                 section ++;
5826         }
5827         
5828         checked_write_file (file, pefile->data, pefile->index);
5829         
5830         mono_dynamic_stream_reset (pefile);
5831         
5832         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5833                 if (!assembly->sections [i].size)
5834                         continue;
5835                 
5836                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5837                         g_error ("SetFilePointer returned %d\n", GetLastError ());
5838                 
5839                 switch (i) {
5840                 case MONO_SECTION_TEXT:
5841                         /* patch entry point */
5842                         p = (guchar*)(assembly->code.data + 2);
5843                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5844                         *p++ = (value) & 0xff;
5845                         *p++ = (value >> 8) & 0xff;
5846                         *p++ = (value >> 16) & 0xff;
5847                         *p++ = (value >> 24) & 0xff;
5848                 
5849                         checked_write_file (file, assembly->code.data, assembly->code.index);
5850                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
5851                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5852                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5853                                 
5854
5855                         g_free (assembly->image.raw_metadata);
5856                         break;
5857                 case MONO_SECTION_RELOC: {
5858                         struct {
5859                                 guint32 page_rva;
5860                                 guint32 block_size;
5861                                 guint16 type_and_offset;
5862                                 guint16 term;
5863                         } reloc;
5864                         
5865                         g_assert (sizeof (reloc) == 12);
5866                         
5867                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5868                         reloc.block_size = GUINT32_FROM_LE (12);
5869                         
5870                         /* 
5871                          * the entrypoint is always at the start of the text section 
5872                          * 3 is IMAGE_REL_BASED_HIGHLOW
5873                          * 2 is patch_size_rva - text_rva
5874                          */
5875                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5876                         reloc.term = 0;
5877                         
5878                         checked_write_file (file, &reloc, sizeof (reloc));
5879                         
5880                         break;
5881                 }
5882                 case MONO_SECTION_RSRC:
5883                         if (assembly->win32_res) {
5884
5885                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5886                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5887                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5888                         }
5889                         break;
5890                 default:
5891                         g_assert_not_reached ();
5892                 }
5893         }
5894         
5895         /* check that the file is properly padded */
5896         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5897                 g_error ("SetFilePointer returned %d\n", GetLastError ());
5898         if (! SetEndOfFile (file))
5899                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5900         
5901         mono_dynamic_stream_reset (&assembly->code);
5902         mono_dynamic_stream_reset (&assembly->us);
5903         mono_dynamic_stream_reset (&assembly->blob);
5904         mono_dynamic_stream_reset (&assembly->guid);
5905         mono_dynamic_stream_reset (&assembly->sheap);
5906
5907         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5908         g_hash_table_destroy (assembly->blob_cache);
5909         assembly->blob_cache = NULL;
5910 }
5911
5912 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5913
5914 void
5915 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5916 {
5917         g_assert_not_reached ();
5918 }
5919
5920 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5921
5922 #ifndef DISABLE_REFLECTION_EMIT
5923
5924 MonoReflectionModule *
5925 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5926 {
5927         char *name;
5928         MonoImage *image;
5929         MonoImageOpenStatus status;
5930         MonoDynamicAssembly *assembly;
5931         guint32 module_count;
5932         MonoImage **new_modules;
5933         gboolean *new_modules_loaded;
5934         
5935         name = mono_string_to_utf8 (fileName);
5936
5937         image = mono_image_open (name, &status);
5938         if (!image) {
5939                 MonoException *exc;
5940                 if (status == MONO_IMAGE_ERROR_ERRNO)
5941                         exc = mono_get_exception_file_not_found (fileName);
5942                 else
5943                         exc = mono_get_exception_bad_image_format (name);
5944                 g_free (name);
5945                 mono_raise_exception (exc);
5946         }
5947
5948         g_free (name);
5949
5950         assembly = ab->dynamic_assembly;
5951         image->assembly = (MonoAssembly*)assembly;
5952
5953         module_count = image->assembly->image->module_count;
5954         new_modules = g_new0 (MonoImage *, module_count + 1);
5955         new_modules_loaded = g_new0 (gboolean, module_count + 1);
5956
5957         if (image->assembly->image->modules)
5958                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5959         if (image->assembly->image->modules_loaded)
5960                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5961         new_modules [module_count] = image;
5962         new_modules_loaded [module_count] = TRUE;
5963         mono_image_addref (image);
5964
5965         g_free (image->assembly->image->modules);
5966         image->assembly->image->modules = new_modules;
5967         image->assembly->image->modules_loaded = new_modules_loaded;
5968         image->assembly->image->module_count ++;
5969
5970         mono_assembly_load_references (image, &status);
5971         if (status) {
5972                 mono_image_close (image);
5973                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5974         }
5975
5976         return mono_module_get_object (mono_domain_get (), image);
5977 }
5978
5979 #endif /* DISABLE_REFLECTION_EMIT */
5980
5981 /*
5982  * We need to return always the same object for MethodInfo, FieldInfo etc..
5983  * but we need to consider the reflected type.
5984  * type uses a different hash, since it uses custom hash/equal functions.
5985  */
5986
5987 typedef struct {
5988         gpointer item;
5989         MonoClass *refclass;
5990 } ReflectedEntry;
5991
5992 static gboolean
5993 reflected_equal (gconstpointer a, gconstpointer b) {
5994         const ReflectedEntry *ea = a;
5995         const ReflectedEntry *eb = b;
5996
5997         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5998 }
5999
6000 static guint
6001 reflected_hash (gconstpointer a) {
6002         const ReflectedEntry *ea = a;
6003         return mono_aligned_addr_hash (ea->item);
6004 }
6005
6006 #define CHECK_OBJECT(t,p,k)     \
6007         do {    \
6008                 t _obj; \
6009                 ReflectedEntry e;       \
6010                 e.item = (p);   \
6011                 e.refclass = (k);       \
6012                 mono_domain_lock (domain);      \
6013                 if (!domain->refobject_hash)    \
6014                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6015                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6016                         mono_domain_unlock (domain);    \
6017                         return _obj;    \
6018                 }       \
6019         mono_domain_unlock (domain); \
6020         } while (0)
6021
6022 #ifdef HAVE_BOEHM_GC
6023 /* ReflectedEntry doesn't need to be GC tracked */
6024 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6025 #define FREE_REFENTRY(entry) g_free ((entry))
6026 #define REFENTRY_REQUIRES_CLEANUP
6027 #else
6028 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6029 /* FIXME: */
6030 #define FREE_REFENTRY(entry)
6031 #endif
6032
6033 #define CACHE_OBJECT(t,p,o,k)   \
6034         do {    \
6035                 t _obj; \
6036         ReflectedEntry pe; \
6037         pe.item = (p); \
6038         pe.refclass = (k); \
6039         mono_domain_lock (domain); \
6040                 if (!domain->refobject_hash)    \
6041                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC);      \
6042         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6043         if (!_obj) { \
6044                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6045                     e->item = (p);      \
6046                     e->refclass = (k);  \
6047                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6048             _obj = o; \
6049         } \
6050                 mono_domain_unlock (domain);    \
6051         return _obj; \
6052         } while (0)
6053
6054 static void
6055 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6056 {
6057         mono_domain_lock (domain);
6058         if (domain->refobject_hash) {
6059         ReflectedEntry pe;
6060                 gpointer orig_pe, orig_value;
6061
6062                 pe.item = o;
6063                 pe.refclass = klass;
6064                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6065                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6066                         FREE_REFENTRY (orig_pe);
6067                 }
6068         }
6069         mono_domain_unlock (domain);
6070 }
6071
6072 #ifdef REFENTRY_REQUIRES_CLEANUP
6073 static void
6074 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6075 {
6076         FREE_REFENTRY (key);
6077 }
6078 #endif
6079
6080 void
6081 mono_reflection_cleanup_domain (MonoDomain *domain)
6082 {
6083         if (domain->refobject_hash) {
6084 /*let's avoid scanning the whole hashtable if not needed*/
6085 #ifdef REFENTRY_REQUIRES_CLEANUP
6086                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6087 #endif
6088                 mono_g_hash_table_destroy (domain->refobject_hash);
6089                 domain->refobject_hash = NULL;
6090         }
6091 }
6092
6093 #ifndef DISABLE_REFLECTION_EMIT
6094 static gpointer
6095 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6096 {
6097         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6098 }
6099
6100 static gpointer
6101 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6102 {
6103         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6104 }
6105
6106 void
6107 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6108 {
6109         MonoDynamicImage *image = moduleb->dynamic_image;
6110         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6111         if (!image) {
6112                 MonoError error;
6113                 int module_count;
6114                 MonoImage **new_modules;
6115                 MonoImage *ass;
6116                 char *name, *fqname;
6117                 /*
6118                  * FIXME: we already created an image in mono_image_basic_init (), but
6119                  * we don't know which module it belongs to, since that is only 
6120                  * determined at assembly save time.
6121                  */
6122                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6123                 name = mono_string_to_utf8 (ab->name);
6124                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6125                 if (!mono_error_ok (&error)) {
6126                         g_free (name);
6127                         mono_error_raise_exception (&error);
6128                 }
6129                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6130
6131                 moduleb->module.image = &image->image;
6132                 moduleb->dynamic_image = image;
6133                 register_module (mono_object_domain (moduleb), moduleb, image);
6134
6135                 /* register the module with the assembly */
6136                 ass = ab->dynamic_assembly->assembly.image;
6137                 module_count = ass->module_count;
6138                 new_modules = g_new0 (MonoImage *, module_count + 1);
6139
6140                 if (ass->modules)
6141                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6142                 new_modules [module_count] = &image->image;
6143                 mono_image_addref (&image->image);
6144
6145                 g_free (ass->modules);
6146                 ass->modules = new_modules;
6147                 ass->module_count ++;
6148         }
6149 }
6150
6151 void
6152 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6153 {
6154         MonoDynamicImage *image = moduleb->dynamic_image;
6155
6156         g_assert (type->type);
6157         image->wrappers_type = mono_class_from_mono_type (type->type);
6158 }
6159
6160 #endif
6161
6162 /*
6163  * mono_assembly_get_object:
6164  * @domain: an app domain
6165  * @assembly: an assembly
6166  *
6167  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6168  */
6169 MonoReflectionAssembly*
6170 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6171 {
6172         static MonoClass *assembly_type;
6173         MonoReflectionAssembly *res;
6174         
6175         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6176         if (!assembly_type) {
6177                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6178                 if (class == NULL)
6179                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6180                 g_assert (class);
6181                 assembly_type = class;
6182         }
6183         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6184         res->assembly = assembly;
6185
6186         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6187 }
6188
6189
6190
6191 MonoReflectionModule*   
6192 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6193 {
6194         static MonoClass *module_type;
6195         MonoReflectionModule *res;
6196         char* basename;
6197         
6198         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6199         if (!module_type) {
6200                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6201                 if (class == NULL)
6202                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6203                 g_assert (class);
6204                 module_type = class;
6205         }
6206         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6207
6208         res->image = image;
6209         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6210
6211         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6212         basename = g_path_get_basename (image->name);
6213         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6214         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6215         
6216         g_free (basename);
6217
6218         if (image->assembly->image == image) {
6219                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6220         } else {
6221                 int i;
6222                 res->token = 0;
6223                 if (image->assembly->image->modules) {
6224                         for (i = 0; i < image->assembly->image->module_count; i++) {
6225                                 if (image->assembly->image->modules [i] == image)
6226                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6227                         }
6228                         g_assert (res->token);
6229                 }
6230         }
6231
6232         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6233 }
6234
6235 MonoReflectionModule*   
6236 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6237 {
6238         static MonoClass *module_type;
6239         MonoReflectionModule *res;
6240         MonoTableInfo *table;
6241         guint32 cols [MONO_FILE_SIZE];
6242         const char *name;
6243         guint32 i, name_idx;
6244         const char *val;
6245         
6246         if (!module_type) {
6247                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6248                 if (class == NULL)
6249                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6250                 g_assert (class);
6251                 module_type = class;
6252         }
6253         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6254
6255         table = &image->tables [MONO_TABLE_FILE];
6256         g_assert (table_index < table->rows);
6257         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6258
6259         res->image = NULL;
6260         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6261         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6262
6263         /* Check whenever the row has a corresponding row in the moduleref table */
6264         table = &image->tables [MONO_TABLE_MODULEREF];
6265         for (i = 0; i < table->rows; ++i) {
6266                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6267                 val = mono_metadata_string_heap (image, name_idx);
6268                 if (strcmp (val, name) == 0)
6269                         res->image = image->modules [i];
6270         }
6271
6272         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6273         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6274         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6275         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6276         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6277
6278         return res;
6279 }
6280
6281 static gboolean
6282 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6283 {
6284         if ((t1->type != t2->type) ||
6285             (t1->byref != t2->byref))
6286                 return FALSE;
6287
6288         switch (t1->type) {
6289         case MONO_TYPE_VOID:
6290         case MONO_TYPE_BOOLEAN:
6291         case MONO_TYPE_CHAR:
6292         case MONO_TYPE_I1:
6293         case MONO_TYPE_U1:
6294         case MONO_TYPE_I2:
6295         case MONO_TYPE_U2:
6296         case MONO_TYPE_I4:
6297         case MONO_TYPE_U4:
6298         case MONO_TYPE_I8:
6299         case MONO_TYPE_U8:
6300         case MONO_TYPE_R4:
6301         case MONO_TYPE_R8:
6302         case MONO_TYPE_STRING:
6303         case MONO_TYPE_I:
6304         case MONO_TYPE_U:
6305         case MONO_TYPE_OBJECT:
6306         case MONO_TYPE_TYPEDBYREF:
6307                 return TRUE;
6308         case MONO_TYPE_VALUETYPE:
6309         case MONO_TYPE_CLASS:
6310         case MONO_TYPE_SZARRAY:
6311                 return t1->data.klass == t2->data.klass;
6312         case MONO_TYPE_PTR:
6313                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6314         case MONO_TYPE_ARRAY:
6315                 if (t1->data.array->rank != t2->data.array->rank)
6316                         return FALSE;
6317                 return t1->data.array->eklass == t2->data.array->eklass;
6318         case MONO_TYPE_GENERICINST: {
6319                 int i;
6320                 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6321                 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6322                 if (i1->type_argc != i2->type_argc)
6323                         return FALSE;
6324                 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6325                                                &t2->data.generic_class->container_class->byval_arg))
6326                         return FALSE;
6327                 /* FIXME: we should probably just compare the instance pointers directly.  */
6328                 for (i = 0; i < i1->type_argc; ++i) {
6329                         if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6330                                 return FALSE;
6331                 }
6332                 return TRUE;
6333         }
6334         case MONO_TYPE_VAR:
6335         case MONO_TYPE_MVAR:
6336                 return t1->data.generic_param == t2->data.generic_param;
6337         default:
6338                 g_error ("implement type compare for %0x!", t1->type);
6339                 return FALSE;
6340         }
6341
6342         return FALSE;
6343 }
6344
6345 static guint
6346 mymono_metadata_type_hash (MonoType *t1)
6347 {
6348         guint hash;
6349
6350         hash = t1->type;
6351
6352         hash |= t1->byref << 6; /* do not collide with t1->type values */
6353         switch (t1->type) {
6354         case MONO_TYPE_VALUETYPE:
6355         case MONO_TYPE_CLASS:
6356         case MONO_TYPE_SZARRAY:
6357                 /* check if the distribution is good enough */
6358                 return ((hash << 5) - hash) ^ mono_aligned_addr_hash (t1->data.klass);
6359         case MONO_TYPE_PTR:
6360                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6361         case MONO_TYPE_GENERICINST: {
6362                 int i;
6363                 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6364                 hash += g_str_hash (t1->data.generic_class->container_class->name);
6365                 hash *= 13;
6366                 for (i = 0; i < inst->type_argc; ++i) {
6367                         hash += mymono_metadata_type_hash (inst->type_argv [i]);
6368                         hash *= 13;
6369                 }
6370                 return hash;
6371         }
6372         case MONO_TYPE_VAR:
6373         case MONO_TYPE_MVAR:
6374                 return ((hash << 5) - hash) ^ GPOINTER_TO_UINT (t1->data.generic_param);
6375         }
6376         return hash;
6377 }
6378
6379 static gboolean
6380 verify_safe_for_managed_space (MonoType *type)
6381 {
6382         switch (type->type) {
6383 #ifdef DEBUG_HARDER
6384         case MONO_TYPE_ARRAY:
6385                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6386         case MONO_TYPE_PTR:
6387                 return verify_safe_for_managed_space (type->data.type);
6388         case MONO_TYPE_SZARRAY:
6389                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6390         case MONO_TYPE_GENERICINST: {
6391                 MonoGenericInst *inst = type->data.generic_class->inst;
6392                 int i;
6393                 if (!inst->is_open)
6394                         break;
6395                 for (i = 0; i < inst->type_argc; ++i)
6396                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6397                                 return FALSE;
6398                 break;
6399         }
6400 #endif
6401         case MONO_TYPE_VAR:
6402         case MONO_TYPE_MVAR:
6403                 return TRUE;
6404         }
6405         return TRUE;
6406 }
6407
6408 static MonoType*
6409 mono_type_normalize (MonoType *type)
6410 {
6411         int i;
6412         MonoGenericClass *gclass;
6413         MonoGenericInst *ginst;
6414         MonoClass *gtd;
6415         MonoGenericContainer *gcontainer;
6416         MonoType **argv = NULL;
6417         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6418
6419         if (type->type != MONO_TYPE_GENERICINST)
6420                 return type;
6421
6422         gclass = type->data.generic_class;
6423         ginst = gclass->context.class_inst;
6424         if (!ginst->is_open)
6425                 return type;
6426
6427         gtd = gclass->container_class;
6428         gcontainer = gtd->generic_container;
6429         argv = g_newa (MonoType*, ginst->type_argc);
6430
6431         for (i = 0; i < ginst->type_argc; ++i) {
6432                 MonoType *t = ginst->type_argv [i], *norm;
6433                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6434                         is_denorm_gtd = FALSE;
6435                 norm = mono_type_normalize (t);
6436                 argv [i] = norm;
6437                 if (norm != t)
6438                         requires_rebind = TRUE;
6439         }
6440
6441         if (is_denorm_gtd)
6442                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6443
6444         if (requires_rebind) {
6445                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6446                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6447         }
6448
6449         return type;
6450 }
6451 /*
6452  * mono_type_get_object:
6453  * @domain: an app domain
6454  * @type: a type
6455  *
6456  * Return an System.MonoType object representing the type @type.
6457  */
6458 MonoReflectionType*
6459 mono_type_get_object (MonoDomain *domain, MonoType *type)
6460 {
6461         MonoType *norm_type;
6462         MonoReflectionType *res;
6463         MonoClass *klass = mono_class_from_mono_type (type);
6464
6465         /*we must avoid using @type as it might have come
6466          * from a mono_metadata_type_dup and the caller
6467          * expects that is can be freed.
6468          * Using the right type from 
6469          */
6470         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6471
6472         /* void is very common */
6473         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6474                 return (MonoReflectionType*)domain->typeof_void;
6475
6476         /*
6477          * If the vtable of the given class was already created, we can use
6478          * the MonoType from there and avoid all locking and hash table lookups.
6479          * 
6480          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6481          * that the resulting object is different.   
6482          */
6483         if (type == &klass->byval_arg && !klass->image->dynamic) {
6484                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6485                 if (vtable && vtable->type)
6486                         return vtable->type;
6487         }
6488
6489         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6490         mono_domain_lock (domain);
6491         if (!domain->type_hash)
6492                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6493                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6494         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6495                 mono_domain_unlock (domain);
6496                 mono_loader_unlock ();
6497                 return res;
6498         }
6499
6500         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6501          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6502          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6503          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6504          * artifact of how generics are encoded and should be transparent to managed code so we
6505          * need to weed out this diference when retrieving managed System.Type objects.
6506          */
6507         norm_type = mono_type_normalize (type);
6508         if (norm_type != type) {
6509                 res = mono_type_get_object (domain, norm_type);
6510                 mono_g_hash_table_insert (domain->type_hash, type, res);
6511                 mono_domain_unlock (domain);
6512                 mono_loader_unlock ();
6513                 return res;
6514         }
6515
6516         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6517         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6518                 g_assert (0);
6519
6520         if (!verify_safe_for_managed_space (type)) {
6521                 mono_domain_unlock (domain);
6522                 mono_loader_unlock ();
6523                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6524         }
6525
6526         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6527                 gboolean is_type_done = TRUE;
6528                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6529                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6530                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6531                 */
6532                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6533                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6534
6535                         if (gparam->owner && gparam->owner->is_method) {
6536                                 MonoMethod *method = gparam->owner->owner.method;
6537                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6538                                         is_type_done = FALSE;
6539                         } else if (gparam->owner && !gparam->owner->is_method) {
6540                                 MonoClass *klass = gparam->owner->owner.klass;
6541                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6542                                         is_type_done = FALSE;
6543                         }
6544                 } 
6545
6546                 /* g_assert_not_reached (); */
6547                 /* should this be considered an error condition? */
6548                 if (is_type_done && !type->byref) {
6549                         mono_domain_unlock (domain);
6550                         mono_loader_unlock ();
6551                         return mono_class_get_ref_info (klass);
6552                 }
6553         }
6554 #ifdef HAVE_SGEN_GC
6555         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6556 #else
6557         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6558 #endif
6559         res->type = type;
6560         mono_g_hash_table_insert (domain->type_hash, type, res);
6561
6562         if (type->type == MONO_TYPE_VOID)
6563                 domain->typeof_void = (MonoObject*)res;
6564
6565         mono_domain_unlock (domain);
6566         mono_loader_unlock ();
6567         return res;
6568 }
6569
6570 /*
6571  * mono_method_get_object:
6572  * @domain: an app domain
6573  * @method: a method
6574  * @refclass: the reflected type (can be NULL)
6575  *
6576  * Return an System.Reflection.MonoMethod object representing the method @method.
6577  */
6578 MonoReflectionMethod*
6579 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6580 {
6581         /*
6582          * We use the same C representation for methods and constructors, but the type 
6583          * name in C# is different.
6584          */
6585         static MonoClass *System_Reflection_MonoMethod = NULL;
6586         static MonoClass *System_Reflection_MonoCMethod = NULL;
6587         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6588         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6589         MonoClass *klass;
6590         MonoReflectionMethod *ret;
6591
6592         if (method->is_inflated) {
6593                 MonoReflectionGenericMethod *gret;
6594
6595                 refclass = method->klass;
6596                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6598                         if (!System_Reflection_MonoGenericCMethod)
6599                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6600                         klass = System_Reflection_MonoGenericCMethod;
6601                 } else {
6602                         if (!System_Reflection_MonoGenericMethod)
6603                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6604                         klass = System_Reflection_MonoGenericMethod;
6605                 }
6606                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6607                 gret->method.method = method;
6608                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6609                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6611         }
6612
6613         if (!refclass)
6614                 refclass = method->klass;
6615
6616         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6617         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6618                 if (!System_Reflection_MonoCMethod)
6619                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6620                 klass = System_Reflection_MonoCMethod;
6621         }
6622         else {
6623                 if (!System_Reflection_MonoMethod)
6624                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6625                 klass = System_Reflection_MonoMethod;
6626         }
6627         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6628         ret->method = method;
6629         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6630         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6631 }
6632
6633 /*
6634  * mono_method_clear_object:
6635  *
6636  *   Clear the cached reflection objects for the dynamic method METHOD.
6637  */
6638 void
6639 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6640 {
6641         MonoClass *klass;
6642         g_assert (method->dynamic);
6643
6644         klass = method->klass;
6645         while (klass) {
6646                 clear_cached_object (domain, method, klass);
6647                 klass = klass->parent;
6648         }
6649         /* Added by mono_param_get_objects () */
6650         clear_cached_object (domain, &(method->signature), NULL);
6651         klass = method->klass;
6652         while (klass) {
6653                 clear_cached_object (domain, &(method->signature), klass);
6654                 klass = klass->parent;
6655         }
6656 }
6657
6658 /*
6659  * mono_field_get_object:
6660  * @domain: an app domain
6661  * @klass: a type
6662  * @field: a field
6663  *
6664  * Return an System.Reflection.MonoField object representing the field @field
6665  * in class @klass.
6666  */
6667 MonoReflectionField*
6668 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6669 {
6670         MonoReflectionField *res;
6671         static MonoClass *monofield_klass;
6672
6673         CHECK_OBJECT (MonoReflectionField *, field, klass);
6674         if (!monofield_klass)
6675                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6676         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6677         res->klass = klass;
6678         res->field = field;
6679         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6680
6681         if (is_field_on_inst (field)) {
6682                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6683                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6684         } else {
6685                 if (field->type)
6686                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6687                 res->attrs = mono_field_get_flags (field);
6688         }
6689         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6690 }
6691
6692 /*
6693  * mono_property_get_object:
6694  * @domain: an app domain
6695  * @klass: a type
6696  * @property: a property
6697  *
6698  * Return an System.Reflection.MonoProperty object representing the property @property
6699  * in class @klass.
6700  */
6701 MonoReflectionProperty*
6702 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6703 {
6704         MonoReflectionProperty *res;
6705         static MonoClass *monoproperty_klass;
6706
6707         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6708         if (!monoproperty_klass)
6709                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6710         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6711         res->klass = klass;
6712         res->property = property;
6713         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6714 }
6715
6716 /*
6717  * mono_event_get_object:
6718  * @domain: an app domain
6719  * @klass: a type
6720  * @event: a event
6721  *
6722  * Return an System.Reflection.MonoEvent object representing the event @event
6723  * in class @klass.
6724  */
6725 MonoReflectionEvent*
6726 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6727 {
6728         MonoReflectionEvent *res;
6729         MonoReflectionMonoEvent *mono_event;
6730         static MonoClass *monoevent_klass;
6731
6732         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6733         if (!monoevent_klass)
6734                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6735         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6736         mono_event->klass = klass;
6737         mono_event->event = event;
6738         res = (MonoReflectionEvent*)mono_event;
6739         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6740 }
6741
6742 /**
6743  * mono_get_reflection_missing_object:
6744  * @domain: Domain where the object lives
6745  *
6746  * Returns the System.Reflection.Missing.Value singleton object
6747  * (of type System.Reflection.Missing).
6748  *
6749  * Used as the value for ParameterInfo.DefaultValue when Optional
6750  * is present
6751  */
6752 static MonoObject *
6753 mono_get_reflection_missing_object (MonoDomain *domain)
6754 {
6755         MonoObject *obj;
6756         static MonoClassField *missing_value_field = NULL;
6757         
6758         if (!missing_value_field) {
6759                 MonoClass *missing_klass;
6760                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6761                 mono_class_init (missing_klass);
6762                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6763                 g_assert (missing_value_field);
6764         }
6765         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6766         g_assert (obj);
6767         return obj;
6768 }
6769
6770 static MonoObject*
6771 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6772 {
6773         if (!*dbnull)
6774                 *dbnull = mono_get_dbnull_object (domain);
6775         return *dbnull;
6776 }
6777
6778 static MonoObject*
6779 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6780 {
6781         if (!*reflection_missing)
6782                 *reflection_missing = mono_get_reflection_missing_object (domain);
6783         return *reflection_missing;
6784 }
6785
6786 /*
6787  * mono_param_get_objects:
6788  * @domain: an app domain
6789  * @method: a method
6790  *
6791  * Return an System.Reflection.ParameterInfo array object representing the parameters
6792  * in the method @method.
6793  */
6794 MonoArray*
6795 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6796 {
6797         static MonoClass *System_Reflection_ParameterInfo;
6798         static MonoClass *System_Reflection_ParameterInfo_array;
6799         MonoArray *res = NULL;
6800         MonoReflectionMethod *member = NULL;
6801         MonoReflectionParameter *param = NULL;
6802         char **names, **blobs = NULL;
6803         guint32 *types = NULL;
6804         MonoType *type = NULL;
6805         MonoObject *dbnull = NULL;
6806         MonoObject *missing = NULL;
6807         MonoMarshalSpec **mspecs;
6808         MonoMethodSignature *sig;
6809         MonoVTable *pinfo_vtable;
6810         int i;
6811
6812         if (!System_Reflection_ParameterInfo_array) {
6813                 MonoClass *klass;
6814
6815                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6816                 mono_memory_barrier ();
6817                 System_Reflection_ParameterInfo = klass; 
6818         
6819                 klass = mono_array_class_get (klass, 1);
6820                 mono_memory_barrier ();
6821                 System_Reflection_ParameterInfo_array = klass;
6822         }
6823         
6824         if (!mono_method_signature (method)->param_count)
6825                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6826
6827         /* Note: the cache is based on the address of the signature into the method
6828          * since we already cache MethodInfos with the method as keys.
6829          */
6830         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6831
6832         sig = mono_method_signature (method);
6833         member = mono_method_get_object (domain, method, refclass);
6834         names = g_new (char *, sig->param_count);
6835         mono_method_get_param_names (method, (const char **) names);
6836
6837         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6838         mono_method_get_marshal_info (method, mspecs);
6839
6840         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6841         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6842         for (i = 0; i < sig->param_count; ++i) {
6843                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6844                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6845                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6846                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6847                 param->PositionImpl = i;
6848                 param->AttrsImpl = sig->params [i]->attrs;
6849
6850                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6851                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6852                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6853                         else
6854                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6855                 } else {
6856
6857                         if (!blobs) {
6858                                 blobs = g_new0 (char *, sig->param_count);
6859                                 types = g_new0 (guint32, sig->param_count);
6860                                 get_default_param_value_blobs (method, blobs, types); 
6861                         }
6862
6863                         /* Build MonoType for the type from the Constant Table */
6864                         if (!type)
6865                                 type = g_new0 (MonoType, 1);
6866                         type->type = types [i];
6867                         type->data.klass = NULL;
6868                         if (types [i] == MONO_TYPE_CLASS)
6869                                 type->data.klass = mono_defaults.object_class;
6870                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6871                                 /* For enums, types [i] contains the base type */
6872
6873                                         type->type = MONO_TYPE_VALUETYPE;
6874                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6875                         } else
6876                                 type->data.klass = mono_class_from_mono_type (type);
6877
6878                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6879
6880                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6881                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6882                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6883                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6884                                 else
6885                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6886                         }
6887                         
6888                 }
6889
6890                 if (mspecs [i + 1])
6891                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6892                 
6893                 mono_array_setref (res, i, param);
6894         }
6895         g_free (names);
6896         g_free (blobs);
6897         g_free (types);
6898         g_free (type);
6899
6900         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6901                 if (mspecs [i])
6902                         mono_metadata_free_marshal_spec (mspecs [i]);
6903         g_free (mspecs);
6904         
6905         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6906 }
6907
6908 MonoArray*
6909 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6910 {
6911         return mono_param_get_objects_internal (domain, method, NULL);
6912 }
6913
6914 /*
6915  * mono_method_body_get_object:
6916  * @domain: an app domain
6917  * @method: a method
6918  *
6919  * Return an System.Reflection.MethodBody object representing the method @method.
6920  */
6921 MonoReflectionMethodBody*
6922 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6923 {
6924         static MonoClass *System_Reflection_MethodBody = NULL;
6925         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6926         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6927         MonoReflectionMethodBody *ret;
6928         MonoMethodHeader *header;
6929         MonoImage *image;
6930         guint32 method_rva, local_var_sig_token;
6931     char *ptr;
6932         unsigned char format, flags;
6933         int i;
6934
6935         if (!System_Reflection_MethodBody)
6936                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6937         if (!System_Reflection_LocalVariableInfo)
6938                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6939         if (!System_Reflection_ExceptionHandlingClause)
6940                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6941
6942         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6943
6944         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6945                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6946             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6947             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6948                 return NULL;
6949
6950         image = method->klass->image;
6951         header = mono_method_get_header (method);
6952
6953         if (!image->dynamic) {
6954                 /* Obtain local vars signature token */
6955                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6956                 ptr = mono_image_rva_map (image, method_rva);
6957                 flags = *(const unsigned char *) ptr;
6958                 format = flags & METHOD_HEADER_FORMAT_MASK;
6959                 switch (format){
6960                 case METHOD_HEADER_TINY_FORMAT:
6961                         local_var_sig_token = 0;
6962                         break;
6963                 case METHOD_HEADER_FAT_FORMAT:
6964                         ptr += 2;
6965                         ptr += 2;
6966                         ptr += 4;
6967                         local_var_sig_token = read32 (ptr);
6968                         break;
6969                 default:
6970                         g_assert_not_reached ();
6971                 }
6972         } else
6973                 local_var_sig_token = 0; //FIXME
6974
6975         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6976
6977         ret->init_locals = header->init_locals;
6978         ret->max_stack = header->max_stack;
6979         ret->local_var_sig_token = local_var_sig_token;
6980         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6981         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6982
6983         /* Locals */
6984         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6985         for (i = 0; i < header->num_locals; ++i) {
6986                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6987                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6988                 info->is_pinned = header->locals [i]->pinned;
6989                 info->local_index = i;
6990                 mono_array_setref (ret->locals, i, info);
6991         }
6992
6993         /* Exceptions */
6994         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6995         for (i = 0; i < header->num_clauses; ++i) {
6996                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6997                 MonoExceptionClause *clause = &header->clauses [i];
6998
6999                 info->flags = clause->flags;
7000                 info->try_offset = clause->try_offset;
7001                 info->try_length = clause->try_len;
7002                 info->handler_offset = clause->handler_offset;
7003                 info->handler_length = clause->handler_len;
7004                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7005                         info->filter_offset = clause->data.filter_offset;
7006                 else if (clause->data.catch_class)
7007                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7008
7009                 mono_array_setref (ret->clauses, i, info);
7010         }
7011
7012         mono_metadata_free_mh (header);
7013         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7014         return ret;
7015 }
7016
7017 /**
7018  * mono_get_dbnull_object:
7019  * @domain: Domain where the object lives
7020  *
7021  * Returns the System.DBNull.Value singleton object
7022  *
7023  * Used as the value for ParameterInfo.DefaultValue 
7024  */
7025 MonoObject *
7026 mono_get_dbnull_object (MonoDomain *domain)
7027 {
7028         MonoObject *obj;
7029         static MonoClassField *dbnull_value_field = NULL;
7030         
7031         if (!dbnull_value_field) {
7032                 MonoClass *dbnull_klass;
7033                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7034                 mono_class_init (dbnull_klass);
7035                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7036                 g_assert (dbnull_value_field);
7037         }
7038         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7039         g_assert (obj);
7040         return obj;
7041 }
7042
7043 static void
7044 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7045 {
7046         guint32 param_index, i, lastp, crow = 0;
7047         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7048         gint32 idx;
7049
7050         MonoClass *klass = method->klass;
7051         MonoImage *image = klass->image;
7052         MonoMethodSignature *methodsig = mono_method_signature (method);
7053
7054         MonoTableInfo *constt;
7055         MonoTableInfo *methodt;
7056         MonoTableInfo *paramt;
7057
7058         if (!methodsig->param_count)
7059                 return;
7060
7061         mono_class_init (klass);
7062
7063         if (klass->image->dynamic) {
7064                 MonoReflectionMethodAux *aux;
7065                 if (method->is_inflated)
7066                         method = ((MonoMethodInflated*)method)->declaring;
7067                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7068                 if (aux && aux->param_defaults) {
7069                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7070                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7071                 }
7072                 return;
7073         }
7074
7075         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7076         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7077         constt = &image->tables [MONO_TABLE_CONSTANT];
7078
7079         idx = mono_method_get_index (method) - 1;
7080         g_assert (idx != -1);
7081
7082         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7083         if (idx + 1 < methodt->rows)
7084                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7085         else
7086                 lastp = paramt->rows + 1;
7087
7088         for (i = param_index; i < lastp; ++i) {
7089                 guint32 paramseq;
7090
7091                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7092                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7093
7094                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7095                         continue;
7096
7097                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7098                 if (!crow) {
7099                         continue;
7100                 }
7101         
7102                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7103                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7104                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7105         }
7106
7107         return;
7108 }
7109
7110 MonoObject *
7111 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7112 {
7113         void *retval;
7114         MonoClass *klass;
7115         MonoObject *object;
7116         MonoType *basetype = type;
7117
7118         if (!blob)
7119                 return NULL;
7120         
7121         klass = mono_class_from_mono_type (type);
7122         if (klass->valuetype) {
7123                 object = mono_object_new (domain, klass);
7124                 retval = ((gchar *) object + sizeof (MonoObject));
7125                 if (klass->enumtype)
7126                         basetype = mono_class_enum_basetype (klass);
7127         } else {
7128                 retval = &object;
7129         }
7130                         
7131         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7132                 return object;
7133         else
7134                 return NULL;
7135 }
7136
7137 static int
7138 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7139         int found_sep;
7140         char *s;
7141
7142         memset (assembly, 0, sizeof (MonoAssemblyName));
7143         assembly->name = p;
7144         assembly->culture = "";
7145         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7146
7147         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7148                 p++;
7149         found_sep = 0;
7150         while (g_ascii_isspace (*p) || *p == ',') {
7151                 *p++ = 0;
7152                 found_sep = 1;
7153                 continue;
7154         }
7155         /* failed */
7156         if (!found_sep)
7157                 return 1;
7158         while (*p) {
7159                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7160                         p += 8;
7161                         assembly->major = strtoul (p, &s, 10);
7162                         if (s == p || *s != '.')
7163                                 return 1;
7164                         p = ++s;
7165                         assembly->minor = strtoul (p, &s, 10);
7166                         if (s == p || *s != '.')
7167                                 return 1;
7168                         p = ++s;
7169                         assembly->build = strtoul (p, &s, 10);
7170                         if (s == p || *s != '.')
7171                                 return 1;
7172                         p = ++s;
7173                         assembly->revision = strtoul (p, &s, 10);
7174                         if (s == p)
7175                                 return 1;
7176                         p = s;
7177                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7178                         p += 8;
7179                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7180                                 assembly->culture = "";
7181                                 p += 7;
7182                         } else {
7183                                 assembly->culture = p;
7184                                 while (*p && *p != ',') {
7185                                         p++;
7186                                 }
7187                         }
7188                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7189                         p += 15;
7190                         if (strncmp (p, "null", 4) == 0) {
7191                                 p += 4;
7192                         } else {
7193                                 int len;
7194                                 gchar *start = p;
7195                                 while (*p && *p != ',') {
7196                                         p++;
7197                                 }
7198                                 len = (p - start + 1);
7199                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7200                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7201                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7202                         }
7203                 } else {
7204                         while (*p && *p != ',')
7205                                 p++;
7206                 }
7207                 found_sep = 0;
7208                 while (g_ascii_isspace (*p) || *p == ',') {
7209                         *p++ = 0;
7210                         found_sep = 1;
7211                         continue;
7212                 }
7213                 /* failed */
7214                 if (!found_sep)
7215                         return 1;
7216         }
7217
7218         return 0;
7219 }
7220
7221 /*
7222  * mono_reflection_parse_type:
7223  * @name: type name
7224  *
7225  * Parse a type name as accepted by the GetType () method and output the info
7226  * extracted in the info structure.
7227  * the name param will be mangled, so, make a copy before passing it to this function.
7228  * The fields in info will be valid until the memory pointed to by name is valid.
7229  *
7230  * See also mono_type_get_name () below.
7231  *
7232  * Returns: 0 on parse error.
7233  */
7234 static int
7235 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7236                              MonoTypeNameParse *info)
7237 {
7238         char *start, *p, *w, *temp, *last_point, *startn;
7239         int in_modifiers = 0;
7240         int isbyref = 0, rank, arity = 0, i;
7241
7242         start = p = w = name;
7243
7244         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7245         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7246         info->name = info->name_space = NULL;
7247         info->nested = NULL;
7248         info->modifiers = NULL;
7249         info->type_arguments = NULL;
7250
7251         /* last_point separates the namespace from the name */
7252         last_point = NULL;
7253         /* Skips spaces */
7254         while (*p == ' ') p++, start++, w++, name++;
7255
7256         while (*p) {
7257                 switch (*p) {
7258                 case '+':
7259                         *p = 0; /* NULL terminate the name */
7260                         startn = p + 1;
7261                         info->nested = g_list_append (info->nested, startn);
7262                         /* we have parsed the nesting namespace + name */
7263                         if (info->name)
7264                                 break;
7265                         if (last_point) {
7266                                 info->name_space = start;
7267                                 *last_point = 0;
7268                                 info->name = last_point + 1;
7269                         } else {
7270                                 info->name_space = (char *)"";
7271                                 info->name = start;
7272                         }
7273                         break;
7274                 case '.':
7275                         last_point = p;
7276                         break;
7277                 case '\\':
7278                         ++p;
7279                         break;
7280                 case '&':
7281                 case '*':
7282                 case '[':
7283                 case ',':
7284                 case ']':
7285                         in_modifiers = 1;
7286                         break;
7287                 case '`':
7288                         ++p;
7289                         i = strtol (p, &temp, 10);
7290                         arity += i;
7291                         if (p == temp)
7292                                 return 0;
7293                         p = temp-1;
7294                         break;
7295                 default:
7296                         break;
7297                 }
7298                 if (in_modifiers)
7299                         break;
7300                 // *w++ = *p++;
7301                 p++;
7302         }
7303         
7304         if (!info->name) {
7305                 if (last_point) {
7306                         info->name_space = start;
7307                         *last_point = 0;
7308                         info->name = last_point + 1;
7309                 } else {
7310                         info->name_space = (char *)"";
7311                         info->name = start;
7312                 }
7313         }
7314         while (*p) {
7315                 switch (*p) {
7316                 case '&':
7317                         if (isbyref) /* only one level allowed by the spec */
7318                                 return 0;
7319                         isbyref = 1;
7320                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7321                         *p++ = 0;
7322                         break;
7323                 case '*':
7324                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7325                         *p++ = 0;
7326                         break;
7327                 case '[':
7328                         if (arity != 0) {
7329                                 *p++ = 0;
7330                                 info->type_arguments = g_ptr_array_new ();
7331                                 for (i = 0; i < arity; i++) {
7332                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7333                                         gboolean fqname = FALSE;
7334
7335                                         g_ptr_array_add (info->type_arguments, subinfo);
7336
7337                                         if (*p == '[') {
7338                                                 p++;
7339                                                 fqname = TRUE;
7340                                         }
7341
7342                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7343                                                 return 0;
7344
7345                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7346                                         if (fqname && (*p != ']')) {
7347                                                 char *aname;
7348
7349                                                 if (*p != ',')
7350                                                         return 0;
7351                                                 *p++ = 0;
7352
7353                                                 aname = p;
7354                                                 while (*p && (*p != ']'))
7355                                                         p++;
7356
7357                                                 if (*p != ']')
7358                                                         return 0;
7359
7360                                                 *p++ = 0;
7361                                                 while (*aname) {
7362                                                         if (g_ascii_isspace (*aname)) {
7363                                                                 ++aname;
7364                                                                 continue;
7365                                                         }
7366                                                         break;
7367                                                 }
7368                                                 if (!*aname ||
7369                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7370                                                         return 0;
7371                                         } else if (fqname && (*p == ']')) {
7372                                                 *p++ = 0;
7373                                         }
7374
7375                                         if (i + 1 < arity) {
7376                                                 if (*p != ',')
7377                                                         return 0;
7378                                         } else {
7379                                                 if (*p != ']')
7380                                                         return 0;
7381                                         }
7382                                         *p++ = 0;
7383                                 }
7384
7385                                 arity = 0;
7386                                 break;
7387                         }
7388                         rank = 1;
7389                         *p++ = 0;
7390                         while (*p) {
7391                                 if (*p == ']')
7392                                         break;
7393                                 if (*p == ',')
7394                                         rank++;
7395                                 else if (*p == '*') /* '*' means unknown lower bound */
7396                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7397                                 else
7398                                         return 0;
7399                                 ++p;
7400                         }
7401                         if (*p++ != ']')
7402                                 return 0;
7403                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7404                         break;
7405                 case ']':
7406                         if (is_recursed)
7407                                 goto end;
7408                         return 0;
7409                 case ',':
7410                         if (is_recursed)
7411                                 goto end;
7412                         *p++ = 0;
7413                         while (*p) {
7414                                 if (g_ascii_isspace (*p)) {
7415                                         ++p;
7416                                         continue;
7417                                 }
7418                                 break;
7419                         }
7420                         if (!*p)
7421                                 return 0; /* missing assembly name */
7422                         if (!assembly_name_to_aname (&info->assembly, p))
7423                                 return 0;
7424                         break;
7425                 default:
7426                         return 0;
7427                 }
7428                 if (info->assembly.name)
7429                         break;
7430         }
7431         // *w = 0; /* terminate class name */
7432  end:
7433         if (!info->name || !*info->name)
7434                 return 0;
7435         if (endptr)
7436                 *endptr = p;
7437         /* add other consistency checks */
7438         return 1;
7439 }
7440
7441 int
7442 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7443 {
7444         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7445 }
7446
7447 static MonoType*
7448 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7449 {
7450         gboolean type_resolve = FALSE;
7451         MonoType *type;
7452         MonoImage *rootimage = image;
7453
7454         if (info->assembly.name) {
7455                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7456                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7457                         /* 
7458                          * This could happen in the AOT compiler case when the search hook is not
7459                          * installed.
7460                          */
7461                         assembly = image->assembly;
7462                 if (!assembly) {
7463                         /* then we must load the assembly ourselve - see #60439 */
7464                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7465                         if (!assembly)
7466                                 return NULL;
7467                 }
7468                 image = assembly->image;
7469         } else if (!image) {
7470                 image = mono_defaults.corlib;
7471         }
7472
7473         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7474         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7475                 image = mono_defaults.corlib;
7476                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7477         }
7478
7479         return type;
7480 }
7481
7482 static MonoType*
7483 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7484 {
7485         MonoClass *klass;
7486         GList *mod;
7487         int modval;
7488         gboolean bounded = FALSE;
7489         
7490         if (!image)
7491                 image = mono_defaults.corlib;
7492
7493         if (ignorecase)
7494                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7495         else
7496                 klass = mono_class_from_name (image, info->name_space, info->name);
7497         if (!klass)
7498                 return NULL;
7499         for (mod = info->nested; mod; mod = mod->next) {
7500                 gpointer iter = NULL;
7501                 MonoClass *parent;
7502
7503                 parent = klass;
7504                 mono_class_init (parent);
7505
7506                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7507                         if (ignorecase) {
7508                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7509                                         break;
7510                         } else {
7511                                 if (strcmp (klass->name, mod->data) == 0)
7512                                         break;
7513                         }
7514                 }
7515                 if (!klass)
7516                         break;
7517         }
7518         if (!klass)
7519                 return NULL;
7520
7521         if (info->type_arguments) {
7522                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7523                 MonoReflectionType *the_type;
7524                 MonoType *instance;
7525                 int i;
7526
7527                 for (i = 0; i < info->type_arguments->len; i++) {
7528                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7529
7530                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7531                         if (!type_args [i]) {
7532                                 g_free (type_args);
7533                                 return NULL;
7534                         }
7535                 }
7536
7537                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7538
7539                 instance = mono_reflection_bind_generic_parameters (
7540                         the_type, info->type_arguments->len, type_args);
7541
7542                 g_free (type_args);
7543                 if (!instance)
7544                         return NULL;
7545
7546                 klass = mono_class_from_mono_type (instance);
7547         }
7548
7549         for (mod = info->modifiers; mod; mod = mod->next) {
7550                 modval = GPOINTER_TO_UINT (mod->data);
7551                 if (!modval) { /* byref: must be last modifier */
7552                         return &klass->this_arg;
7553                 } else if (modval == -1) {
7554                         klass = mono_ptr_class_get (&klass->byval_arg);
7555                 } else if (modval == -2) {
7556                         bounded = TRUE;
7557                 } else { /* array rank */
7558                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7559                 }
7560         }
7561
7562         return &klass->byval_arg;
7563 }
7564
7565 /*
7566  * mono_reflection_get_type:
7567  * @image: a metadata context
7568  * @info: type description structure
7569  * @ignorecase: flag for case-insensitive string compares
7570  * @type_resolve: whenever type resolve was already tried
7571  *
7572  * Build a MonoType from the type description in @info.
7573  * 
7574  */
7575
7576 MonoType*
7577 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7578         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7579 }
7580
7581 static MonoType*
7582 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7583 {
7584         MonoReflectionAssemblyBuilder *abuilder;
7585         MonoType *type;
7586         int i;
7587
7588         g_assert (assembly->dynamic);
7589         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7590
7591         /* Enumerate all modules */
7592
7593         type = NULL;
7594         if (abuilder->modules) {
7595                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7596                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7597                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7598                         if (type)
7599                                 break;
7600                 }
7601         }
7602
7603         if (!type && abuilder->loaded_modules) {
7604                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7605                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7606                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7607                         if (type)
7608                                 break;
7609                 }
7610         }
7611
7612         return type;
7613 }
7614         
7615 MonoType*
7616 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7617 {
7618         MonoType *type;
7619         MonoReflectionAssembly *assembly;
7620         GString *fullName;
7621         GList *mod;
7622
7623         if (image && image->dynamic)
7624                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7625         else
7626                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7627         if (type)
7628                 return type;
7629         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7630                 return NULL;
7631
7632         if (type_resolve) {
7633                 if (*type_resolve) 
7634                         return NULL;
7635                 else
7636                         *type_resolve = TRUE;
7637         }
7638         
7639         /* Reconstruct the type name */
7640         fullName = g_string_new ("");
7641         if (info->name_space && (info->name_space [0] != '\0'))
7642                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7643         else
7644                 g_string_printf (fullName, "%s", info->name);
7645         for (mod = info->nested; mod; mod = mod->next)
7646                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7647
7648         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7649         if (assembly) {
7650                 if (assembly->assembly->dynamic)
7651                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7652                 else
7653                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7654                                                                                                           info, ignorecase);
7655         }
7656         g_string_free (fullName, TRUE);
7657         return type;
7658 }
7659
7660 void
7661 mono_reflection_free_type_info (MonoTypeNameParse *info)
7662 {
7663         g_list_free (info->modifiers);
7664         g_list_free (info->nested);
7665
7666         if (info->type_arguments) {
7667                 int i;
7668
7669                 for (i = 0; i < info->type_arguments->len; i++) {
7670                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7671
7672                         mono_reflection_free_type_info (subinfo);
7673                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7674                         g_free (subinfo);
7675                 }
7676
7677                 g_ptr_array_free (info->type_arguments, TRUE);
7678         }
7679 }
7680
7681 /*
7682  * mono_reflection_type_from_name:
7683  * @name: type name.
7684  * @image: a metadata context (can be NULL).
7685  *
7686  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7687  * it defaults to get the type from @image or, if @image is NULL or loading
7688  * from it fails, uses corlib.
7689  * 
7690  */
7691 MonoType*
7692 mono_reflection_type_from_name (char *name, MonoImage *image)
7693 {
7694         MonoType *type = NULL;
7695         MonoTypeNameParse info;
7696         char *tmp;
7697
7698         /* Make a copy since parse_type modifies its argument */
7699         tmp = g_strdup (name);
7700         
7701         /*g_print ("requested type %s\n", str);*/
7702         if (mono_reflection_parse_type (tmp, &info)) {
7703                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7704         }
7705
7706         g_free (tmp);
7707         mono_reflection_free_type_info (&info);
7708         return type;
7709 }
7710
7711 /*
7712  * mono_reflection_get_token:
7713  *
7714  *   Return the metadata token of OBJ which should be an object
7715  * representing a metadata element.
7716  */
7717 guint32
7718 mono_reflection_get_token (MonoObject *obj)
7719 {
7720         MonoClass *klass;
7721         guint32 token = 0;
7722
7723         klass = obj->vtable->klass;
7724
7725         if (strcmp (klass->name, "MethodBuilder") == 0) {
7726                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7727
7728                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7729         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7730                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7731
7732                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7733         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7734                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7735
7736                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7737                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7738         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7739                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7740                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7741         } else if (strcmp (klass->name, "MonoType") == 0) {
7742                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7743                 MonoClass *mc = mono_class_from_mono_type (type);
7744                 if (!mono_class_init (mc))
7745                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7746
7747                 token = mc->type_token;
7748         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7749                    strcmp (klass->name, "MonoMethod") == 0 ||
7750                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7751                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7752                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7753                 if (m->method->is_inflated) {
7754                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7755                         return inflated->declaring->token;
7756                 } else {
7757                         token = m->method->token;
7758                 }
7759         } else if (strcmp (klass->name, "MonoField") == 0) {
7760                 MonoReflectionField *f = (MonoReflectionField*)obj;
7761
7762                 if (is_field_on_inst (f->field)) {
7763                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7764                         int field_index = f->field - dgclass->fields;
7765                         MonoObject *obj;
7766
7767                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7768                         obj = dgclass->field_objects [field_index];
7769                         return mono_reflection_get_token (obj);
7770                 }
7771                 token = mono_class_get_field_token (f->field);
7772         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7773                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7774
7775                 token = mono_class_get_property_token (p->property);
7776         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7777                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7778
7779                 token = mono_class_get_event_token (p->event);
7780         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7781                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7782                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7783                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7784
7785                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7786         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7787                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7788
7789                 token = m->token;
7790         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7791                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7792         } else {
7793                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7794                 MonoException *ex = mono_get_exception_not_implemented (msg);
7795                 g_free (msg);
7796                 mono_raise_exception (ex);
7797         }
7798
7799         return token;
7800 }
7801
7802 static void*
7803 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7804 {
7805         int slen, type = t->type;
7806         MonoClass *tklass = t->data.klass;
7807
7808 handle_enum:
7809         switch (type) {
7810         case MONO_TYPE_U1:
7811         case MONO_TYPE_I1:
7812         case MONO_TYPE_BOOLEAN: {
7813                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7814                 *bval = *p;
7815                 *end = p + 1;
7816                 return bval;
7817         }
7818         case MONO_TYPE_CHAR:
7819         case MONO_TYPE_U2:
7820         case MONO_TYPE_I2: {
7821                 guint16 *val = g_malloc (sizeof (guint16));
7822                 *val = read16 (p);
7823                 *end = p + 2;
7824                 return val;
7825         }
7826 #if SIZEOF_VOID_P == 4
7827         case MONO_TYPE_U:
7828         case MONO_TYPE_I:
7829 #endif
7830         case MONO_TYPE_R4:
7831         case MONO_TYPE_U4:
7832         case MONO_TYPE_I4: {
7833                 guint32 *val = g_malloc (sizeof (guint32));
7834                 *val = read32 (p);
7835                 *end = p + 4;
7836                 return val;
7837         }
7838 #if SIZEOF_VOID_P == 8
7839         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7840         case MONO_TYPE_I:
7841 #endif
7842         case MONO_TYPE_U8:
7843         case MONO_TYPE_I8: {
7844                 guint64 *val = g_malloc (sizeof (guint64));
7845                 *val = read64 (p);
7846                 *end = p + 8;
7847                 return val;
7848         }
7849         case MONO_TYPE_R8: {
7850                 double *val = g_malloc (sizeof (double));
7851                 readr8 (p, val);
7852                 *end = p + 8;
7853                 return val;
7854         }
7855         case MONO_TYPE_VALUETYPE:
7856                 if (t->data.klass->enumtype) {
7857                         type = mono_class_enum_basetype (t->data.klass)->type;
7858                         goto handle_enum;
7859                 } else {
7860                         MonoClass *k =  t->data.klass;
7861                         
7862                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7863                                 guint64 *val = g_malloc (sizeof (guint64));
7864                                 *val = read64 (p);
7865                                 *end = p + 8;
7866                                 return val;
7867                         }
7868                 }
7869                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7870                 break;
7871                 
7872         case MONO_TYPE_STRING:
7873                 if (*p == (char)0xFF) {
7874                         *end = p + 1;
7875                         return NULL;
7876                 }
7877                 slen = mono_metadata_decode_value (p, &p);
7878                 *end = p + slen;
7879                 return mono_string_new_len (mono_domain_get (), p, slen);
7880         case MONO_TYPE_CLASS: {
7881                 char *n;
7882                 MonoType *t;
7883                 if (*p == (char)0xFF) {
7884                         *end = p + 1;
7885                         return NULL;
7886                 }
7887 handle_type:
7888                 slen = mono_metadata_decode_value (p, &p);
7889                 n = g_memdup (p, slen + 1);
7890                 n [slen] = 0;
7891                 t = mono_reflection_type_from_name (n, image);
7892                 if (!t)
7893                         g_warning ("Cannot load type '%s'", n);
7894                 g_free (n);
7895                 *end = p + slen;
7896                 if (t)
7897                         return mono_type_get_object (mono_domain_get (), t);
7898                 else
7899                         return NULL;
7900         }
7901         case MONO_TYPE_OBJECT: {
7902                 char subt = *p++;
7903                 MonoObject *obj;
7904                 MonoClass *subc = NULL;
7905                 void *val;
7906
7907                 if (subt == 0x50) {
7908                         goto handle_type;
7909                 } else if (subt == 0x0E) {
7910                         type = MONO_TYPE_STRING;
7911                         goto handle_enum;
7912                 } else if (subt == 0x1D) {
7913                         MonoType simple_type = {{0}};
7914                         int etype = *p;
7915                         p ++;
7916
7917                         if (etype == 0x51)
7918                                 /* See Partition II, Appendix B3 */
7919                                 etype = MONO_TYPE_OBJECT;
7920                         type = MONO_TYPE_SZARRAY;
7921                         simple_type.type = etype;
7922                         tklass = mono_class_from_mono_type (&simple_type);
7923                         goto handle_enum;
7924                 } else if (subt == 0x55) {
7925                         char *n;
7926                         MonoType *t;
7927                         slen = mono_metadata_decode_value (p, &p);
7928                         n = g_memdup (p, slen + 1);
7929                         n [slen] = 0;
7930                         t = mono_reflection_type_from_name (n, image);
7931                         if (!t)
7932                                 g_error ("Cannot load type '%s'", n);
7933                         g_free (n);
7934                         p += slen;
7935                         subc = mono_class_from_mono_type (t);
7936                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7937                         MonoType simple_type = {{0}};
7938                         simple_type.type = subt;
7939                         subc = mono_class_from_mono_type (&simple_type);
7940                 } else {
7941                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7942                 }
7943                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7944                 obj = mono_object_new (mono_domain_get (), subc);
7945                 g_assert (!subc->has_references);
7946                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7947                 g_free (val);
7948                 return obj;
7949         }
7950         case MONO_TYPE_SZARRAY: {
7951                 MonoArray *arr;
7952                 guint32 i, alen, basetype;
7953                 alen = read32 (p);
7954                 p += 4;
7955                 if (alen == 0xffffffff) {
7956                         *end = p;
7957                         return NULL;
7958                 }
7959                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7960                 basetype = tklass->byval_arg.type;
7961                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7962                         basetype = mono_class_enum_basetype (tklass)->type;
7963                 switch (basetype)
7964                 {
7965                         case MONO_TYPE_U1:
7966                         case MONO_TYPE_I1:
7967                         case MONO_TYPE_BOOLEAN:
7968                                 for (i = 0; i < alen; i++) {
7969                                         MonoBoolean val = *p++;
7970                                         mono_array_set (arr, MonoBoolean, i, val);
7971                                 }
7972                                 break;
7973                         case MONO_TYPE_CHAR:
7974                         case MONO_TYPE_U2:
7975                         case MONO_TYPE_I2:
7976                                 for (i = 0; i < alen; i++) {
7977                                         guint16 val = read16 (p);
7978                                         mono_array_set (arr, guint16, i, val);
7979                                         p += 2;
7980                                 }
7981                                 break;
7982                         case MONO_TYPE_R4:
7983                         case MONO_TYPE_U4:
7984                         case MONO_TYPE_I4:
7985                                 for (i = 0; i < alen; i++) {
7986                                         guint32 val = read32 (p);
7987                                         mono_array_set (arr, guint32, i, val);
7988                                         p += 4;
7989                                 }
7990                                 break;
7991                         case MONO_TYPE_R8:
7992                                 for (i = 0; i < alen; i++) {
7993                                         double val;
7994                                         readr8 (p, &val);
7995                                         mono_array_set (arr, double, i, val);
7996                                         p += 8;
7997                                 }
7998                                 break;
7999                         case MONO_TYPE_U8:
8000                         case MONO_TYPE_I8:
8001                                 for (i = 0; i < alen; i++) {
8002                                         guint64 val = read64 (p);
8003                                         mono_array_set (arr, guint64, i, val);
8004                                         p += 8;
8005                                 }
8006                                 break;
8007                         case MONO_TYPE_CLASS:
8008                         case MONO_TYPE_OBJECT:
8009                         case MONO_TYPE_STRING:
8010                                 for (i = 0; i < alen; i++) {
8011                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8012                                         mono_array_setref (arr, i, item);
8013                                 }
8014                                 break;
8015                         default:
8016                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8017                 }
8018                 *end=p;
8019                 return arr;
8020         }
8021         default:
8022                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8023         }
8024         return NULL;
8025 }
8026
8027 static MonoObject*
8028 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8029 {
8030         static MonoClass *klass;
8031         static MonoMethod *ctor;
8032         MonoObject *retval;
8033         void *params [2], *unboxed;
8034
8035         if (!klass)
8036                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8037         if (!ctor)
8038                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8039         
8040         params [0] = mono_type_get_object (mono_domain_get (), t);
8041         params [1] = val;
8042         retval = mono_object_new (mono_domain_get (), klass);
8043         unboxed = mono_object_unbox (retval);
8044         mono_runtime_invoke (ctor, unboxed, params, NULL);
8045
8046         return retval;
8047 }
8048
8049 static MonoObject*
8050 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8051 {
8052         static MonoClass *klass;
8053         static MonoMethod *ctor;
8054         MonoObject *retval;
8055         void *unboxed, *params [2];
8056
8057         if (!klass)
8058                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8059         if (!ctor)
8060                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8061
8062         params [0] = minfo;
8063         params [1] = typedarg;
8064         retval = mono_object_new (mono_domain_get (), klass);
8065         unboxed = mono_object_unbox (retval);
8066         mono_runtime_invoke (ctor, unboxed, params, NULL);
8067
8068         return retval;
8069 }
8070
8071 static gboolean
8072 type_is_reference (MonoType *type)
8073 {
8074         switch (type->type) {
8075         case MONO_TYPE_BOOLEAN:
8076         case MONO_TYPE_CHAR:
8077         case MONO_TYPE_U:
8078         case MONO_TYPE_I:
8079         case MONO_TYPE_U1:
8080         case MONO_TYPE_I1:
8081         case MONO_TYPE_U2:
8082         case MONO_TYPE_I2:
8083         case MONO_TYPE_U4:
8084         case MONO_TYPE_I4:
8085         case MONO_TYPE_U8:
8086         case MONO_TYPE_I8:
8087         case MONO_TYPE_R8:
8088         case MONO_TYPE_R4:
8089         case MONO_TYPE_VALUETYPE:
8090                 return FALSE;
8091         default:
8092                 return TRUE;
8093         }
8094 }
8095
8096 static void
8097 free_param_data (MonoMethodSignature *sig, void **params) {
8098         int i;
8099         for (i = 0; i < sig->param_count; ++i) {
8100                 if (!type_is_reference (sig->params [i]))
8101                         g_free (params [i]);
8102         }
8103 }
8104
8105 /*
8106  * Find the field index in the metadata FieldDef table.
8107  */
8108 static guint32
8109 find_field_index (MonoClass *klass, MonoClassField *field) {
8110         int i;
8111
8112         for (i = 0; i < klass->field.count; ++i) {
8113                 if (field == &klass->fields [i])
8114                         return klass->field.first + 1 + i;
8115         }
8116         return 0;
8117 }
8118
8119 /*
8120  * Find the property index in the metadata Property table.
8121  */
8122 static guint32
8123 find_property_index (MonoClass *klass, MonoProperty *property) {
8124         int i;
8125
8126         for (i = 0; i < klass->ext->property.count; ++i) {
8127                 if (property == &klass->ext->properties [i])
8128                         return klass->ext->property.first + 1 + i;
8129         }
8130         return 0;
8131 }
8132
8133 /*
8134  * Find the event index in the metadata Event table.
8135  */
8136 static guint32
8137 find_event_index (MonoClass *klass, MonoEvent *event) {
8138         int i;
8139
8140         for (i = 0; i < klass->ext->event.count; ++i) {
8141                 if (event == &klass->ext->events [i])
8142                         return klass->ext->event.first + 1 + i;
8143         }
8144         return 0;
8145 }
8146
8147 static MonoObject*
8148 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8149 {
8150         const char *p = (const char*)data;
8151         const char *named;
8152         guint32 i, j, num_named;
8153         MonoObject *attr;
8154         void *params_buf [32];
8155         void **params;
8156         MonoMethodSignature *sig;
8157
8158         mono_class_init (method->klass);
8159
8160         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8161                 return NULL;
8162
8163         if (len == 0) {
8164                 attr = mono_object_new (mono_domain_get (), method->klass);
8165                 mono_runtime_invoke (method, attr, NULL, NULL);
8166                 return attr;
8167         }
8168
8169         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8170                 return NULL;
8171
8172         /*g_print ("got attr %s\n", method->klass->name);*/
8173
8174         sig = mono_method_signature (method);
8175         if (sig->param_count < 32)
8176                 params = params_buf;
8177         else
8178                 /* Allocate using GC so it gets GC tracking */
8179                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8180
8181         /* skip prolog */
8182         p += 2;
8183         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8184                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8185         }
8186
8187         named = p;
8188         attr = mono_object_new (mono_domain_get (), method->klass);
8189         mono_runtime_invoke (method, attr, params, NULL);
8190         free_param_data (method->signature, params);
8191         num_named = read16 (named);
8192         named += 2;
8193         for (j = 0; j < num_named; j++) {
8194                 gint name_len;
8195                 char *name, named_type, data_type;
8196                 named_type = *named++;
8197                 data_type = *named++; /* type of data */
8198                 if (data_type == MONO_TYPE_SZARRAY)
8199                         data_type = *named++;
8200                 if (data_type == MONO_TYPE_ENUM) {
8201                         gint type_len;
8202                         char *type_name;
8203                         type_len = mono_metadata_decode_blob_size (named, &named);
8204                         type_name = g_malloc (type_len + 1);
8205                         memcpy (type_name, named, type_len);
8206                         type_name [type_len] = 0;
8207                         named += type_len;
8208                         /* FIXME: lookup the type and check type consistency */
8209                         g_free (type_name);
8210                 }
8211                 name_len = mono_metadata_decode_blob_size (named, &named);
8212                 name = g_malloc (name_len + 1);
8213                 memcpy (name, named, name_len);
8214                 name [name_len] = 0;
8215                 named += name_len;
8216                 if (named_type == 0x53) {
8217                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8218                         void *val = load_cattr_value (image, field->type, named, &named);
8219                         mono_field_set_value (attr, field, val);
8220                         if (!type_is_reference (field->type))
8221                                 g_free (val);
8222                 } else if (named_type == 0x54) {
8223                         MonoProperty *prop;
8224                         void *pparams [1];
8225                         MonoType *prop_type;
8226
8227                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8228                         /* can we have more that 1 arg in a custom attr named property? */
8229                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8230                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8231                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8232                         mono_property_set_value (prop, attr, pparams, NULL);
8233                         if (!type_is_reference (prop_type))
8234                                 g_free (pparams [0]);
8235                 }
8236                 g_free (name);
8237         }
8238
8239         if (params != params_buf)
8240                 mono_gc_free_fixed (params);
8241
8242         return attr;
8243 }
8244         
8245 /*
8246  * mono_reflection_create_custom_attr_data_args:
8247  *
8248  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8249  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8250  * NAMED_ARG_INFO will contain information about the named arguments.
8251  */
8252 void
8253 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)
8254 {
8255         MonoArray *typedargs, *namedargs;
8256         MonoClass *attrklass;
8257         MonoDomain *domain;
8258         const char *p = (const char*)data;
8259         const char *named;
8260         guint32 i, j, num_named;
8261         CattrNamedArg *arginfo = NULL;
8262
8263         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8264                 return;
8265
8266         mono_class_init (method->klass);
8267
8268         *typed_args = NULL;
8269         *named_args = NULL;
8270         *named_arg_info = NULL;
8271         
8272         domain = mono_domain_get ();
8273
8274         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8275                 return;
8276
8277         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8278         
8279         /* skip prolog */
8280         p += 2;
8281         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8282                 MonoObject *obj;
8283                 void *val;
8284
8285                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8286                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8287                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8288                 mono_array_setref (typedargs, i, obj);
8289
8290                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8291                         g_free (val);
8292         }
8293
8294         named = p;
8295         num_named = read16 (named);
8296         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8297         named += 2;
8298         attrklass = method->klass;
8299
8300         arginfo = g_new0 (CattrNamedArg, num_named);
8301         *named_arg_info = arginfo;
8302
8303         for (j = 0; j < num_named; j++) {
8304                 gint name_len;
8305                 char *name, named_type, data_type;
8306                 named_type = *named++;
8307                 data_type = *named++; /* type of data */
8308                 if (data_type == MONO_TYPE_SZARRAY)
8309                         data_type = *named++;
8310                 if (data_type == MONO_TYPE_ENUM) {
8311                         gint type_len;
8312                         char *type_name;
8313                         type_len = mono_metadata_decode_blob_size (named, &named);
8314                         type_name = g_malloc (type_len + 1);
8315                         memcpy (type_name, named, type_len);
8316                         type_name [type_len] = 0;
8317                         named += type_len;
8318                         /* FIXME: lookup the type and check type consistency */
8319                         g_free (type_name);
8320                 }
8321                 name_len = mono_metadata_decode_blob_size (named, &named);
8322                 name = g_malloc (name_len + 1);
8323                 memcpy (name, named, name_len);
8324                 name [name_len] = 0;
8325                 named += name_len;
8326                 if (named_type == 0x53) {
8327                         MonoObject *obj;
8328                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8329                         void *val;
8330
8331                         arginfo [j].type = field->type;
8332                         arginfo [j].field = field;
8333
8334                         val = load_cattr_value (image, field->type, named, &named);
8335                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8336                         mono_array_setref (namedargs, j, obj);
8337                         if (!type_is_reference (field->type))
8338                                 g_free (val);
8339                 } else if (named_type == 0x54) {
8340                         MonoObject *obj;
8341                         MonoType *prop_type;
8342                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8343                         void *val;
8344
8345                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8346                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8347
8348                         arginfo [j].type = prop_type;
8349                         arginfo [j].prop = prop;
8350
8351                         val = load_cattr_value (image, prop_type, named, &named);
8352                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8353                         mono_array_setref (namedargs, j, obj);
8354                         if (!type_is_reference (prop_type))
8355                                 g_free (val);
8356                 }
8357                 g_free (name);
8358         }
8359
8360         *typed_args = typedargs;
8361         *named_args = namedargs;
8362 }
8363
8364 void
8365 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8366 {
8367         MonoDomain *domain;
8368         MonoArray *typedargs, *namedargs;
8369         MonoImage *image;
8370         MonoMethod *method;
8371         CattrNamedArg *arginfo;
8372         int i;
8373
8374         *ctor_args = NULL;
8375         *named_args = NULL;
8376
8377         if (len == 0)
8378                 return;
8379
8380         image = assembly->assembly->image;
8381         method = ref_method->method;
8382         domain = mono_object_domain (ref_method);
8383
8384         if (!mono_class_init (method->klass))
8385                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8386
8387         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8388         if (mono_loader_get_last_error ())
8389                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8390
8391         if (!typedargs || !namedargs)
8392                 return;
8393
8394         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8395                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8396                 MonoObject *typedarg;
8397
8398                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8399                 mono_array_setref (typedargs, i, typedarg);
8400         }
8401
8402         for (i = 0; i < mono_array_length (namedargs); ++i) {
8403                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8404                 MonoObject *typedarg, *namedarg, *minfo;
8405
8406                 if (arginfo [i].prop)
8407                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8408                 else
8409                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8410
8411                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8412                 namedarg = create_cattr_named_arg (minfo, typedarg);
8413
8414                 mono_array_setref (namedargs, i, namedarg);
8415         }
8416
8417         *ctor_args = typedargs;
8418         *named_args = namedargs;
8419 }
8420
8421 static MonoObject*
8422 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8423 {
8424         static MonoMethod *ctor;
8425         MonoDomain *domain;
8426         MonoObject *attr;
8427         void *params [4];
8428
8429         g_assert (image->assembly);
8430
8431         if (!ctor)
8432                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8433
8434         domain = mono_domain_get ();
8435         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8436         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8437         params [1] = mono_assembly_get_object (domain, image->assembly);
8438         params [2] = (gpointer)&cattr->data;
8439         params [3] = &cattr->data_size;
8440         mono_runtime_invoke (ctor, attr, params, NULL);
8441         return attr;
8442 }
8443
8444 MonoArray*
8445 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8446 {
8447         MonoArray *result;
8448         MonoObject *attr;
8449         int i;
8450
8451         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8452         for (i = 0; i < cinfo->num_attrs; ++i) {
8453                 if (!cinfo->attrs [i].ctor)
8454                         /* The cattr type is not finished yet */
8455                         /* We should include the type name but cinfo doesn't contain it */
8456                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8457                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8458                 mono_array_setref (result, i, attr);
8459         }
8460         return result;
8461 }
8462
8463 static MonoArray*
8464 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8465 {
8466         MonoArray *result;
8467         MonoObject *attr;
8468         int i, n;
8469
8470         n = 0;
8471         for (i = 0; i < cinfo->num_attrs; ++i) {
8472                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8473                         n ++;
8474         }
8475
8476         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8477         n = 0;
8478         for (i = 0; i < cinfo->num_attrs; ++i) {
8479                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8480                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8481                         mono_array_setref (result, n, attr);
8482                         n ++;
8483                 }
8484         }
8485         return result;
8486 }
8487
8488 static MonoArray*
8489 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8490 {
8491         MonoArray *result;
8492         MonoObject *attr;
8493         int i;
8494         
8495         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8496         for (i = 0; i < cinfo->num_attrs; ++i) {
8497                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8498                 mono_array_setref (result, i, attr);
8499         }
8500         return result;
8501 }
8502
8503 /**
8504  * mono_custom_attrs_from_index:
8505  *
8506  * Returns: NULL if no attributes are found or if a loading error occurs.
8507  */
8508 MonoCustomAttrInfo*
8509 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8510 {
8511         guint32 mtoken, i, len;
8512         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8513         MonoTableInfo *ca;
8514         MonoCustomAttrInfo *ainfo;
8515         GList *tmp, *list = NULL;
8516         const char *data;
8517
8518         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8519
8520         i = mono_metadata_custom_attrs_from_index (image, idx);
8521         if (!i)
8522                 return NULL;
8523         i --;
8524         while (i < ca->rows) {
8525                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8526                         break;
8527                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8528                 ++i;
8529         }
8530         len = g_list_length (list);
8531         if (!len)
8532                 return NULL;
8533         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8534         ainfo->num_attrs = len;
8535         ainfo->image = image;
8536         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8537                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8538                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8539                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8540                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8541                         mtoken |= MONO_TOKEN_METHOD_DEF;
8542                         break;
8543                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8544                         mtoken |= MONO_TOKEN_MEMBER_REF;
8545                         break;
8546                 default:
8547                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8548                         break;
8549                 }
8550                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8551                 if (!ainfo->attrs [i].ctor) {
8552                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8553                         g_list_free (list);
8554                         g_free (ainfo);
8555                         return NULL;
8556                 }
8557
8558                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8559                         /*FIXME raising an exception here doesn't make any sense*/
8560                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8561                         g_list_free (list);
8562                         g_free (ainfo);
8563                         return NULL;
8564                 }
8565                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8566                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8567                 ainfo->attrs [i].data = (guchar*)data;
8568         }
8569         g_list_free (list);
8570
8571         return ainfo;
8572 }
8573
8574 MonoCustomAttrInfo*
8575 mono_custom_attrs_from_method (MonoMethod *method)
8576 {
8577         guint32 idx;
8578
8579         /*
8580          * An instantiated method has the same cattrs as the generic method definition.
8581          *
8582          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8583          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8584          */
8585         if (method->is_inflated)
8586                 method = ((MonoMethodInflated *) method)->declaring;
8587         
8588         if (method->dynamic || method->klass->image->dynamic)
8589                 return lookup_custom_attr (method->klass->image, method);
8590
8591         if (!method->token)
8592                 /* Synthetic methods */
8593                 return NULL;
8594
8595         idx = mono_method_get_index (method);
8596         idx <<= MONO_CUSTOM_ATTR_BITS;
8597         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8598         return mono_custom_attrs_from_index (method->klass->image, idx);
8599 }
8600
8601 MonoCustomAttrInfo*
8602 mono_custom_attrs_from_class (MonoClass *klass)
8603 {
8604         guint32 idx;
8605
8606         if (klass->generic_class)
8607                 klass = klass->generic_class->container_class;
8608
8609         if (klass->image->dynamic)
8610                 return lookup_custom_attr (klass->image, klass);
8611
8612         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8613                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8614                 idx <<= MONO_CUSTOM_ATTR_BITS;
8615                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8616         } else {
8617                 idx = mono_metadata_token_index (klass->type_token);
8618                 idx <<= MONO_CUSTOM_ATTR_BITS;
8619                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8620         }
8621         return mono_custom_attrs_from_index (klass->image, idx);
8622 }
8623
8624 MonoCustomAttrInfo*
8625 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8626 {
8627         guint32 idx;
8628         
8629         if (assembly->image->dynamic)
8630                 return lookup_custom_attr (assembly->image, assembly);
8631         idx = 1; /* there is only one assembly */
8632         idx <<= MONO_CUSTOM_ATTR_BITS;
8633         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8634         return mono_custom_attrs_from_index (assembly->image, idx);
8635 }
8636
8637 static MonoCustomAttrInfo*
8638 mono_custom_attrs_from_module (MonoImage *image)
8639 {
8640         guint32 idx;
8641         
8642         if (image->dynamic)
8643                 return lookup_custom_attr (image, image);
8644         idx = 1; /* there is only one module */
8645         idx <<= MONO_CUSTOM_ATTR_BITS;
8646         idx |= MONO_CUSTOM_ATTR_MODULE;
8647         return mono_custom_attrs_from_index (image, idx);
8648 }
8649
8650 MonoCustomAttrInfo*
8651 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8652 {
8653         guint32 idx;
8654         
8655         if (klass->image->dynamic) {
8656                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8657                 return lookup_custom_attr (klass->image, property);
8658         }
8659         idx = find_property_index (klass, property);
8660         idx <<= MONO_CUSTOM_ATTR_BITS;
8661         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8662         return mono_custom_attrs_from_index (klass->image, idx);
8663 }
8664
8665 MonoCustomAttrInfo*
8666 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8667 {
8668         guint32 idx;
8669         
8670         if (klass->image->dynamic) {
8671                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8672                 return lookup_custom_attr (klass->image, event);
8673         }
8674         idx = find_event_index (klass, event);
8675         idx <<= MONO_CUSTOM_ATTR_BITS;
8676         idx |= MONO_CUSTOM_ATTR_EVENT;
8677         return mono_custom_attrs_from_index (klass->image, idx);
8678 }
8679
8680 MonoCustomAttrInfo*
8681 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8682 {
8683         guint32 idx;
8684         if (klass->image->dynamic) {
8685                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8686                 return lookup_custom_attr (klass->image, field);
8687         }
8688         idx = find_field_index (klass, field);
8689         idx <<= MONO_CUSTOM_ATTR_BITS;
8690         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8691         return mono_custom_attrs_from_index (klass->image, idx);
8692 }
8693
8694 MonoCustomAttrInfo*
8695 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8696 {
8697         MonoTableInfo *ca;
8698         guint32 i, idx, method_index;
8699         guint32 param_list, param_last, param_pos, found;
8700         MonoImage *image;
8701         MonoReflectionMethodAux *aux;
8702
8703         /*
8704          * An instantiated method has the same cattrs as the generic method definition.
8705          *
8706          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8707          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8708          */
8709         if (method->is_inflated)
8710                 method = ((MonoMethodInflated *) method)->declaring;
8711
8712         if (method->klass->image->dynamic) {
8713                 MonoCustomAttrInfo *res, *ainfo;
8714                 int size;
8715
8716                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8717                 if (!aux || !aux->param_cattr)
8718                         return NULL;
8719
8720                 /* Need to copy since it will be freed later */
8721                 ainfo = aux->param_cattr [param];
8722                 if (!ainfo)
8723                         return NULL;
8724                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8725                 res = g_malloc0 (size);
8726                 memcpy (res, ainfo, size);
8727                 return res;
8728         }
8729
8730         image = method->klass->image;
8731         method_index = mono_method_get_index (method);
8732         if (!method_index)
8733                 return NULL;
8734         ca = &image->tables [MONO_TABLE_METHOD];
8735
8736         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8737         if (method_index == ca->rows) {
8738                 ca = &image->tables [MONO_TABLE_PARAM];
8739                 param_last = ca->rows + 1;
8740         } else {
8741                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8742                 ca = &image->tables [MONO_TABLE_PARAM];
8743         }
8744         found = FALSE;
8745         for (i = param_list; i < param_last; ++i) {
8746                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8747                 if (param_pos == param) {
8748                         found = TRUE;
8749                         break;
8750                 }
8751         }
8752         if (!found)
8753                 return NULL;
8754         idx = i;
8755         idx <<= MONO_CUSTOM_ATTR_BITS;
8756         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8757         return mono_custom_attrs_from_index (image, idx);
8758 }
8759
8760 gboolean
8761 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8762 {
8763         int i;
8764         MonoClass *klass;
8765         for (i = 0; i < ainfo->num_attrs; ++i) {
8766                 klass = ainfo->attrs [i].ctor->klass;
8767                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8768                         return TRUE;
8769         }
8770         return FALSE;
8771 }
8772
8773 MonoObject*
8774 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8775 {
8776         int i, attr_index;
8777         MonoClass *klass;
8778         MonoArray *attrs;
8779
8780         attr_index = -1;
8781         for (i = 0; i < ainfo->num_attrs; ++i) {
8782                 klass = ainfo->attrs [i].ctor->klass;
8783                 if (mono_class_has_parent (klass, attr_klass)) {
8784                         attr_index = i;
8785                         break;
8786                 }
8787         }
8788         if (attr_index == -1)
8789                 return NULL;
8790
8791         attrs = mono_custom_attrs_construct (ainfo);
8792         if (attrs)
8793                 return mono_array_get (attrs, MonoObject*, attr_index);
8794         else
8795                 return NULL;
8796 }
8797
8798 /*
8799  * mono_reflection_get_custom_attrs_info:
8800  * @obj: a reflection object handle
8801  *
8802  * Return the custom attribute info for attributes defined for the
8803  * reflection handle @obj. The objects.
8804  *
8805  * FIXME this function leaks like a sieve for SRE objects.
8806  */
8807 MonoCustomAttrInfo*
8808 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8809 {
8810         MonoClass *klass;
8811         MonoCustomAttrInfo *cinfo = NULL;
8812         
8813         klass = obj->vtable->klass;
8814         if (klass == mono_defaults.monotype_class) {
8815                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8816                 klass = mono_class_from_mono_type (type);
8817                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8818                 cinfo = mono_custom_attrs_from_class (klass);
8819         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8820                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8821                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8822         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8823                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8824                 cinfo = mono_custom_attrs_from_module (module->image);
8825         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8826                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8827                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8828         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8829                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8830                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8831         } else if (strcmp ("MonoField", klass->name) == 0) {
8832                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8833                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8834         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8835                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8836                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8837         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8838                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8839                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8840         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8841                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8842                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8843                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8844                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8845                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8846                 } else if (is_sr_mono_property (member_class)) {
8847                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8848                         MonoMethod *method;
8849                         if (!(method = prop->property->get))
8850                                 method = prop->property->set;
8851                         g_assert (method);
8852
8853                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8854                 } 
8855 #ifndef DISABLE_REFLECTION_EMIT
8856                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8857                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8858                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8859                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8860                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8861                         MonoMethod *method = NULL;
8862                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8863                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8864                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8865                                 method = ((MonoReflectionMethod *)c->cb)->method;
8866                         else
8867                                 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));
8868
8869                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8870                 } 
8871 #endif
8872                 else {
8873                         char *type_name = mono_type_get_full_name (member_class);
8874                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8875                         MonoException *ex = mono_get_exception_not_supported  (msg);
8876                         g_free (type_name);
8877                         g_free (msg);
8878                         mono_raise_exception (ex);
8879                 }
8880         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8881                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8882                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8883         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8884                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8885                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8886         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8887                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8888                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8889         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8890                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8891                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8892         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8893                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8894                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8895         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8896                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8897                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8898         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8899                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8900                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8901         } else { /* handle other types here... */
8902                 g_error ("get custom attrs not yet supported for %s", klass->name);
8903         }
8904
8905         return cinfo;
8906 }
8907
8908 /*
8909  * mono_reflection_get_custom_attrs_by_type:
8910  * @obj: a reflection object handle
8911  *
8912  * Return an array with all the custom attributes defined of the
8913  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8914  * of that type are returned. The objects are fully build. Return NULL if a loading error
8915  * occurs.
8916  */
8917 MonoArray*
8918 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8919 {
8920         MonoArray *result;
8921         MonoCustomAttrInfo *cinfo;
8922
8923         cinfo = mono_reflection_get_custom_attrs_info (obj);
8924         if (cinfo) {
8925                 if (attr_klass)
8926                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8927                 else
8928                         result = mono_custom_attrs_construct (cinfo);
8929                 if (!cinfo->cached)
8930                         mono_custom_attrs_free (cinfo);
8931         } else {
8932                 if (mono_loader_get_last_error ())
8933                         return NULL;
8934                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8935         }
8936
8937         return result;
8938 }
8939
8940 /*
8941  * mono_reflection_get_custom_attrs:
8942  * @obj: a reflection object handle
8943  *
8944  * Return an array with all the custom attributes defined of the
8945  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8946  * occurs.
8947  */
8948 MonoArray*
8949 mono_reflection_get_custom_attrs (MonoObject *obj)
8950 {
8951         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8952 }
8953
8954 /*
8955  * mono_reflection_get_custom_attrs_data:
8956  * @obj: a reflection obj handle
8957  *
8958  * Returns an array of System.Reflection.CustomAttributeData,
8959  * which include information about attributes reflected on
8960  * types loaded using the Reflection Only methods
8961  */
8962 MonoArray*
8963 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8964 {
8965         MonoArray *result;
8966         MonoCustomAttrInfo *cinfo;
8967
8968         cinfo = mono_reflection_get_custom_attrs_info (obj);
8969         if (cinfo) {
8970                 result = mono_custom_attrs_data_construct (cinfo);
8971                 if (!cinfo->cached)
8972                         mono_custom_attrs_free (cinfo);
8973         } else
8974                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8975
8976         return result;
8977 }
8978
8979 static MonoReflectionType*
8980 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8981 {
8982         static MonoMethod *method_get_underlying_system_type = NULL;
8983         MonoMethod *usertype_method;
8984
8985         if (!method_get_underlying_system_type)
8986                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8987         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8988         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8989 }
8990
8991
8992 static gboolean
8993 is_corlib_type (MonoClass *class)
8994 {
8995         return class->image == mono_defaults.corlib;
8996 }
8997
8998 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8999         static MonoClass *cached_class; \
9000         if (cached_class) \
9001                 return cached_class == _class; \
9002         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9003                 cached_class = _class; \
9004                 return TRUE; \
9005         } \
9006         return FALSE; \
9007 } while (0) \
9008
9009
9010 #ifndef DISABLE_REFLECTION_EMIT
9011 static gboolean
9012 is_sre_array (MonoClass *class)
9013 {
9014         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9015 }
9016
9017 static gboolean
9018 is_sre_byref (MonoClass *class)
9019 {
9020         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9021 }
9022
9023 static gboolean
9024 is_sre_pointer (MonoClass *class)
9025 {
9026         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9027 }
9028
9029 static gboolean
9030 is_sre_generic_instance (MonoClass *class)
9031 {
9032         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9033 }
9034
9035 static gboolean
9036 is_sre_type_builder (MonoClass *class)
9037 {
9038         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9039 }
9040
9041 static gboolean
9042 is_sre_method_builder (MonoClass *class)
9043 {
9044         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9045 }
9046
9047 static gboolean
9048 is_sre_ctor_builder (MonoClass *class)
9049 {
9050         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9051 }
9052
9053 static gboolean
9054 is_sre_field_builder (MonoClass *class)
9055 {
9056         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9057 }
9058
9059 static gboolean
9060 is_sre_method_on_tb_inst (MonoClass *class)
9061 {
9062         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9063 }
9064
9065 static gboolean
9066 is_sre_ctor_on_tb_inst (MonoClass *class)
9067 {
9068         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9069 }
9070
9071 MonoType*
9072 mono_reflection_type_get_handle (MonoReflectionType* ref)
9073 {
9074         MonoClass *class;
9075         if (!ref)
9076                 return NULL;
9077         if (ref->type)
9078                 return ref->type;
9079
9080         if (is_usertype (ref)) {
9081                 ref = mono_reflection_type_get_underlying_system_type (ref);
9082                 if (ref == NULL || is_usertype (ref))
9083                         return NULL;
9084                 if (ref->type)
9085                         return ref->type;
9086         }
9087
9088         class = mono_object_class (ref);
9089
9090         if (is_sre_array (class)) {
9091                 MonoType *res;
9092                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9093                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9094                 g_assert (base);
9095                 if (sre_array->rank == 0) //single dimentional array
9096                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9097                 else
9098                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9099                 sre_array->type.type = res;
9100                 return res;
9101         } else if (is_sre_byref (class)) {
9102                 MonoType *res;
9103                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9104                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9105                 g_assert (base);
9106                 res = &mono_class_from_mono_type (base)->this_arg;
9107                 sre_byref->type.type = res;
9108                 return res;
9109         } else if (is_sre_pointer (class)) {
9110                 MonoType *res;
9111                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9112                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9113                 g_assert (base);
9114                 res = &mono_ptr_class_get (base)->byval_arg;
9115                 sre_pointer->type.type = res;
9116                 return res;
9117         } else if (is_sre_generic_instance (class)) {
9118                 MonoType *res, **types;
9119                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9120                 int i, count;
9121
9122                 count = mono_array_length (gclass->type_arguments);
9123                 types = g_new0 (MonoType*, count);
9124                 for (i = 0; i < count; ++i) {
9125                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9126                         types [i] = mono_reflection_type_get_handle (t);
9127                         if (!types[i]) {
9128                                 g_free (types);
9129                                 return NULL;
9130                         }
9131                 }
9132
9133                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9134                 g_free (types);
9135                 g_assert (res);
9136                 gclass->type.type = res;
9137                 return res;
9138         }
9139
9140         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9141         return NULL;
9142 }
9143
9144
9145
9146 void
9147 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9148 {
9149         mono_reflection_type_get_handle (type);
9150 }
9151
9152 void
9153 mono_reflection_register_with_runtime (MonoReflectionType *type)
9154 {
9155         MonoType *res = mono_reflection_type_get_handle (type);
9156         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9157         MonoClass *class;
9158
9159         if (!res)
9160                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9161
9162         class = mono_class_from_mono_type (res);
9163
9164         mono_loader_lock (); /*same locking as mono_type_get_object*/
9165         mono_domain_lock (domain);
9166
9167         if (!class->image->dynamic) {
9168                 mono_class_setup_supertypes (class);
9169         } else {
9170                 if (!domain->type_hash)
9171                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
9172                                         (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9173                 mono_g_hash_table_insert (domain->type_hash, res, type);
9174         }
9175         mono_domain_unlock (domain);
9176         mono_loader_unlock ();
9177 }
9178
9179 /**
9180  * LOCKING: Assumes the loader lock is held.
9181  */
9182 static MonoMethodSignature*
9183 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9184         MonoMethodSignature *sig;
9185         int count, i;
9186
9187         count = parameters? mono_array_length (parameters): 0;
9188
9189         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9190         sig->param_count = count;
9191         sig->sentinelpos = -1; /* FIXME */
9192         for (i = 0; i < count; ++i)
9193                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9194         return sig;
9195 }
9196
9197 /**
9198  * LOCKING: Assumes the loader lock is held.
9199  */
9200 static MonoMethodSignature*
9201 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9202         MonoMethodSignature *sig;
9203
9204         sig = parameters_to_signature (image, ctor->parameters);
9205         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9206         sig->ret = &mono_defaults.void_class->byval_arg;
9207         return sig;
9208 }
9209
9210 /**
9211  * LOCKING: Assumes the loader lock is held.
9212  */
9213 static MonoMethodSignature*
9214 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9215         MonoMethodSignature *sig;
9216
9217         sig = parameters_to_signature (image, method->parameters);
9218         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9219         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9220         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9221         return sig;
9222 }
9223
9224 static MonoMethodSignature*
9225 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9226         MonoMethodSignature *sig;
9227
9228         sig = parameters_to_signature (NULL, method->parameters);
9229         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9230         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9231         sig->generic_param_count = 0;
9232         return sig;
9233 }
9234
9235 static void
9236 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9237 {
9238         MonoClass *klass = mono_object_class (prop);
9239         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9240                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9241                 *name = mono_string_to_utf8 (pb->name);
9242                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9243         } else {
9244                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9245                 *name = g_strdup (p->property->name);
9246                 if (p->property->get)
9247                         *type = mono_method_signature (p->property->get)->ret;
9248                 else
9249                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9250         }
9251 }
9252
9253 static void
9254 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9255 {
9256         MonoClass *klass = mono_object_class (field);
9257         if (strcmp (klass->name, "FieldBuilder") == 0) {
9258                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9259                 *name = mono_string_to_utf8 (fb->name);
9260                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9261         } else {
9262                 MonoReflectionField *f = (MonoReflectionField *)field;
9263                 *name = g_strdup (mono_field_get_name (f->field));
9264                 *type = f->field->type;
9265         }
9266 }
9267
9268 #else /* DISABLE_REFLECTION_EMIT */
9269
9270 void
9271 mono_reflection_register_with_runtime (MonoReflectionType *type)
9272 {
9273         /* This is empty */
9274 }
9275
9276 static gboolean
9277 is_sre_type_builder (MonoClass *class)
9278 {
9279         return FALSE;
9280 }
9281
9282 static gboolean
9283 is_sre_generic_instance (MonoClass *class)
9284 {
9285         return FALSE;
9286 }
9287
9288 #endif /* !DISABLE_REFLECTION_EMIT */
9289
9290
9291 static gboolean
9292 is_sr_mono_field (MonoClass *class)
9293 {
9294         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9295 }
9296
9297 static gboolean
9298 is_sr_mono_property (MonoClass *class)
9299 {
9300         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9301 }
9302
9303 static gboolean
9304 is_sr_mono_method (MonoClass *class)
9305 {
9306         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9307 }
9308
9309 static gboolean
9310 is_sr_mono_cmethod (MonoClass *class)
9311 {
9312         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9313 }
9314
9315 static gboolean
9316 is_sr_mono_generic_method (MonoClass *class)
9317 {
9318         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9319 }
9320
9321 static gboolean
9322 is_sr_mono_generic_cmethod (MonoClass *class)
9323 {
9324         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9325 }
9326
9327 gboolean
9328 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9329 {
9330         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9331 }
9332
9333 static gboolean
9334 is_usertype (MonoReflectionType *ref)
9335 {
9336         MonoClass *class = mono_object_class (ref);
9337         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9338 }
9339
9340 static MonoReflectionType*
9341 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9342 {
9343         if (!type || type->type)
9344                 return type;
9345
9346         if (is_usertype (type)) {
9347                 type = mono_reflection_type_get_underlying_system_type (type);
9348                 if (is_usertype (type))
9349                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9350         }
9351
9352         return type;
9353 }
9354 /*
9355  * Encode a value in a custom attribute stream of bytes.
9356  * The value to encode is either supplied as an object in argument val
9357  * (valuetypes are boxed), or as a pointer to the data in the
9358  * argument argval.
9359  * @type represents the type of the value
9360  * @buffer is the start of the buffer
9361  * @p the current position in the buffer
9362  * @buflen contains the size of the buffer and is used to return the new buffer size
9363  * if this needs to be realloced.
9364  * @retbuffer and @retp return the start and the position of the buffer
9365  */
9366 static void
9367 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9368 {
9369         MonoTypeEnum simple_type;
9370         
9371         if ((p-buffer) + 10 >= *buflen) {
9372                 char *newbuf;
9373                 *buflen *= 2;
9374                 newbuf = g_realloc (buffer, *buflen);
9375                 p = newbuf + (p-buffer);
9376                 buffer = newbuf;
9377         }
9378         if (!argval)
9379                 argval = ((char*)arg + sizeof (MonoObject));
9380         simple_type = type->type;
9381 handle_enum:
9382         switch (simple_type) {
9383         case MONO_TYPE_BOOLEAN:
9384         case MONO_TYPE_U1:
9385         case MONO_TYPE_I1:
9386                 *p++ = *argval;
9387                 break;
9388         case MONO_TYPE_CHAR:
9389         case MONO_TYPE_U2:
9390         case MONO_TYPE_I2:
9391                 swap_with_size (p, argval, 2, 1);
9392                 p += 2;
9393                 break;
9394         case MONO_TYPE_U4:
9395         case MONO_TYPE_I4:
9396         case MONO_TYPE_R4:
9397                 swap_with_size (p, argval, 4, 1);
9398                 p += 4;
9399                 break;
9400         case MONO_TYPE_R8:
9401 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9402                 p [0] = argval [4];
9403                 p [1] = argval [5];
9404                 p [2] = argval [6];
9405                 p [3] = argval [7];
9406                 p [4] = argval [0];
9407                 p [5] = argval [1];
9408                 p [6] = argval [2];
9409                 p [7] = argval [3];
9410 #else
9411                 swap_with_size (p, argval, 8, 1);
9412 #endif
9413                 p += 8;
9414                 break;
9415         case MONO_TYPE_U8:
9416         case MONO_TYPE_I8:
9417                 swap_with_size (p, argval, 8, 1);
9418                 p += 8;
9419                 break;
9420         case MONO_TYPE_VALUETYPE:
9421                 if (type->data.klass->enumtype) {
9422                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9423                         goto handle_enum;
9424                 } else {
9425                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9426                 }
9427                 break;
9428         case MONO_TYPE_STRING: {
9429                 char *str;
9430                 guint32 slen;
9431                 if (!arg) {
9432                         *p++ = 0xFF;
9433                         break;
9434                 }
9435                 str = mono_string_to_utf8 ((MonoString*)arg);
9436                 slen = strlen (str);
9437                 if ((p-buffer) + 10 + slen >= *buflen) {
9438                         char *newbuf;
9439                         *buflen *= 2;
9440                         *buflen += slen;
9441                         newbuf = g_realloc (buffer, *buflen);
9442                         p = newbuf + (p-buffer);
9443                         buffer = newbuf;
9444                 }
9445                 mono_metadata_encode_value (slen, p, &p);
9446                 memcpy (p, str, slen);
9447                 p += slen;
9448                 g_free (str);
9449                 break;
9450         }
9451         case MONO_TYPE_CLASS: {
9452                 char *str;
9453                 guint32 slen;
9454                 if (!arg) {
9455                         *p++ = 0xFF;
9456                         break;
9457                 }
9458 handle_type:
9459                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9460                 slen = strlen (str);
9461                 if ((p-buffer) + 10 + slen >= *buflen) {
9462                         char *newbuf;
9463                         *buflen *= 2;
9464                         *buflen += slen;
9465                         newbuf = g_realloc (buffer, *buflen);
9466                         p = newbuf + (p-buffer);
9467                         buffer = newbuf;
9468                 }
9469                 mono_metadata_encode_value (slen, p, &p);
9470                 memcpy (p, str, slen);
9471                 p += slen;
9472                 g_free (str);
9473                 break;
9474         }
9475         case MONO_TYPE_SZARRAY: {
9476                 int len, i;
9477                 MonoClass *eclass, *arg_eclass;
9478
9479                 if (!arg) {
9480                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9481                         break;
9482                 }
9483                 len = mono_array_length ((MonoArray*)arg);
9484                 *p++ = len & 0xff;
9485                 *p++ = (len >> 8) & 0xff;
9486                 *p++ = (len >> 16) & 0xff;
9487                 *p++ = (len >> 24) & 0xff;
9488                 *retp = p;
9489                 *retbuffer = buffer;
9490                 eclass = type->data.klass;
9491                 arg_eclass = mono_object_class (arg)->element_class;
9492
9493                 if (!eclass) {
9494                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9495                         eclass = mono_defaults.object_class;
9496                 }
9497                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9498                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9499                         int elsize = mono_class_array_element_size (arg_eclass);
9500                         for (i = 0; i < len; ++i) {
9501                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9502                                 elptr += elsize;
9503                         }
9504                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9505                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9506                         int elsize = mono_class_array_element_size (eclass);
9507                         for (i = 0; i < len; ++i) {
9508                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9509                                 elptr += elsize;
9510                         }
9511                 } else {
9512                         for (i = 0; i < len; ++i) {
9513                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9514                         }
9515                 }
9516                 break;
9517         }
9518         case MONO_TYPE_OBJECT: {
9519                 MonoClass *klass;
9520                 char *str;
9521                 guint32 slen;
9522
9523                 /*
9524                  * The parameter type is 'object' but the type of the actual
9525                  * argument is not. So we have to add type information to the blob
9526                  * too. This is completely undocumented in the spec.
9527                  */
9528
9529                 if (arg == NULL) {
9530                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9531                         *p++ = 0xFF;
9532                         break;
9533                 }
9534                 
9535                 klass = mono_object_class (arg);
9536
9537                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9538                         *p++ = 0x50;
9539                         goto handle_type;
9540                 } else if (klass->enumtype) {
9541                         *p++ = 0x55;
9542                 } else if (klass == mono_defaults.string_class) {
9543                         simple_type = MONO_TYPE_STRING;
9544                         *p++ = 0x0E;
9545                         goto handle_enum;
9546                 } else if (klass->rank == 1) {
9547                         *p++ = 0x1D;
9548                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9549                                 /* See Partition II, Appendix B3 */
9550                                 *p++ = 0x51;
9551                         else
9552                                 *p++ = klass->element_class->byval_arg.type;
9553                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9554                         break;
9555                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9556                         *p++ = simple_type = klass->byval_arg.type;
9557                         goto handle_enum;
9558                 } else {
9559                         g_error ("unhandled type in custom attr");
9560                 }
9561                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9562                 slen = strlen (str);
9563                 if ((p-buffer) + 10 + slen >= *buflen) {
9564                         char *newbuf;
9565                         *buflen *= 2;
9566                         *buflen += slen;
9567                         newbuf = g_realloc (buffer, *buflen);
9568                         p = newbuf + (p-buffer);
9569                         buffer = newbuf;
9570                 }
9571                 mono_metadata_encode_value (slen, p, &p);
9572                 memcpy (p, str, slen);
9573                 p += slen;
9574                 g_free (str);
9575                 simple_type = mono_class_enum_basetype (klass)->type;
9576                 goto handle_enum;
9577         }
9578         default:
9579                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9580         }
9581         *retp = p;
9582         *retbuffer = buffer;
9583 }
9584
9585 static void
9586 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9587 {
9588         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9589                 char *str = type_get_qualified_name (type, NULL);
9590                 int slen = strlen (str);
9591
9592                 *p++ = 0x55;
9593                 /*
9594                  * This seems to be optional...
9595                  * *p++ = 0x80;
9596                  */
9597                 mono_metadata_encode_value (slen, p, &p);
9598                 memcpy (p, str, slen);
9599                 p += slen;
9600                 g_free (str);
9601         } else if (type->type == MONO_TYPE_OBJECT) {
9602                 *p++ = 0x51;
9603         } else if (type->type == MONO_TYPE_CLASS) {
9604                 /* it should be a type: encode_cattr_value () has the check */
9605                 *p++ = 0x50;
9606         } else {
9607                 mono_metadata_encode_value (type->type, p, &p);
9608                 if (type->type == MONO_TYPE_SZARRAY)
9609                         /* See the examples in Partition VI, Annex B */
9610                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9611         }
9612
9613         *retp = p;
9614 }
9615
9616 #ifndef DISABLE_REFLECTION_EMIT
9617 static void
9618 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9619 {
9620         int len;
9621         /* Preallocate a large enough buffer */
9622         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9623                 char *str = type_get_qualified_name (type, NULL);
9624                 len = strlen (str);
9625                 g_free (str);
9626         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9627                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9628                 len = strlen (str);
9629                 g_free (str);
9630         } else {
9631                 len = 0;
9632         }
9633         len += strlen (name);
9634
9635         if ((p-buffer) + 20 + len >= *buflen) {
9636                 char *newbuf;
9637                 *buflen *= 2;
9638                 *buflen += len;
9639                 newbuf = g_realloc (buffer, *buflen);
9640                 p = newbuf + (p-buffer);
9641                 buffer = newbuf;
9642         }
9643
9644         encode_field_or_prop_type (type, p, &p);
9645
9646         len = strlen (name);
9647         mono_metadata_encode_value (len, p, &p);
9648         memcpy (p, name, len);
9649         p += len;
9650         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9651         *retp = p;
9652         *retbuffer = buffer;
9653 }
9654
9655 /*
9656  * mono_reflection_get_custom_attrs_blob:
9657  * @ctor: custom attribute constructor
9658  * @ctorArgs: arguments o the constructor
9659  * @properties:
9660  * @propValues:
9661  * @fields:
9662  * @fieldValues:
9663  * 
9664  * Creates the blob of data that needs to be saved in the metadata and that represents
9665  * the custom attributed described by @ctor, @ctorArgs etc.
9666  * Returns: a Byte array representing the blob of data.
9667  */
9668 MonoArray*
9669 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9670 {
9671         MonoArray *result;
9672         MonoMethodSignature *sig;
9673         MonoObject *arg;
9674         char *buffer, *p;
9675         guint32 buflen, i;
9676
9677         MONO_ARCH_SAVE_REGS;
9678
9679         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9680                 /* sig is freed later so allocate it in the heap */
9681                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9682         } else {
9683                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9684         }
9685
9686         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9687         buflen = 256;
9688         p = buffer = g_malloc (buflen);
9689         /* write the prolog */
9690         *p++ = 1;
9691         *p++ = 0;
9692         for (i = 0; i < sig->param_count; ++i) {
9693                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9694                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9695         }
9696         i = 0;
9697         if (properties)
9698                 i += mono_array_length (properties);
9699         if (fields)
9700                 i += mono_array_length (fields);
9701         *p++ = i & 0xff;
9702         *p++ = (i >> 8) & 0xff;
9703         if (properties) {
9704                 MonoObject *prop;
9705                 for (i = 0; i < mono_array_length (properties); ++i) {
9706                         MonoType *ptype;
9707                         char *pname;
9708
9709                         prop = mono_array_get (properties, gpointer, i);
9710                         get_prop_name_and_type (prop, &pname, &ptype);
9711                         *p++ = 0x54; /* PROPERTY signature */
9712                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9713                         g_free (pname);
9714                 }
9715         }
9716
9717         if (fields) {
9718                 MonoObject *field;
9719                 for (i = 0; i < mono_array_length (fields); ++i) {
9720                         MonoType *ftype;
9721                         char *fname;
9722
9723                         field = mono_array_get (fields, gpointer, i);
9724                         get_field_name_and_type (field, &fname, &ftype);
9725                         *p++ = 0x53; /* FIELD signature */
9726                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9727                         g_free (fname);
9728                 }
9729         }
9730
9731         g_assert (p - buffer <= buflen);
9732         buflen = p - buffer;
9733         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9734         p = mono_array_addr (result, char, 0);
9735         memcpy (p, buffer, buflen);
9736         g_free (buffer);
9737         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9738                 g_free (sig);
9739         return result;
9740 }
9741
9742 /*
9743  * mono_reflection_setup_internal_class:
9744  * @tb: a TypeBuilder object
9745  *
9746  * Creates a MonoClass that represents the TypeBuilder.
9747  * This is a trick that lets us simplify a lot of reflection code
9748  * (and will allow us to support Build and Run assemblies easier).
9749  */
9750 void
9751 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9752 {
9753         MonoError error;
9754         MonoClass *klass, *parent;
9755
9756         MONO_ARCH_SAVE_REGS;
9757
9758         RESOLVE_TYPE (tb->parent);
9759
9760         mono_loader_lock ();
9761
9762         if (tb->parent) {
9763                 /* check so we can compile corlib correctly */
9764                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9765                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9766                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9767                 } else {
9768                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9769                 }
9770         } else {
9771                 parent = NULL;
9772         }
9773         
9774         /* the type has already being created: it means we just have to change the parent */
9775         if (tb->type.type) {
9776                 klass = mono_class_from_mono_type (tb->type.type);
9777                 klass->parent = NULL;
9778                 /* fool mono_class_setup_parent */
9779                 klass->supertypes = NULL;
9780                 mono_class_setup_parent (klass, parent);
9781                 mono_class_setup_mono_type (klass);
9782                 mono_loader_unlock ();
9783                 return;
9784         }
9785
9786         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9787
9788         klass->image = &tb->module->dynamic_image->image;
9789
9790         klass->inited = 1; /* we lie to the runtime */
9791         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9792         if (!mono_error_ok (&error))
9793                 goto failure;
9794         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9795         if (!mono_error_ok (&error))
9796                 goto failure;
9797         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9798         klass->flags = tb->attrs;
9799         
9800         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9801
9802         klass->element_class = klass;
9803
9804         if (mono_class_get_ref_info (klass) == NULL) {
9805
9806                 mono_class_set_ref_info (klass, tb);
9807
9808                 /* Put into cache so mono_class_get () will find it.
9809                 Skip nested types as those should not be available on the global scope. */
9810                 if (!tb->nesting_type) {
9811                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9812                 } else {
9813                         klass->image->reflection_info_unregister_classes =
9814                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9815                 }
9816         } else {
9817                 g_assert (mono_class_get_ref_info (klass) == tb);
9818         }
9819
9820         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9821                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9822
9823         if (parent != NULL) {
9824                 mono_class_setup_parent (klass, parent);
9825         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9826                 const char *old_n = klass->name;
9827                 /* trick to get relative numbering right when compiling corlib */
9828                 klass->name = "BuildingObject";
9829                 mono_class_setup_parent (klass, mono_defaults.object_class);
9830                 klass->name = old_n;
9831         }
9832
9833         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9834                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9835                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9836                 klass->instance_size = sizeof (MonoObject);
9837                 klass->size_inited = 1;
9838                 mono_class_setup_vtable_general (klass, NULL, 0);
9839         }
9840
9841         mono_class_setup_mono_type (klass);
9842
9843         mono_class_setup_supertypes (klass);
9844
9845         /*
9846          * FIXME: handle interfaces.
9847          */
9848
9849         tb->type.type = &klass->byval_arg;
9850
9851         if (tb->nesting_type) {
9852                 g_assert (tb->nesting_type->type);
9853                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9854         }
9855
9856         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9857
9858         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9859         
9860         mono_loader_unlock ();
9861         return;
9862
9863 failure:
9864         mono_loader_unlock ();
9865         mono_error_raise_exception (&error);
9866 }
9867
9868 /*
9869  * mono_reflection_setup_generic_class:
9870  * @tb: a TypeBuilder object
9871  *
9872  * Setup the generic class before adding the first generic parameter.
9873  */
9874 void
9875 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9876 {
9877 }
9878
9879 /*
9880  * mono_reflection_create_generic_class:
9881  * @tb: a TypeBuilder object
9882  *
9883  * Creates the generic class after all generic parameters have been added.
9884  */
9885 void
9886 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9887 {
9888         MonoClass *klass;
9889         int count, i;
9890
9891         MONO_ARCH_SAVE_REGS;
9892
9893         klass = mono_class_from_mono_type (tb->type.type);
9894
9895         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9896
9897         if (klass->generic_container || (count == 0))
9898                 return;
9899
9900         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9901
9902         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9903
9904         klass->generic_container->owner.klass = klass;
9905         klass->generic_container->type_argc = count;
9906         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9907
9908         klass->is_generic = 1;
9909
9910         for (i = 0; i < count; i++) {
9911                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9912                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9913                 klass->generic_container->type_params [i] = *param;
9914                 /*Make sure we are a diferent type instance */
9915                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9916                 klass->generic_container->type_params [i].info.pklass = NULL;
9917                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9918
9919                 g_assert (klass->generic_container->type_params [i].param.owner);
9920         }
9921
9922         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9923 }
9924
9925 /*
9926  * mono_reflection_create_internal_class:
9927  * @tb: a TypeBuilder object
9928  *
9929  * Actually create the MonoClass that is associated with the TypeBuilder.
9930  */
9931 void
9932 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9933 {
9934         MonoClass *klass;
9935
9936         MONO_ARCH_SAVE_REGS;
9937
9938         klass = mono_class_from_mono_type (tb->type.type);
9939
9940         mono_loader_lock ();
9941         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9942                 MonoReflectionFieldBuilder *fb;
9943                 MonoClass *ec;
9944                 MonoType *enum_basetype;
9945
9946                 g_assert (tb->fields != NULL);
9947                 g_assert (mono_array_length (tb->fields) >= 1);
9948
9949                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9950
9951                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9952                         mono_loader_unlock ();
9953                         return;
9954                 }
9955
9956                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9957                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9958                 if (!klass->element_class)
9959                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9960
9961                 /*
9962                  * get the element_class from the current corlib.
9963                  */
9964                 ec = default_class_from_mono_type (enum_basetype);
9965                 klass->instance_size = ec->instance_size;
9966                 klass->size_inited = 1;
9967                 /* 
9968                  * this is almost safe to do with enums and it's needed to be able
9969                  * to create objects of the enum type (for use in SetConstant).
9970                  */
9971                 /* FIXME: Does this mean enums can't have method overrides ? */
9972                 mono_class_setup_vtable_general (klass, NULL, 0);
9973         }
9974         mono_loader_unlock ();
9975 }
9976
9977 static MonoMarshalSpec*
9978 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9979                                                                 MonoReflectionMarshal *minfo)
9980 {
9981         MonoMarshalSpec *res;
9982
9983         res = image_g_new0 (image, MonoMarshalSpec, 1);
9984         res->native = minfo->type;
9985
9986         switch (minfo->type) {
9987         case MONO_NATIVE_LPARRAY:
9988                 res->data.array_data.elem_type = minfo->eltype;
9989                 if (minfo->has_size) {
9990                         res->data.array_data.param_num = minfo->param_num;
9991                         res->data.array_data.num_elem = minfo->count;
9992                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9993                 }
9994                 else {
9995                         res->data.array_data.param_num = -1;
9996                         res->data.array_data.num_elem = -1;
9997                         res->data.array_data.elem_mult = -1;
9998                 }
9999                 break;
10000
10001         case MONO_NATIVE_BYVALTSTR:
10002         case MONO_NATIVE_BYVALARRAY:
10003                 res->data.array_data.num_elem = minfo->count;
10004                 break;
10005
10006         case MONO_NATIVE_CUSTOM:
10007                 if (minfo->marshaltyperef)
10008                         res->data.custom_data.custom_name =
10009                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10010                 if (minfo->mcookie)
10011                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10012                 break;
10013
10014         default:
10015                 break;
10016         }
10017
10018         return res;
10019 }
10020 #endif /* !DISABLE_REFLECTION_EMIT */
10021
10022 MonoReflectionMarshal*
10023 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10024                                                                                    MonoMarshalSpec *spec)
10025 {
10026         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
10027         MonoReflectionMarshal *minfo;
10028         MonoType *mtype;
10029
10030         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10031                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10032                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10033                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10034         }
10035
10036         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10037         minfo->type = spec->native;
10038
10039         switch (minfo->type) {
10040         case MONO_NATIVE_LPARRAY:
10041                 minfo->eltype = spec->data.array_data.elem_type;
10042                 minfo->count = spec->data.array_data.num_elem;
10043                 minfo->param_num = spec->data.array_data.param_num;
10044                 break;
10045
10046         case MONO_NATIVE_BYVALTSTR:
10047         case MONO_NATIVE_BYVALARRAY:
10048                 minfo->count = spec->data.array_data.num_elem;
10049                 break;
10050
10051         case MONO_NATIVE_CUSTOM:
10052                 if (spec->data.custom_data.custom_name) {
10053                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10054                         if (mtype)
10055                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10056
10057                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10058                 }
10059                 if (spec->data.custom_data.cookie)
10060                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10061                 break;
10062
10063         default:
10064                 break;
10065         }
10066
10067         return minfo;
10068 }
10069
10070 #ifndef DISABLE_REFLECTION_EMIT
10071 static MonoMethod*
10072 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10073                                          ReflectionMethodBuilder *rmb,
10074                                          MonoMethodSignature *sig)
10075 {
10076         MonoError error;
10077         MonoMethod *m;
10078         MonoMethodWrapper *wrapperm;
10079         MonoMarshalSpec **specs;
10080         MonoReflectionMethodAux *method_aux;
10081         MonoImage *image;
10082         gboolean dynamic;
10083         int i;
10084
10085         mono_error_init (&error);
10086         /*
10087          * Methods created using a MethodBuilder should have their memory allocated
10088          * inside the image mempool, while dynamic methods should have their memory
10089          * malloc'd.
10090          */
10091         dynamic = rmb->refs != NULL;
10092         image = dynamic ? NULL : klass->image;
10093
10094         if (!dynamic)
10095                 g_assert (!klass->generic_class);
10096
10097         mono_loader_lock ();
10098
10099         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10100                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10101                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10102         else
10103                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10104
10105         wrapperm = (MonoMethodWrapper*)m;
10106
10107         m->dynamic = dynamic;
10108         m->slot = -1;
10109         m->flags = rmb->attrs;
10110         m->iflags = rmb->iattrs;
10111         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10112         g_assert (mono_error_ok (&error));
10113         m->klass = klass;
10114         m->signature = sig;
10115         m->sre_method = TRUE;
10116         m->skip_visibility = rmb->skip_visibility;
10117         if (rmb->table_idx)
10118                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10119
10120         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10121                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10122                         m->string_ctor = 1;
10123
10124                 m->signature->pinvoke = 1;
10125         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10126                 m->signature->pinvoke = 1;
10127
10128                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10129
10130                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10131                 g_assert (mono_error_ok (&error));
10132                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10133                 g_assert (mono_error_ok (&error));
10134                 
10135                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10136
10137                 if (klass->image->dynamic)
10138                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10139
10140                 mono_loader_unlock ();
10141
10142                 return m;
10143         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10144                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10145                 MonoMethodHeader *header;
10146                 guint32 code_size;
10147                 gint32 max_stack, i;
10148                 gint32 num_locals = 0;
10149                 gint32 num_clauses = 0;
10150                 guint8 *code;
10151
10152                 if (rmb->ilgen) {
10153                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10154                         code_size = rmb->ilgen->code_len;
10155                         max_stack = rmb->ilgen->max_stack;
10156                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10157                         if (rmb->ilgen->ex_handlers)
10158                                 num_clauses = method_count_clauses (rmb->ilgen);
10159                 } else {
10160                         if (rmb->code) {
10161                                 code = mono_array_addr (rmb->code, guint8, 0);
10162                                 code_size = mono_array_length (rmb->code);
10163                                 /* we probably need to run a verifier on the code... */
10164                                 max_stack = 8; 
10165                         }
10166                         else {
10167                                 code = NULL;
10168                                 code_size = 0;
10169                                 max_stack = 8;
10170                         }
10171                 }
10172
10173                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10174                 header->code_size = code_size;
10175                 header->code = image_g_malloc (image, code_size);
10176                 memcpy ((char*)header->code, code, code_size);
10177                 header->max_stack = max_stack;
10178                 header->init_locals = rmb->init_locals;
10179                 header->num_locals = num_locals;
10180
10181                 for (i = 0; i < num_locals; ++i) {
10182                         MonoReflectionLocalBuilder *lb = 
10183                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10184
10185                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10186                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10187                 }
10188
10189                 header->num_clauses = num_clauses;
10190                 if (num_clauses) {
10191                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10192                                  rmb->ilgen, num_clauses);
10193                 }
10194
10195                 wrapperm->header = header;
10196         }
10197
10198         if (rmb->generic_params) {
10199                 int count = mono_array_length (rmb->generic_params);
10200                 MonoGenericContainer *container = rmb->generic_container;
10201
10202                 g_assert (container);
10203
10204                 container->type_argc = count;
10205                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10206                 container->owner.method = m;
10207
10208                 m->is_generic = TRUE;
10209                 mono_method_set_generic_container (m, container);
10210
10211                 for (i = 0; i < count; i++) {
10212                         MonoReflectionGenericParam *gp =
10213                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10214                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10215                         container->type_params [i] = *param;
10216                 }
10217
10218                 /*
10219                  * The method signature might have pointers to generic parameters that belong to other methods.
10220                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10221                  * generic parameters.
10222                  */
10223                 for (i = 0; i < m->signature->param_count; ++i) {
10224                         MonoType *t = m->signature->params [i];
10225                         if (t->type == MONO_TYPE_MVAR) {
10226                                 MonoGenericParam *gparam =  t->data.generic_param;
10227                                 if (gparam->num < count) {
10228                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10229                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10230                                 }
10231
10232                         }
10233                 }
10234
10235                 if (klass->generic_container) {
10236                         container->parent = klass->generic_container;
10237                         container->context.class_inst = klass->generic_container->context.class_inst;
10238                 }
10239                 container->context.method_inst = mono_get_shared_generic_inst (container);
10240         }
10241
10242         if (rmb->refs) {
10243                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10244                 int i;
10245                 void **data;
10246
10247                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10248
10249                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10250                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10251                 for (i = 0; i < rmb->nrefs; ++i)
10252                         data [i + 1] = rmb->refs [i];
10253         }
10254
10255         method_aux = NULL;
10256
10257         /* Parameter info */
10258         if (rmb->pinfo) {
10259                 if (!method_aux)
10260                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10261                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10262                 for (i = 0; i <= m->signature->param_count; ++i) {
10263                         MonoReflectionParamBuilder *pb;
10264                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10265                                 if ((i > 0) && (pb->attrs)) {
10266                                         /* Make a copy since it might point to a shared type structure */
10267                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10268                                         m->signature->params [i - 1]->attrs = pb->attrs;
10269                                 }
10270
10271                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10272                                         MonoDynamicImage *assembly;
10273                                         guint32 idx, def_type, len;
10274                                         char *p;
10275                                         const char *p2;
10276
10277                                         if (!method_aux->param_defaults) {
10278                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10279                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10280                                         }
10281                                         assembly = (MonoDynamicImage*)klass->image;
10282                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10283                                         /* Copy the data from the blob since it might get realloc-ed */
10284                                         p = assembly->blob.data + idx;
10285                                         len = mono_metadata_decode_blob_size (p, &p2);
10286                                         len += p2 - p;
10287                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10288                                         method_aux->param_default_types [i] = def_type;
10289                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10290                                 }
10291
10292                                 if (pb->name) {
10293                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10294                                         g_assert (mono_error_ok (&error));
10295                                 }
10296                                 if (pb->cattrs) {
10297                                         if (!method_aux->param_cattr)
10298                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10299                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10300                                 }
10301                         }
10302                 }
10303         }
10304
10305         /* Parameter marshalling */
10306         specs = NULL;
10307         if (rmb->pinfo)         
10308                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10309                         MonoReflectionParamBuilder *pb;
10310                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10311                                 if (pb->marshal_info) {
10312                                         if (specs == NULL)
10313                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10314                                         specs [pb->position] = 
10315                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10316                                 }
10317                         }
10318                 }
10319         if (specs != NULL) {
10320                 if (!method_aux)
10321                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10322                 method_aux->param_marshall = specs;
10323         }
10324
10325         if (klass->image->dynamic && method_aux)
10326                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10327
10328         mono_loader_unlock ();
10329
10330         return m;
10331 }       
10332
10333 static MonoMethod*
10334 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10335 {
10336         ReflectionMethodBuilder rmb;
10337         MonoMethodSignature *sig;
10338
10339         mono_loader_lock ();
10340         sig = ctor_builder_to_signature (klass->image, mb);
10341         mono_loader_unlock ();
10342
10343         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10344
10345         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10346         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10347
10348         /* If we are in a generic class, we might be called multiple times from inflate_method */
10349         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10350                 /* ilgen is no longer needed */
10351                 mb->ilgen = NULL;
10352         }
10353
10354         return mb->mhandle;
10355 }
10356
10357 static MonoMethod*
10358 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10359 {
10360         ReflectionMethodBuilder rmb;
10361         MonoMethodSignature *sig;
10362
10363         mono_loader_lock ();
10364         sig = method_builder_to_signature (klass->image, mb);
10365         mono_loader_unlock ();
10366
10367         reflection_methodbuilder_from_method_builder (&rmb, mb);
10368
10369         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10370         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10371
10372         /* If we are in a generic class, we might be called multiple times from inflate_method */
10373         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10374                 /* ilgen is no longer needed */
10375                 mb->ilgen = NULL;
10376         }
10377         return mb->mhandle;
10378 }
10379
10380 static MonoClassField*
10381 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10382 {
10383         MonoClassField *field;
10384         MonoType *custom;
10385
10386         field = g_new0 (MonoClassField, 1);
10387
10388         field->name = mono_string_to_utf8 (fb->name);
10389         if (fb->attrs || fb->modreq || fb->modopt) {
10390                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10391                 field->type->attrs = fb->attrs;
10392
10393                 g_assert (klass->image->dynamic);
10394                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10395                 g_free (field->type);
10396                 field->type = custom;
10397         } else {
10398                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10399         }
10400         if (fb->offset != -1)
10401                 field->offset = fb->offset;
10402         field->parent = klass;
10403         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10404
10405         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10406
10407         return field;
10408 }
10409 #endif
10410
10411 MonoType*
10412 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10413 {
10414         MonoClass *klass;
10415         MonoReflectionTypeBuilder *tb = NULL;
10416         gboolean is_dynamic = FALSE;
10417         MonoDomain *domain;
10418         MonoClass *geninst;
10419
10420         mono_loader_lock ();
10421
10422         domain = mono_object_domain (type);
10423
10424         if (is_sre_type_builder (mono_object_class (type))) {
10425                 tb = (MonoReflectionTypeBuilder *) type;
10426
10427                 is_dynamic = TRUE;
10428         } else if (is_sre_generic_instance (mono_object_class (type))) {
10429                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10430                 MonoReflectionType *gtd = rgi->generic_type;
10431
10432                 if (is_sre_type_builder (mono_object_class (gtd))) {
10433                         tb = (MonoReflectionTypeBuilder *)gtd;
10434                         is_dynamic = TRUE;
10435                 }
10436         }
10437
10438         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10439         if (tb && tb->generic_container)
10440                 mono_reflection_create_generic_class (tb);
10441
10442         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10443         if (!klass->generic_container) {
10444                 mono_loader_unlock ();
10445                 return NULL;
10446         }
10447
10448         if (klass->wastypebuilder) {
10449                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10450
10451                 is_dynamic = TRUE;
10452         }
10453
10454         mono_loader_unlock ();
10455
10456         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10457
10458         return &geninst->byval_arg;
10459 }
10460
10461 MonoClass*
10462 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10463 {
10464         MonoGenericClass *gclass;
10465         MonoGenericInst *inst;
10466
10467         g_assert (klass->generic_container);
10468
10469         inst = mono_metadata_get_generic_inst (type_argc, types);
10470         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10471
10472         return mono_generic_class_get_class (gclass);
10473 }
10474
10475 MonoReflectionMethod*
10476 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10477 {
10478         MonoClass *klass;
10479         MonoMethod *method, *inflated;
10480         MonoMethodInflated *imethod;
10481         MonoGenericContext tmp_context;
10482         MonoGenericInst *ginst;
10483         MonoType **type_argv;
10484         int count, i;
10485
10486         MONO_ARCH_SAVE_REGS;
10487
10488         /*FIXME but this no longer should happen*/
10489         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10490 #ifndef DISABLE_REFLECTION_EMIT
10491                 MonoReflectionMethodBuilder *mb = NULL;
10492                 MonoReflectionTypeBuilder *tb;
10493                 MonoClass *klass;
10494
10495                 mb = (MonoReflectionMethodBuilder *) rmethod;
10496                 tb = (MonoReflectionTypeBuilder *) mb->type;
10497                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10498
10499                 method = methodbuilder_to_mono_method (klass, mb);
10500 #else
10501                 g_assert_not_reached ();
10502                 method = NULL;
10503 #endif
10504         } else {
10505                 method = rmethod->method;
10506         }
10507
10508         klass = method->klass;
10509
10510         if (method->is_inflated)
10511                 method = ((MonoMethodInflated *) method)->declaring;
10512
10513         count = mono_method_signature (method)->generic_param_count;
10514         if (count != mono_array_length (types))
10515                 return NULL;
10516
10517         type_argv = g_new0 (MonoType *, count);
10518         for (i = 0; i < count; i++) {
10519                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10520                 type_argv [i] = mono_reflection_type_get_handle (garg);
10521         }
10522         ginst = mono_metadata_get_generic_inst (count, type_argv);
10523         g_free (type_argv);
10524
10525         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10526         tmp_context.method_inst = ginst;
10527
10528         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10529         imethod = (MonoMethodInflated *) inflated;
10530
10531         /*FIXME but I think this is no longer necessary*/
10532         if (method->klass->image->dynamic) {
10533                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10534                 /*
10535                  * This table maps metadata structures representing inflated methods/fields
10536                  * to the reflection objects representing their generic definitions.
10537                  */
10538                 mono_loader_lock ();
10539                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10540                 mono_loader_unlock ();
10541         }
10542         
10543         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10544 }
10545
10546 #ifndef DISABLE_REFLECTION_EMIT
10547
10548 static MonoMethod *
10549 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10550 {
10551         MonoMethodInflated *imethod;
10552         MonoGenericContext *context;
10553         int i;
10554
10555         /*
10556          * With generic code sharing the klass might not be inflated.
10557          * This can happen because classes inflated with their own
10558          * type arguments are "normalized" to the uninflated class.
10559          */
10560         if (!klass->generic_class)
10561                 return method;
10562
10563         context = mono_class_get_context (klass);
10564
10565         if (klass->method.count && klass->methods) {
10566                 /* Find the already created inflated method */
10567                 for (i = 0; i < klass->method.count; ++i) {
10568                         g_assert (klass->methods [i]->is_inflated);
10569                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10570                                 break;
10571                 }
10572                 g_assert (i < klass->method.count);
10573                 imethod = (MonoMethodInflated*)klass->methods [i];
10574         } else {
10575                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10576         }
10577
10578         if (method->is_generic && method->klass->image->dynamic) {
10579                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10580
10581                 mono_loader_lock ();
10582                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10583                 mono_loader_unlock ();
10584         }
10585         return (MonoMethod *) imethod;
10586 }
10587
10588 static MonoMethod *
10589 inflate_method (MonoReflectionType *type, MonoObject *obj)
10590 {
10591         MonoMethod *method;
10592         MonoClass *gklass;
10593
10594         MonoClass *type_class = mono_object_class (type);
10595
10596         if (is_sre_generic_instance (type_class)) {
10597                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10598                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10599         } else if (is_sre_type_builder (type_class)) {
10600                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10601         } else if (type->type) {
10602                 gklass = mono_class_from_mono_type (type->type);
10603                 gklass = mono_class_get_generic_type_definition (gklass);
10604         } else {
10605                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10606         }
10607
10608         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10609                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10610                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10611                 else
10612                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10613         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10614                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10615         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10616                 method = ((MonoReflectionMethod *) obj)->method;
10617         else {
10618                 method = NULL; /* prevent compiler warning */
10619                 g_error ("can't handle type %s", obj->vtable->klass->name);
10620         }
10621
10622         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10623 }
10624
10625 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10626 void
10627 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10628                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10629                                           MonoArray *events)
10630 {
10631         MonoGenericClass *gclass;
10632         MonoDynamicGenericClass *dgclass;
10633         MonoClass *klass, *gklass;
10634         MonoType *gtype;
10635         int i;
10636
10637         MONO_ARCH_SAVE_REGS;
10638
10639         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10640         klass = mono_class_from_mono_type (gtype);
10641         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10642         gclass = gtype->data.generic_class;
10643
10644         if (!gclass->is_dynamic)
10645                 return;
10646
10647         dgclass = (MonoDynamicGenericClass *) gclass;
10648
10649         if (dgclass->initialized)
10650                 return;
10651
10652         gklass = gclass->container_class;
10653         mono_class_init (gklass);
10654
10655         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10656         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10657         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10658
10659         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10660         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10661         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10662         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10663         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10664
10665         for (i = 0; i < dgclass->count_methods; i++) {
10666                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10667
10668                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10669         }
10670
10671         for (i = 0; i < dgclass->count_ctors; i++) {
10672                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10673
10674                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10675         }
10676
10677         for (i = 0; i < dgclass->count_fields; i++) {
10678                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10679                 MonoClassField *field, *inflated_field = NULL;
10680
10681                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10682                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10683                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10684                         field = ((MonoReflectionField *) obj)->field;
10685                 else {
10686                         field = NULL; /* prevent compiler warning */
10687                         g_assert_not_reached ();
10688                 }
10689
10690                 dgclass->fields [i] = *field;
10691                 dgclass->fields [i].parent = klass;
10692                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10693                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10694                 dgclass->field_generic_types [i] = field->type;
10695                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10696                 dgclass->field_objects [i] = obj;
10697
10698                 if (inflated_field) {
10699                         g_free (inflated_field);
10700                 } else {
10701                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10702                 }
10703         }
10704
10705         dgclass->initialized = TRUE;
10706 }
10707
10708 static void
10709 fix_partial_generic_class (MonoClass *klass)
10710 {
10711         MonoClass *gklass = klass->generic_class->container_class;
10712         MonoDynamicGenericClass *dgclass;
10713         int i;
10714
10715         if (klass->wastypebuilder)
10716                 return;
10717
10718         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10719         if (klass->parent != gklass->parent) {
10720                 MonoError error;
10721                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10722                 if (mono_error_ok (&error)) {
10723                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10724                         mono_metadata_free_type (parent_type);
10725                         if (parent != klass->parent) {
10726                                 /*fool mono_class_setup_parent*/
10727                                 klass->supertypes = NULL;
10728                                 mono_class_setup_parent (klass, parent);
10729                         }
10730                 } else {
10731                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10732                         mono_error_cleanup (&error);
10733                         if (gklass->wastypebuilder)
10734                                 klass->wastypebuilder = TRUE;
10735                         return;
10736                 }
10737         }
10738
10739         if (!dgclass->initialized)
10740                 return;
10741
10742         if (klass->method.count != gklass->method.count) {
10743                 klass->method.count = gklass->method.count;
10744                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10745
10746                 for (i = 0; i < klass->method.count; i++) {
10747                         klass->methods [i] = mono_class_inflate_generic_method_full (
10748                                 gklass->methods [i], klass, mono_class_get_context (klass));
10749                 }
10750         }
10751
10752         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10753                 klass->interface_count = gklass->interface_count;
10754                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10755                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10756
10757                 for (i = 0; i < gklass->interface_count; ++i) {
10758                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10759                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10760                         mono_metadata_free_type (iface_type);
10761
10762                         ensure_runtime_vtable (klass->interfaces [i]);
10763                 }
10764                 klass->interfaces_inited = 1;
10765         }
10766
10767         if (klass->field.count != gklass->field.count) {
10768                 klass->field.count = gklass->field.count;
10769                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10770
10771                 for (i = 0; i < klass->field.count; i++) {
10772                         klass->fields [i] = gklass->fields [i];
10773                         klass->fields [i].parent = klass;
10774                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10775                 }
10776         }
10777
10778         /*We can only finish with this klass once it's parent has as well*/
10779         if (gklass->wastypebuilder)
10780                 klass->wastypebuilder = TRUE;
10781         return;
10782 }
10783
10784 static void
10785 ensure_generic_class_runtime_vtable (MonoClass *klass)
10786 {
10787         MonoClass *gklass = klass->generic_class->container_class;
10788
10789         ensure_runtime_vtable (gklass); 
10790
10791         fix_partial_generic_class (klass);
10792 }
10793
10794 static void
10795 ensure_runtime_vtable (MonoClass *klass)
10796 {
10797         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10798         int i, num, j;
10799
10800         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10801                 return;
10802         if (klass->parent)
10803                 ensure_runtime_vtable (klass->parent);
10804
10805         if (tb) {
10806                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10807                 num += tb->num_methods;
10808                 klass->method.count = num;
10809                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10810                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10811                 for (i = 0; i < num; ++i)
10812                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10813                 num = tb->num_methods;
10814                 j = i;
10815                 for (i = 0; i < num; ++i)
10816                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10817         
10818                 if (tb->interfaces) {
10819                         klass->interface_count = mono_array_length (tb->interfaces);
10820                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10821                         for (i = 0; i < klass->interface_count; ++i) {
10822                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10823                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10824                                 ensure_runtime_vtable (klass->interfaces [i]);
10825                         }
10826                         klass->interfaces_inited = 1;
10827                 }
10828         } else if (klass->generic_class){
10829                 ensure_generic_class_runtime_vtable (klass);
10830         }
10831
10832         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10833                 for (i = 0; i < klass->method.count; ++i)
10834                         klass->methods [i]->slot = i;
10835                 
10836                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10837                 mono_class_setup_interface_offsets (klass);
10838                 mono_class_setup_interface_id (klass);
10839         }
10840
10841         /*
10842          * The generic vtable is needed even if image->run is not set since some
10843          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10844          * method->slot being defined.
10845          */
10846
10847         /* 
10848          * tb->methods could not be freed since it is used for determining 
10849          * overrides during dynamic vtable construction.
10850          */
10851 }
10852
10853 static MonoMethod*
10854 mono_reflection_method_get_handle (MonoObject *method)
10855 {
10856         MonoClass *class = mono_object_class (method);
10857         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10858                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10859                 return sr_method->method;
10860         }
10861         if (is_sre_method_builder (class)) {
10862                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10863                 return mb->mhandle;
10864         }
10865         if (is_sre_method_on_tb_inst (class)) {
10866                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10867                 MonoMethod *result;
10868                 /*FIXME move this to a proper method and unify with resolve_object*/
10869                 if (m->method_args) {
10870                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10871                 } else {
10872                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10873                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10874                         MonoMethod *mono_method;
10875
10876                         if (is_sre_method_builder (mono_object_class (m->mb)))
10877                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10878                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10879                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10880                         else
10881                                 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)));
10882
10883                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10884                 }
10885                 return result;
10886         }
10887
10888         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10889         return NULL;
10890 }
10891
10892 void
10893 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10894 {
10895         MonoReflectionTypeBuilder *tb;
10896         int i, onum;
10897
10898         *overrides = NULL;
10899         *num_overrides = 0;
10900
10901         g_assert (klass->image->dynamic);
10902
10903         if (!mono_class_get_ref_info (klass))
10904                 return;
10905
10906         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10907
10908         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10909
10910         onum = 0;
10911         if (tb->methods) {
10912                 for (i = 0; i < tb->num_methods; ++i) {
10913                         MonoReflectionMethodBuilder *mb = 
10914                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10915                         if (mb->override_method)
10916                                 onum ++;
10917                 }
10918         }
10919
10920         if (onum) {
10921                 *overrides = g_new0 (MonoMethod*, onum * 2);
10922
10923                 onum = 0;
10924                 for (i = 0; i < tb->num_methods; ++i) {
10925                         MonoReflectionMethodBuilder *mb = 
10926                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10927                         if (mb->override_method) {
10928                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10929                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10930
10931                                 g_assert (mb->mhandle);
10932
10933                                 onum ++;
10934                         }
10935                 }
10936         }
10937
10938         *num_overrides = onum;
10939 }
10940
10941 static void
10942 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10943 {
10944         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10945         MonoReflectionFieldBuilder *fb;
10946         MonoClassField *field;
10947         MonoImage *image = klass->image;
10948         const char *p, *p2;
10949         int i;
10950         guint32 len, idx, real_size = 0;
10951
10952         klass->field.count = tb->num_fields;
10953         klass->field.first = 0;
10954
10955         mono_error_init (error);
10956
10957         if (tb->class_size) {
10958                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
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                 fb = mono_array_get (tb->fields, gpointer, i);
10982                 field = &klass->fields [i];
10983                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10984                 if (!mono_error_ok (error))
10985                         return;
10986                 if (fb->attrs) {
10987                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10988                         field->type->attrs = fb->attrs;
10989                 } else {
10990                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10991                 }
10992                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10993                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10994                 if (fb->offset != -1)
10995                         field->offset = fb->offset;
10996                 field->parent = klass;
10997                 fb->handle = field;
10998                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10999
11000                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11001                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11002                 }
11003                 if (fb->def_value) {
11004                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11005                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11006                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11007                         /* Copy the data from the blob since it might get realloc-ed */
11008                         p = assembly->blob.data + idx;
11009                         len = mono_metadata_decode_blob_size (p, &p2);
11010                         len += p2 - p;
11011                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11012                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11013                 }
11014         }
11015
11016         klass->instance_size = MAX (klass->instance_size, real_size);
11017         mono_class_layout_fields (klass);
11018 }
11019
11020 static void
11021 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11022 {
11023         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11024         MonoReflectionPropertyBuilder *pb;
11025         MonoImage *image = klass->image;
11026         MonoProperty *properties;
11027         int i;
11028
11029         mono_error_init (error);
11030
11031         if (!klass->ext)
11032                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11033
11034         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11035         klass->ext->property.first = 0;
11036
11037         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11038         klass->ext->properties = properties;
11039         for (i = 0; i < klass->ext->property.count; ++i) {
11040                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11041                 properties [i].parent = klass;
11042                 properties [i].attrs = pb->attrs;
11043                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11044                 if (!mono_error_ok (error))
11045                         return;
11046                 if (pb->get_method)
11047                         properties [i].get = pb->get_method->mhandle;
11048                 if (pb->set_method)
11049                         properties [i].set = pb->set_method->mhandle;
11050
11051                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11052                 if (pb->def_value) {
11053                         guint32 len, idx;
11054                         const char *p, *p2;
11055                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11056                         if (!klass->ext->prop_def_values)
11057                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11058                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11059                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11060                         /* Copy the data from the blob since it might get realloc-ed */
11061                         p = assembly->blob.data + idx;
11062                         len = mono_metadata_decode_blob_size (p, &p2);
11063                         len += p2 - p;
11064                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11065                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11066                 }
11067         }
11068 }
11069
11070 MonoReflectionEvent *
11071 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11072 {
11073         MonoEvent *event = g_new0 (MonoEvent, 1);
11074         MonoClass *klass;
11075
11076         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11077
11078         event->parent = klass;
11079         event->attrs = eb->attrs;
11080         event->name = mono_string_to_utf8 (eb->name);
11081         if (eb->add_method)
11082                 event->add = eb->add_method->mhandle;
11083         if (eb->remove_method)
11084                 event->remove = eb->remove_method->mhandle;
11085         if (eb->raise_method)
11086                 event->raise = eb->raise_method->mhandle;
11087
11088 #ifndef MONO_SMALL_CONFIG
11089         if (eb->other_methods) {
11090                 int j;
11091                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11092                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11093                         MonoReflectionMethodBuilder *mb = 
11094                                 mono_array_get (eb->other_methods,
11095                                                 MonoReflectionMethodBuilder*, j);
11096                         event->other [j] = mb->mhandle;
11097                 }
11098         }
11099 #endif
11100
11101         return mono_event_get_object (mono_object_domain (tb), klass, event);
11102 }
11103
11104 static void
11105 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11106 {
11107         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11108         MonoReflectionEventBuilder *eb;
11109         MonoImage *image = klass->image;
11110         MonoEvent *events;
11111         int i;
11112
11113         mono_error_init (error);
11114
11115         if (!klass->ext)
11116                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11117
11118         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11119         klass->ext->event.first = 0;
11120
11121         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11122         klass->ext->events = events;
11123         for (i = 0; i < klass->ext->event.count; ++i) {
11124                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11125                 events [i].parent = klass;
11126                 events [i].attrs = eb->attrs;
11127                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11128                 if (!mono_error_ok (error))
11129                         return;
11130                 if (eb->add_method)
11131                         events [i].add = eb->add_method->mhandle;
11132                 if (eb->remove_method)
11133                         events [i].remove = eb->remove_method->mhandle;
11134                 if (eb->raise_method)
11135                         events [i].raise = eb->raise_method->mhandle;
11136
11137 #ifndef MONO_SMALL_CONFIG
11138                 if (eb->other_methods) {
11139                         int j;
11140                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11141                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11142                                 MonoReflectionMethodBuilder *mb = 
11143                                         mono_array_get (eb->other_methods,
11144                                                                         MonoReflectionMethodBuilder*, j);
11145                                 events [i].other [j] = mb->mhandle;
11146                         }
11147                 }
11148 #endif
11149                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11150         }
11151 }
11152
11153 static gboolean
11154 remove_instantiations_of_and_ensure_contents (gpointer key,
11155                                                   gpointer value,
11156                                                   gpointer user_data)
11157 {
11158         MonoType *type = (MonoType*)key;
11159         MonoClass *klass = (MonoClass*)user_data;
11160
11161         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11162                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11163                 return TRUE;
11164         } else
11165                 return FALSE;
11166 }
11167
11168 static void
11169 check_array_for_usertypes (MonoArray *arr)
11170 {
11171         int i;
11172
11173         if (!arr)
11174                 return;
11175
11176         for (i = 0; i < mono_array_length (arr); ++i)
11177                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11178 }
11179
11180 MonoReflectionType*
11181 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11182 {
11183         MonoError error;
11184         MonoClass *klass;
11185         MonoDomain* domain;
11186         MonoReflectionType* res;
11187         int i, j;
11188
11189         MONO_ARCH_SAVE_REGS;
11190
11191         domain = mono_object_domain (tb);
11192         klass = mono_class_from_mono_type (tb->type.type);
11193
11194         /*
11195          * Check for user defined Type subclasses.
11196          */
11197         RESOLVE_TYPE (tb->parent);
11198         check_array_for_usertypes (tb->interfaces);
11199         if (tb->fields) {
11200                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11201                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11202                         if (fb) {
11203                                 RESOLVE_TYPE (fb->type);
11204                                 check_array_for_usertypes (fb->modreq);
11205                                 check_array_for_usertypes (fb->modopt);
11206                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11207                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11208                         }
11209                 }
11210         }
11211         if (tb->methods) {
11212                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11213                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11214                         if (mb) {
11215                                 RESOLVE_TYPE (mb->rtype);
11216                                 check_array_for_usertypes (mb->return_modreq);
11217                                 check_array_for_usertypes (mb->return_modopt);
11218                                 check_array_for_usertypes (mb->parameters);
11219                                 if (mb->param_modreq)
11220                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11221                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11222                                 if (mb->param_modopt)
11223                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11224                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11225                         }
11226                 }
11227         }
11228         if (tb->ctors) {
11229                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11230                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11231                         if (mb) {
11232                                 check_array_for_usertypes (mb->parameters);
11233                                 if (mb->param_modreq)
11234                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11235                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11236                                 if (mb->param_modopt)
11237                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11238                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11239                         }
11240                 }
11241         }
11242
11243         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11244
11245         /* 
11246          * we need to lock the domain because the lock will be taken inside
11247          * So, we need to keep the locking order correct.
11248          */
11249         mono_loader_lock ();
11250         mono_domain_lock (domain);
11251         if (klass->wastypebuilder) {
11252                 mono_domain_unlock (domain);
11253                 mono_loader_unlock ();
11254                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11255         }
11256         /*
11257          * Fields to set in klass:
11258          * the various flags: delegate/unicode/contextbound etc.
11259          */
11260         klass->flags = tb->attrs;
11261         klass->has_cctor = 1;
11262         klass->has_finalize = 1;
11263
11264         /* fool mono_class_setup_parent */
11265         klass->supertypes = NULL;
11266         mono_class_setup_parent (klass, klass->parent);
11267         mono_class_setup_mono_type (klass);
11268
11269 #if 0
11270         if (!((MonoDynamicImage*)klass->image)->run) {
11271                 if (klass->generic_container) {
11272                         /* FIXME: The code below can't handle generic classes */
11273                         klass->wastypebuilder = TRUE;
11274                         mono_loader_unlock ();
11275                         mono_domain_unlock (domain);
11276                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11277                 }
11278         }
11279 #endif
11280
11281         /* enums are done right away */
11282         if (!klass->enumtype)
11283                 ensure_runtime_vtable (klass);
11284
11285         if (tb->subtypes) {
11286                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11287                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11288                         mono_class_alloc_ext (klass);
11289                         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)));
11290                 }
11291         }
11292
11293         klass->nested_classes_inited = TRUE;
11294
11295         /* fields and object layout */
11296         if (klass->parent) {
11297                 if (!klass->parent->size_inited)
11298                         mono_class_init (klass->parent);
11299                 klass->instance_size = klass->parent->instance_size;
11300                 klass->sizes.class_size = 0;
11301                 klass->min_align = klass->parent->min_align;
11302                 /* if the type has no fields we won't call the field_setup
11303                  * routine which sets up klass->has_references.
11304                  */
11305                 klass->has_references |= klass->parent->has_references;
11306         } else {
11307                 klass->instance_size = sizeof (MonoObject);
11308                 klass->min_align = 1;
11309         }
11310
11311         /* FIXME: handle packing_size and instance_size */
11312         typebuilder_setup_fields (klass, &error);
11313         if (!mono_error_ok (&error))
11314                 goto failure;
11315         typebuilder_setup_properties (klass, &error);
11316         if (!mono_error_ok (&error))
11317                 goto failure;
11318
11319         typebuilder_setup_events (klass, &error);
11320         if (!mono_error_ok (&error))
11321                 goto failure;
11322
11323         klass->wastypebuilder = TRUE;
11324
11325         /* 
11326          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11327          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11328          * we want to return normal System.MonoType objects, so clear these out from the cache.
11329          *
11330          * Together with this we must ensure the contents of all instances to match the created type.
11331          */
11332         if (domain->type_hash && klass->generic_container)
11333                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11334
11335         mono_domain_unlock (domain);
11336         mono_loader_unlock ();
11337
11338         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11339                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11340                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11341         }
11342
11343         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11344         g_assert (res != (MonoReflectionType*)tb);
11345
11346         return res;
11347
11348 failure:
11349         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11350         klass->wastypebuilder = TRUE;
11351         mono_domain_unlock (domain);
11352         mono_loader_unlock ();
11353         mono_error_raise_exception (&error);
11354         return NULL;
11355 }
11356
11357 void
11358 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11359 {
11360         MonoGenericParamFull *param;
11361         MonoImage *image;
11362         MonoClass *pklass;
11363
11364         MONO_ARCH_SAVE_REGS;
11365
11366         param = g_new0 (MonoGenericParamFull, 1);
11367
11368         if (gparam->mbuilder) {
11369                 if (!gparam->mbuilder->generic_container) {
11370                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11371                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11372                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11373                         gparam->mbuilder->generic_container->is_method = TRUE;
11374                         /* 
11375                          * Cannot set owner.method, since the MonoMethod is not created yet.
11376                          * Set the image field instead, so type_in_image () works.
11377                          */
11378                         gparam->mbuilder->generic_container->image = klass->image;
11379                 }
11380                 param->param.owner = gparam->mbuilder->generic_container;
11381         } else if (gparam->tbuilder) {
11382                 if (!gparam->tbuilder->generic_container) {
11383                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11384                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11385                         gparam->tbuilder->generic_container->owner.klass = klass;
11386                 }
11387                 param->param.owner = gparam->tbuilder->generic_container;
11388         }
11389
11390         param->info.name = mono_string_to_utf8 (gparam->name);
11391         param->param.num = gparam->index;
11392
11393         image = &gparam->tbuilder->module->dynamic_image->image;
11394         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11395
11396         gparam->type.type = &pklass->byval_arg;
11397
11398         mono_class_set_ref_info (pklass, gparam);
11399         mono_image_lock (image);
11400         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11401         mono_image_unlock (image);
11402 }
11403
11404 MonoArray *
11405 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11406 {
11407         MonoReflectionModuleBuilder *module = sig->module;
11408         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11409         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11410         guint32 buflen, i;
11411         MonoArray *result;
11412         SigBuffer buf;
11413
11414         check_array_for_usertypes (sig->arguments);
11415
11416         sigbuffer_init (&buf, 32);
11417
11418         sigbuffer_add_value (&buf, 0x07);
11419         sigbuffer_add_value (&buf, na);
11420         if (assembly != NULL){
11421                 for (i = 0; i < na; ++i) {
11422                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11423                         encode_reflection_type (assembly, type, &buf);
11424                 }
11425         }
11426
11427         buflen = buf.p - buf.buf;
11428         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11429         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11430         sigbuffer_free (&buf);
11431
11432         return result;
11433 }
11434
11435 MonoArray *
11436 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11437 {
11438         MonoDynamicImage *assembly = sig->module->dynamic_image;
11439         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11440         guint32 buflen, i;
11441         MonoArray *result;
11442         SigBuffer buf;
11443
11444         check_array_for_usertypes (sig->arguments);
11445
11446         sigbuffer_init (&buf, 32);
11447
11448         sigbuffer_add_value (&buf, 0x06);
11449         for (i = 0; i < na; ++i) {
11450                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11451                 encode_reflection_type (assembly, type, &buf);
11452         }
11453
11454         buflen = buf.p - buf.buf;
11455         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11456         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11457         sigbuffer_free (&buf);
11458
11459         return result;
11460 }
11461
11462 void 
11463 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11464 {
11465         ReflectionMethodBuilder rmb;
11466         MonoMethodSignature *sig;
11467         MonoClass *klass;
11468         GSList *l;
11469         int i;
11470
11471         sig = dynamic_method_to_signature (mb);
11472
11473         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11474
11475         /*
11476          * Resolve references.
11477          */
11478         /* 
11479          * Every second entry in the refs array is reserved for storing handle_class,
11480          * which is needed by the ldtoken implementation in the JIT.
11481          */
11482         rmb.nrefs = mb->nrefs;
11483         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11484         for (i = 0; i < mb->nrefs; i += 2) {
11485                 MonoClass *handle_class;
11486                 gpointer ref;
11487                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11488
11489                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11490                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11491                         /*
11492                          * The referenced DynamicMethod should already be created by the managed
11493                          * code, except in the case of circular references. In that case, we store
11494                          * method in the refs array, and fix it up later when the referenced 
11495                          * DynamicMethod is created.
11496                          */
11497                         if (method->mhandle) {
11498                                 ref = method->mhandle;
11499                         } else {
11500                                 /* FIXME: GC object stored in unmanaged memory */
11501                                 ref = method;
11502
11503                                 /* FIXME: GC object stored in unmanaged memory */
11504                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11505                         }
11506                         handle_class = mono_defaults.methodhandle_class;
11507                 } else {
11508                         MonoException *ex = NULL;
11509                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11510                         if (!ref)
11511                                 ex = mono_get_exception_type_load (NULL, NULL);
11512                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11513                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11514
11515                         if (ex) {
11516                                 g_free (rmb.refs);
11517                                 mono_raise_exception (ex);
11518                                 return;
11519                         }
11520                 }
11521
11522                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11523                 rmb.refs [i + 1] = handle_class;
11524         }               
11525
11526         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11527
11528         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11529
11530         /* Fix up refs entries pointing at us */
11531         for (l = mb->referenced_by; l; l = l->next) {
11532                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11533                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11534                 gpointer *data;
11535                 
11536                 g_assert (method->mhandle);
11537
11538                 data = (gpointer*)wrapper->method_data;
11539                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11540                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11541                                 data [i + 1] = mb->mhandle;
11542                 }
11543         }
11544         g_slist_free (mb->referenced_by);
11545
11546         g_free (rmb.refs);
11547
11548         /* ilgen is no longer needed */
11549         mb->ilgen = NULL;
11550 }
11551
11552 #endif /* DISABLE_REFLECTION_EMIT */
11553
11554 void
11555 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11556 {
11557         g_assert (mb);
11558
11559         if (mb->mhandle)
11560                 mono_runtime_free_method (
11561                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11562 }
11563
11564 /**
11565  * 
11566  * mono_reflection_is_valid_dynamic_token:
11567  * 
11568  * Returns TRUE if token is valid.
11569  * 
11570  */
11571 gboolean
11572 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11573 {
11574         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11575 }
11576
11577 #ifndef DISABLE_REFLECTION_EMIT
11578
11579 /**
11580  * mono_reflection_lookup_dynamic_token:
11581  *
11582  * Finish the Builder object pointed to by TOKEN and return the corresponding
11583  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11584  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11585  * mapping table.
11586  *
11587  * LOCKING: Take the loader lock
11588  */
11589 gpointer
11590 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11591 {
11592         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11593         MonoObject *obj;
11594         MonoClass *klass;
11595
11596         mono_loader_lock ();
11597         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11598         mono_loader_unlock ();
11599         if (!obj) {
11600                 if (valid_token)
11601                         g_error ("Could not find required dynamic token 0x%08x", token);
11602                 else
11603                         return NULL;
11604         }
11605
11606         if (!handle_class)
11607                 handle_class = &klass;
11608         return resolve_object (image, obj, handle_class, context);
11609 }
11610
11611 MonoMethodSignature *
11612 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11613 {
11614         MonoMethodSignature *sig;
11615         g_assert (image->dynamic);
11616
11617         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11618         if (sig)
11619                 return sig;
11620
11621         return mono_method_signature (method);
11622 }
11623
11624 /*
11625  * ensure_complete_type:
11626  *
11627  *   Ensure that KLASS is completed if it is a dynamic type, or references
11628  * dynamic types.
11629  */
11630 static void
11631 ensure_complete_type (MonoClass *klass)
11632 {
11633         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11634                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11635
11636                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11637
11638                 // Asserting here could break a lot of code
11639                 //g_assert (klass->wastypebuilder);
11640         }
11641
11642         if (klass->generic_class) {
11643                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11644                 int i;
11645
11646                 for (i = 0; i < inst->type_argc; ++i) {
11647                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11648                 }
11649         }
11650 }
11651
11652 static gpointer
11653 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11654 {
11655         gpointer result = NULL;
11656
11657         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11658                 result = mono_string_intern ((MonoString*)obj);
11659                 *handle_class = mono_defaults.string_class;
11660                 g_assert (result);
11661         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11662                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11663                 MonoClass *mc = mono_class_from_mono_type (type);
11664                 if (!mono_class_init (mc))
11665                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11666
11667                 if (context) {
11668                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11669                         result = mono_class_from_mono_type (inflated);
11670                         mono_metadata_free_type (inflated);
11671                 } else {
11672                         result = mono_class_from_mono_type (type);
11673                 }
11674                 *handle_class = mono_defaults.typehandle_class;
11675                 g_assert (result);
11676         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11677                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11678                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11679                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11680                 result = ((MonoReflectionMethod*)obj)->method;
11681                 if (context)
11682                         result = mono_class_inflate_generic_method (result, context);
11683                 *handle_class = mono_defaults.methodhandle_class;
11684                 g_assert (result);
11685         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11686                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11687                 result = mb->mhandle;
11688                 if (!result) {
11689                         /* Type is not yet created */
11690                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11691
11692                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11693
11694                         /*
11695                          * Hopefully this has been filled in by calling CreateType() on the
11696                          * TypeBuilder.
11697                          */
11698                         /*
11699                          * TODO: This won't work if the application finishes another 
11700                          * TypeBuilder instance instead of this one.
11701                          */
11702                         result = mb->mhandle;
11703                 }
11704                 if (context)
11705                         result = mono_class_inflate_generic_method (result, context);
11706                 *handle_class = mono_defaults.methodhandle_class;
11707         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11708                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11709
11710                 result = cb->mhandle;
11711                 if (!result) {
11712                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11713
11714                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11715                         result = cb->mhandle;
11716                 }
11717                 if (context)
11718                         result = mono_class_inflate_generic_method (result, context);
11719                 *handle_class = mono_defaults.methodhandle_class;
11720         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11721                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11722
11723                 ensure_complete_type (field->parent);
11724                 if (context) {
11725                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11726                         MonoClass *class = mono_class_from_mono_type (inflated);
11727                         MonoClassField *inflated_field;
11728                         gpointer iter = NULL;
11729                         mono_metadata_free_type (inflated);
11730                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11731                                 if (!strcmp (field->name, inflated_field->name))
11732                                         break;
11733                         }
11734                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11735                         result = inflated_field;
11736                 } else {
11737                         result = field;
11738                 }
11739                 *handle_class = mono_defaults.fieldhandle_class;
11740                 g_assert (result);
11741         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11742                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11743                 result = fb->handle;
11744
11745                 if (!result) {
11746                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11747
11748                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11749                         result = fb->handle;
11750                 }
11751
11752                 if (fb->handle && fb->handle->parent->generic_container) {
11753                         MonoClass *klass = fb->handle->parent;
11754                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11755                         MonoClass *inflated = mono_class_from_mono_type (type);
11756
11757                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11758                         g_assert (result);
11759                         mono_metadata_free_type (type);
11760                 }
11761                 *handle_class = mono_defaults.fieldhandle_class;
11762         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11763                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11764                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11765                 MonoClass *klass;
11766
11767                 klass = type->data.klass;
11768                 if (klass->wastypebuilder) {
11769                         /* Already created */
11770                         result = klass;
11771                 }
11772                 else {
11773                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11774                         result = type->data.klass;
11775                         g_assert (result);
11776                 }
11777                 *handle_class = mono_defaults.typehandle_class;
11778         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11779                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11780                 MonoMethodSignature *sig;
11781                 int nargs, i;
11782
11783                 if (helper->arguments)
11784                         nargs = mono_array_length (helper->arguments);
11785                 else
11786                         nargs = 0;
11787
11788                 sig = mono_metadata_signature_alloc (image, nargs);
11789                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11790                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11791
11792                 if (helper->unmanaged_call_conv) { /* unmanaged */
11793                         sig->call_convention = helper->unmanaged_call_conv - 1;
11794                         sig->pinvoke = TRUE;
11795                 } else if (helper->call_conv & 0x02) {
11796                         sig->call_convention = MONO_CALL_VARARG;
11797                 } else {
11798                         sig->call_convention = MONO_CALL_DEFAULT;
11799                 }
11800
11801                 sig->param_count = nargs;
11802                 /* TODO: Copy type ? */
11803                 sig->ret = helper->return_type->type;
11804                 for (i = 0; i < nargs; ++i)
11805                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11806
11807                 result = sig;
11808                 *handle_class = NULL;
11809         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11810                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11811                 /* Already created by the managed code */
11812                 g_assert (method->mhandle);
11813                 result = method->mhandle;
11814                 *handle_class = mono_defaults.methodhandle_class;
11815         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11816                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11817                 type = mono_class_inflate_generic_type (type, context);
11818                 result = mono_class_from_mono_type (type);
11819                 *handle_class = mono_defaults.typehandle_class;
11820                 g_assert (result);
11821                 mono_metadata_free_type (type);
11822         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11823                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11824                 type = mono_class_inflate_generic_type (type, context);
11825                 result = mono_class_from_mono_type (type);
11826                 *handle_class = mono_defaults.typehandle_class;
11827                 g_assert (result);
11828                 mono_metadata_free_type (type);
11829         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11830                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11831                 MonoClass *inflated;
11832                 MonoType *type;
11833                 MonoClassField *field;
11834
11835                 if (is_sre_field_builder (mono_object_class (f->fb)))
11836                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11837                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11838                         field = ((MonoReflectionField*)f->fb)->field;
11839                 else
11840                         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)));
11841
11842                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11843                 inflated = mono_class_from_mono_type (type);
11844
11845                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11846                 ensure_complete_type (field->parent);
11847                 g_assert (result);
11848                 mono_metadata_free_type (type);
11849                 *handle_class = mono_defaults.fieldhandle_class;
11850         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11851                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11852                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11853                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11854                 MonoMethod *method;
11855
11856                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11857                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11858                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11859                         method = ((MonoReflectionMethod *)c->cb)->method;
11860                 else
11861                         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)));
11862
11863                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11864                 *handle_class = mono_defaults.methodhandle_class;
11865                 mono_metadata_free_type (type);
11866         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11867                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11868                 if (m->method_args) {
11869                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11870                         if (context)
11871                                 result = mono_class_inflate_generic_method (result, context);
11872                 } else {
11873                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11874                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11875                         MonoMethod *method;
11876
11877                         if (is_sre_method_builder (mono_object_class (m->mb)))
11878                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11879                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11880                                 method = ((MonoReflectionMethod *)m->mb)->method;
11881                         else
11882                                 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)));
11883
11884                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11885                         mono_metadata_free_type (type);
11886                 }
11887                 *handle_class = mono_defaults.methodhandle_class;
11888         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11889                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11890                 MonoType *mtype;
11891                 MonoClass *klass;
11892                 MonoMethod *method;
11893                 gpointer iter;
11894                 char *name;
11895
11896                 mtype = mono_reflection_type_get_handle (m->parent);
11897                 klass = mono_class_from_mono_type (mtype);
11898
11899                 /* Find the method */
11900
11901                 name = mono_string_to_utf8 (m->name);
11902                 iter = NULL;
11903                 while ((method = mono_class_get_methods (klass, &iter))) {
11904                         if (!strcmp (method->name, name))
11905                                 break;
11906                 }
11907                 g_free (name);
11908
11909                 // FIXME:
11910                 g_assert (method);
11911                 // FIXME: Check parameters/return value etc. match
11912
11913                 result = method;
11914                 *handle_class = mono_defaults.methodhandle_class;
11915         } else if (is_sre_array (mono_object_get_class(obj)) ||
11916                                 is_sre_byref (mono_object_get_class(obj)) ||
11917                                 is_sre_pointer (mono_object_get_class(obj))) {
11918                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11919                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11920                 result = mono_class_from_mono_type (type);
11921                 *handle_class = mono_defaults.typehandle_class;
11922         } else {
11923                 g_print ("%s\n", obj->vtable->klass->name);
11924                 g_assert_not_reached ();
11925         }
11926         return result;
11927 }
11928
11929 #else /* DISABLE_REFLECTION_EMIT */
11930
11931 MonoArray*
11932 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11933 {
11934         g_assert_not_reached ();
11935         return NULL;
11936 }
11937
11938 void
11939 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11940 {
11941         g_assert_not_reached ();
11942 }
11943
11944 void
11945 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11946 {
11947         g_assert_not_reached ();
11948 }
11949
11950 void
11951 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11952 {
11953         g_assert_not_reached ();
11954 }
11955
11956 void
11957 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11958 {
11959         g_assert_not_reached ();
11960 }
11961
11962 void
11963 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11964 {
11965         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11966 }
11967
11968 void
11969 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11970 {
11971         g_assert_not_reached ();
11972 }
11973
11974 void
11975 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11976 {
11977         g_assert_not_reached ();
11978 }
11979
11980 MonoReflectionModule *
11981 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11982 {
11983         g_assert_not_reached ();
11984         return NULL;
11985 }
11986
11987 guint32
11988 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11989 {
11990         g_assert_not_reached ();
11991         return 0;
11992 }
11993
11994 guint32
11995 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11996 {
11997         g_assert_not_reached ();
11998         return 0;
11999 }
12000
12001 guint32
12002 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12003                                                  gboolean create_methodspec, gboolean register_token)
12004 {
12005         g_assert_not_reached ();
12006         return 0;
12007 }
12008
12009 void
12010 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12011 {
12012 }
12013
12014 void
12015 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
12016                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12017                                           MonoArray *events)
12018 {
12019         g_assert_not_reached ();
12020 }
12021
12022 void
12023 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12024 {
12025         *overrides = NULL;
12026         *num_overrides = 0;
12027 }
12028
12029 MonoReflectionEvent *
12030 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12031 {
12032         g_assert_not_reached ();
12033         return NULL;
12034 }
12035
12036 MonoReflectionType*
12037 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12038 {
12039         g_assert_not_reached ();
12040         return NULL;
12041 }
12042
12043 void
12044 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12045 {
12046         g_assert_not_reached ();
12047 }
12048
12049 MonoArray *
12050 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12051 {
12052         g_assert_not_reached ();
12053         return NULL;
12054 }
12055
12056 MonoArray *
12057 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12058 {
12059         g_assert_not_reached ();
12060         return NULL;
12061 }
12062
12063 void 
12064 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12065 {
12066 }
12067
12068 gpointer
12069 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12070 {
12071         return NULL;
12072 }
12073
12074 MonoType*
12075 mono_reflection_type_get_handle (MonoReflectionType* ref)
12076 {
12077         if (!ref)
12078                 return NULL;
12079         return ref->type;
12080 }
12081
12082 #endif /* DISABLE_REFLECTION_EMIT */
12083
12084 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12085 const static guint32 declsec_flags_map[] = {
12086         0x00000000,                                     /* empty */
12087         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12088         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12089         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12090         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12091         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12092         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12093         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12094         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12095         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12096         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12097         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12098         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12099         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12100         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12101         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12102         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12103         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12104         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12105 };
12106
12107 /*
12108  * Returns flags that includes all available security action associated to the handle.
12109  * @token: metadata token (either for a class or a method)
12110  * @image: image where resides the metadata.
12111  */
12112 static guint32
12113 mono_declsec_get_flags (MonoImage *image, guint32 token)
12114 {
12115         int index = mono_metadata_declsec_from_index (image, token);
12116         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12117         guint32 result = 0;
12118         guint32 action;
12119         int i;
12120
12121         /* HasSecurity can be present for other, not specially encoded, attributes,
12122            e.g. SuppressUnmanagedCodeSecurityAttribute */
12123         if (index < 0)
12124                 return 0;
12125
12126         for (i = index; i < t->rows; i++) {
12127                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12128
12129                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12130                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12131                         break;
12132
12133                 action = cols [MONO_DECL_SECURITY_ACTION];
12134                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12135                         result |= declsec_flags_map [action];
12136                 } else {
12137                         g_assert_not_reached ();
12138                 }
12139         }
12140         return result;
12141 }
12142
12143 /*
12144  * Get the security actions (in the form of flags) associated with the specified method.
12145  *
12146  * @method: The method for which we want the declarative security flags.
12147  * Return the declarative security flags for the method (only).
12148  *
12149  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12150  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12151  */
12152 guint32
12153 mono_declsec_flags_from_method (MonoMethod *method)
12154 {
12155         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12156                 /* FIXME: No cache (for the moment) */
12157                 guint32 idx = mono_method_get_index (method);
12158                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12159                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12160                 return mono_declsec_get_flags (method->klass->image, idx);
12161         }
12162         return 0;
12163 }
12164
12165 /*
12166  * Get the security actions (in the form of flags) associated with the specified class.
12167  *
12168  * @klass: The class for which we want the declarative security flags.
12169  * Return the declarative security flags for the class.
12170  *
12171  * Note: We cache the flags inside the MonoClass structure as this will get 
12172  *       called very often (at least for each method).
12173  */
12174 guint32
12175 mono_declsec_flags_from_class (MonoClass *klass)
12176 {
12177         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12178                 if (!klass->ext || !klass->ext->declsec_flags) {
12179                         guint32 idx;
12180
12181                         idx = mono_metadata_token_index (klass->type_token);
12182                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12183                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12184                         mono_loader_lock ();
12185                         mono_class_alloc_ext (klass);
12186                         mono_loader_unlock ();
12187                         /* we cache the flags on classes */
12188                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12189                 }
12190                 return klass->ext->declsec_flags;
12191         }
12192         return 0;
12193 }
12194
12195 /*
12196  * Get the security actions (in the form of flags) associated with the specified assembly.
12197  *
12198  * @assembly: The assembly for which we want the declarative security flags.
12199  * Return the declarative security flags for the assembly.
12200  */
12201 guint32
12202 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12203 {
12204         guint32 idx = 1; /* there is only one assembly */
12205         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12206         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12207         return mono_declsec_get_flags (assembly->image, idx);
12208 }
12209
12210
12211 /*
12212  * Fill actions for the specific index (which may either be an encoded class token or
12213  * an encoded method token) from the metadata image.
12214  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12215  */
12216 static MonoBoolean
12217 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12218         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12219 {
12220         MonoBoolean result = FALSE;
12221         MonoTableInfo *t;
12222         guint32 cols [MONO_DECL_SECURITY_SIZE];
12223         int index = mono_metadata_declsec_from_index (image, token);
12224         int i;
12225
12226         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12227         for (i = index; i < t->rows; i++) {
12228                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12229
12230                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12231                         return result;
12232
12233                 /* if present only replace (class) permissions with method permissions */
12234                 /* if empty accept either class or method permissions */
12235                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12236                         if (!actions->demand.blob) {
12237                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12238                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12239                                 actions->demand.blob = (char*) (blob + 2);
12240                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12241                                 result = TRUE;
12242                         }
12243                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12244                         if (!actions->noncasdemand.blob) {
12245                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12246                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12247                                 actions->noncasdemand.blob = (char*) (blob + 2);
12248                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12249                                 result = TRUE;
12250                         }
12251                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12252                         if (!actions->demandchoice.blob) {
12253                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12254                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12255                                 actions->demandchoice.blob = (char*) (blob + 2);
12256                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12257                                 result = TRUE;
12258                         }
12259                 }
12260         }
12261
12262         return result;
12263 }
12264
12265 static MonoBoolean
12266 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12267         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12268 {
12269         guint32 idx = mono_metadata_token_index (klass->type_token);
12270         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12271         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12272         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12273 }
12274
12275 static MonoBoolean
12276 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12277         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12278 {
12279         guint32 idx = mono_method_get_index (method);
12280         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12281         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12282         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12283 }
12284
12285 /*
12286  * Collect all actions (that requires to generate code in mini) assigned for
12287  * the specified method.
12288  * Note: Don't use the content of actions if the function return FALSE.
12289  */
12290 MonoBoolean
12291 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12292 {
12293         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12294                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12295         MonoBoolean result = FALSE;
12296         guint32 flags;
12297
12298         /* quick exit if no declarative security is present in the metadata */
12299         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12300                 return FALSE;
12301
12302         /* we want the original as the wrapper is "free" of the security informations */
12303         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12304                 method = mono_marshal_method_from_wrapper (method);
12305                 if (!method)
12306                         return FALSE;
12307         }
12308
12309         /* First we look for method-level attributes */
12310         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12311                 mono_class_init (method->klass);
12312                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12313
12314                 result = mono_declsec_get_method_demands_params (method, demands, 
12315                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12316         }
12317
12318         /* Here we use (or create) the class declarative cache to look for demands */
12319         flags = mono_declsec_flags_from_class (method->klass);
12320         if (flags & mask) {
12321                 if (!result) {
12322                         mono_class_init (method->klass);
12323                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12324                 }
12325                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12326                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12327         }
12328
12329         /* The boolean return value is used as a shortcut in case nothing needs to
12330            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12331         return result;
12332 }
12333
12334
12335 /*
12336  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12337  *
12338  * Note: Don't use the content of actions if the function return FALSE.
12339  */
12340 MonoBoolean
12341 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12342 {
12343         MonoBoolean result = FALSE;
12344         guint32 flags;
12345
12346         /* quick exit if no declarative security is present in the metadata */
12347         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12348                 return FALSE;
12349
12350         /* we want the original as the wrapper is "free" of the security informations */
12351         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12352                 method = mono_marshal_method_from_wrapper (method);
12353                 if (!method)
12354                         return FALSE;
12355         }
12356
12357         /* results are independant - zeroize both */
12358         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12359         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12360
12361         /* First we look for method-level attributes */
12362         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12363                 mono_class_init (method->klass);
12364
12365                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12366                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12367         }
12368
12369         /* Here we use (or create) the class declarative cache to look for demands */
12370         flags = mono_declsec_flags_from_class (method->klass);
12371         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12372                 mono_class_init (method->klass);
12373
12374                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12375                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12376         }
12377
12378         return result;
12379 }
12380
12381 /*
12382  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12383  *
12384  * @klass       The inherited class - this is the class that provides the security check (attributes)
12385  * @demans      
12386  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12387  * 
12388  * Note: Don't use the content of actions if the function return FALSE.
12389  */
12390 MonoBoolean
12391 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12392 {
12393         MonoBoolean result = FALSE;
12394         guint32 flags;
12395
12396         /* quick exit if no declarative security is present in the metadata */
12397         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12398                 return FALSE;
12399
12400         /* Here we use (or create) the class declarative cache to look for demands */
12401         flags = mono_declsec_flags_from_class (klass);
12402         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12403                 mono_class_init (klass);
12404                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12405
12406                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12407                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12408         }
12409
12410         return result;
12411 }
12412
12413 /*
12414  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12415  *
12416  * Note: Don't use the content of actions if the function return FALSE.
12417  */
12418 MonoBoolean
12419 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12420 {
12421         /* quick exit if no declarative security is present in the metadata */
12422         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12423                 return FALSE;
12424
12425         /* we want the original as the wrapper is "free" of the security informations */
12426         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12427                 method = mono_marshal_method_from_wrapper (method);
12428                 if (!method)
12429                         return FALSE;
12430         }
12431
12432         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12433                 mono_class_init (method->klass);
12434                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12435
12436                 return mono_declsec_get_method_demands_params (method, demands, 
12437                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12438         }
12439         return FALSE;
12440 }
12441
12442
12443 static MonoBoolean
12444 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12445 {
12446         guint32 cols [MONO_DECL_SECURITY_SIZE];
12447         MonoTableInfo *t;
12448         int i;
12449
12450         int index = mono_metadata_declsec_from_index (image, token);
12451         if (index == -1)
12452                 return FALSE;
12453
12454         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12455         for (i = index; i < t->rows; i++) {
12456                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12457
12458                 /* shortcut - index are ordered */
12459                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12460                         return FALSE;
12461
12462                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12463                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12464                         entry->blob = (char*) (metadata + 2);
12465                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12466                         return TRUE;
12467                 }
12468         }
12469
12470         return FALSE;
12471 }
12472
12473 MonoBoolean
12474 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12475 {
12476         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12477                 guint32 idx = mono_method_get_index (method);
12478                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12479                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12480                 return get_declsec_action (method->klass->image, idx, action, entry);
12481         }
12482         return FALSE;
12483 }
12484
12485 MonoBoolean
12486 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12487 {
12488         /* use cache */
12489         guint32 flags = mono_declsec_flags_from_class (klass);
12490         if (declsec_flags_map [action] & flags) {
12491                 guint32 idx = mono_metadata_token_index (klass->type_token);
12492                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12493                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12494                 return get_declsec_action (klass->image, idx, action, entry);
12495         }
12496         return FALSE;
12497 }
12498
12499 MonoBoolean
12500 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12501 {
12502         guint32 idx = 1; /* there is only one assembly */
12503         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12504         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12505
12506         return get_declsec_action (assembly->image, idx, action, entry);
12507 }
12508
12509 gboolean
12510 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12511 {
12512         MonoObject *res, *exc;
12513         void *params [1];
12514         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12515         static MonoMethod *method = NULL;
12516
12517         if (!System_Reflection_Emit_TypeBuilder) {
12518                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12519                 g_assert (System_Reflection_Emit_TypeBuilder);
12520         }
12521         if (method == NULL) {
12522                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12523                 g_assert (method);
12524         }
12525
12526         /* 
12527          * The result of mono_type_get_object () might be a System.MonoType but we
12528          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12529          */
12530         g_assert (mono_class_get_ref_info (klass));
12531         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12532
12533         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12534
12535         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12536         if (exc)
12537                 return FALSE;
12538         else
12539                 return *(MonoBoolean*)mono_object_unbox (res);
12540 }