mono_custom_attrs_from_param: return null if the method defining the parameter can...
[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) ^ g_str_hash (t1->data.klass->name);
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         }
6373         return hash;
6374 }
6375
6376 static gboolean
6377 verify_safe_for_managed_space (MonoType *type)
6378 {
6379         switch (type->type) {
6380 #ifdef DEBUG_HARDER
6381         case MONO_TYPE_ARRAY:
6382                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6383         case MONO_TYPE_PTR:
6384                 return verify_safe_for_managed_space (type->data.type);
6385         case MONO_TYPE_SZARRAY:
6386                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6387         case MONO_TYPE_GENERICINST: {
6388                 MonoGenericInst *inst = type->data.generic_class->inst;
6389                 int i;
6390                 if (!inst->is_open)
6391                         break;
6392                 for (i = 0; i < inst->type_argc; ++i)
6393                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6394                                 return FALSE;
6395                 break;
6396         }
6397 #endif
6398         case MONO_TYPE_VAR:
6399         case MONO_TYPE_MVAR:
6400                 return TRUE;
6401         }
6402         return TRUE;
6403 }
6404
6405 static MonoType*
6406 mono_type_normalize (MonoType *type)
6407 {
6408         int i;
6409         MonoGenericClass *gclass;
6410         MonoGenericInst *ginst;
6411         MonoClass *gtd;
6412         MonoGenericContainer *gcontainer;
6413         MonoType **argv = NULL;
6414         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6415
6416         if (type->type != MONO_TYPE_GENERICINST)
6417                 return type;
6418
6419         gclass = type->data.generic_class;
6420         ginst = gclass->context.class_inst;
6421         if (!ginst->is_open)
6422                 return type;
6423
6424         gtd = gclass->container_class;
6425         gcontainer = gtd->generic_container;
6426         argv = g_newa (MonoType*, ginst->type_argc);
6427
6428         for (i = 0; i < ginst->type_argc; ++i) {
6429                 MonoType *t = ginst->type_argv [i], *norm;
6430                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6431                         is_denorm_gtd = FALSE;
6432                 norm = mono_type_normalize (t);
6433                 argv [i] = norm;
6434                 if (norm != t)
6435                         requires_rebind = TRUE;
6436         }
6437
6438         if (is_denorm_gtd)
6439                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6440
6441         if (requires_rebind) {
6442                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6443                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6444         }
6445
6446         return type;
6447 }
6448 /*
6449  * mono_type_get_object:
6450  * @domain: an app domain
6451  * @type: a type
6452  *
6453  * Return an System.MonoType object representing the type @type.
6454  */
6455 MonoReflectionType*
6456 mono_type_get_object (MonoDomain *domain, MonoType *type)
6457 {
6458         MonoType *norm_type;
6459         MonoReflectionType *res;
6460         MonoClass *klass = mono_class_from_mono_type (type);
6461
6462         /*we must avoid using @type as it might have come
6463          * from a mono_metadata_type_dup and the caller
6464          * expects that is can be freed.
6465          * Using the right type from 
6466          */
6467         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6468
6469         /* void is very common */
6470         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6471                 return (MonoReflectionType*)domain->typeof_void;
6472
6473         /*
6474          * If the vtable of the given class was already created, we can use
6475          * the MonoType from there and avoid all locking and hash table lookups.
6476          * 
6477          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6478          * that the resulting object is different.   
6479          */
6480         if (type == &klass->byval_arg && !klass->image->dynamic) {
6481                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6482                 if (vtable && vtable->type)
6483                         return vtable->type;
6484         }
6485
6486         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6487         mono_domain_lock (domain);
6488         if (!domain->type_hash)
6489                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
6490                                 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6491         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6492                 mono_domain_unlock (domain);
6493                 mono_loader_unlock ();
6494                 return res;
6495         }
6496
6497         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6498          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6499          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6500          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6501          * artifact of how generics are encoded and should be transparent to managed code so we
6502          * need to weed out this diference when retrieving managed System.Type objects.
6503          */
6504         norm_type = mono_type_normalize (type);
6505         if (norm_type != type) {
6506                 res = mono_type_get_object (domain, norm_type);
6507                 mono_g_hash_table_insert (domain->type_hash, type, res);
6508                 mono_domain_unlock (domain);
6509                 mono_loader_unlock ();
6510                 return res;
6511         }
6512
6513         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6514         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6515                 g_assert (0);
6516
6517         if (!verify_safe_for_managed_space (type)) {
6518                 mono_domain_unlock (domain);
6519                 mono_loader_unlock ();
6520                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6521         }
6522
6523         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6524                 gboolean is_type_done = TRUE;
6525                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6526                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6527                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6528                 */
6529                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6530                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6531
6532                         if (gparam->owner && gparam->owner->is_method) {
6533                                 MonoMethod *method = gparam->owner->owner.method;
6534                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6535                                         is_type_done = FALSE;
6536                         } else if (gparam->owner && !gparam->owner->is_method) {
6537                                 MonoClass *klass = gparam->owner->owner.klass;
6538                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6539                                         is_type_done = FALSE;
6540                         }
6541                 } 
6542
6543                 /* g_assert_not_reached (); */
6544                 /* should this be considered an error condition? */
6545                 if (is_type_done && !type->byref) {
6546                         mono_domain_unlock (domain);
6547                         mono_loader_unlock ();
6548                         return mono_class_get_ref_info (klass);
6549                 }
6550         }
6551 #ifdef HAVE_SGEN_GC
6552         res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6553 #else
6554         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6555 #endif
6556         res->type = type;
6557         mono_g_hash_table_insert (domain->type_hash, type, res);
6558
6559         if (type->type == MONO_TYPE_VOID)
6560                 domain->typeof_void = (MonoObject*)res;
6561
6562         mono_domain_unlock (domain);
6563         mono_loader_unlock ();
6564         return res;
6565 }
6566
6567 /*
6568  * mono_method_get_object:
6569  * @domain: an app domain
6570  * @method: a method
6571  * @refclass: the reflected type (can be NULL)
6572  *
6573  * Return an System.Reflection.MonoMethod object representing the method @method.
6574  */
6575 MonoReflectionMethod*
6576 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6577 {
6578         /*
6579          * We use the same C representation for methods and constructors, but the type 
6580          * name in C# is different.
6581          */
6582         static MonoClass *System_Reflection_MonoMethod = NULL;
6583         static MonoClass *System_Reflection_MonoCMethod = NULL;
6584         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6585         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6586         MonoClass *klass;
6587         MonoReflectionMethod *ret;
6588
6589         if (method->is_inflated) {
6590                 MonoReflectionGenericMethod *gret;
6591
6592                 refclass = method->klass;
6593                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6594                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6595                         if (!System_Reflection_MonoGenericCMethod)
6596                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6597                         klass = System_Reflection_MonoGenericCMethod;
6598                 } else {
6599                         if (!System_Reflection_MonoGenericMethod)
6600                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6601                         klass = System_Reflection_MonoGenericMethod;
6602                 }
6603                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6604                 gret->method.method = method;
6605                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6606                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6607                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6608         }
6609
6610         if (!refclass)
6611                 refclass = method->klass;
6612
6613         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6614         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6615                 if (!System_Reflection_MonoCMethod)
6616                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6617                 klass = System_Reflection_MonoCMethod;
6618         }
6619         else {
6620                 if (!System_Reflection_MonoMethod)
6621                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6622                 klass = System_Reflection_MonoMethod;
6623         }
6624         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6625         ret->method = method;
6626         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6627         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6628 }
6629
6630 /*
6631  * mono_method_clear_object:
6632  *
6633  *   Clear the cached reflection objects for the dynamic method METHOD.
6634  */
6635 void
6636 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6637 {
6638         MonoClass *klass;
6639         g_assert (method->dynamic);
6640
6641         klass = method->klass;
6642         while (klass) {
6643                 clear_cached_object (domain, method, klass);
6644                 klass = klass->parent;
6645         }
6646         /* Added by mono_param_get_objects () */
6647         clear_cached_object (domain, &(method->signature), NULL);
6648         klass = method->klass;
6649         while (klass) {
6650                 clear_cached_object (domain, &(method->signature), klass);
6651                 klass = klass->parent;
6652         }
6653 }
6654
6655 /*
6656  * mono_field_get_object:
6657  * @domain: an app domain
6658  * @klass: a type
6659  * @field: a field
6660  *
6661  * Return an System.Reflection.MonoField object representing the field @field
6662  * in class @klass.
6663  */
6664 MonoReflectionField*
6665 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6666 {
6667         MonoReflectionField *res;
6668         static MonoClass *monofield_klass;
6669
6670         CHECK_OBJECT (MonoReflectionField *, field, klass);
6671         if (!monofield_klass)
6672                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6673         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6674         res->klass = klass;
6675         res->field = field;
6676         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6677         if (is_field_on_inst (field))
6678                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6679         else
6680                 res->attrs = field->type->attrs;
6681         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6682         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6683 }
6684
6685 /*
6686  * mono_property_get_object:
6687  * @domain: an app domain
6688  * @klass: a type
6689  * @property: a property
6690  *
6691  * Return an System.Reflection.MonoProperty object representing the property @property
6692  * in class @klass.
6693  */
6694 MonoReflectionProperty*
6695 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6696 {
6697         MonoReflectionProperty *res;
6698         static MonoClass *monoproperty_klass;
6699
6700         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6701         if (!monoproperty_klass)
6702                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6703         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6704         res->klass = klass;
6705         res->property = property;
6706         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6707 }
6708
6709 /*
6710  * mono_event_get_object:
6711  * @domain: an app domain
6712  * @klass: a type
6713  * @event: a event
6714  *
6715  * Return an System.Reflection.MonoEvent object representing the event @event
6716  * in class @klass.
6717  */
6718 MonoReflectionEvent*
6719 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6720 {
6721         MonoReflectionEvent *res;
6722         MonoReflectionMonoEvent *mono_event;
6723         static MonoClass *monoevent_klass;
6724
6725         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6726         if (!monoevent_klass)
6727                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6728         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6729         mono_event->klass = klass;
6730         mono_event->event = event;
6731         res = (MonoReflectionEvent*)mono_event;
6732         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6733 }
6734
6735 /**
6736  * mono_get_reflection_missing_object:
6737  * @domain: Domain where the object lives
6738  *
6739  * Returns the System.Reflection.Missing.Value singleton object
6740  * (of type System.Reflection.Missing).
6741  *
6742  * Used as the value for ParameterInfo.DefaultValue when Optional
6743  * is present
6744  */
6745 static MonoObject *
6746 mono_get_reflection_missing_object (MonoDomain *domain)
6747 {
6748         MonoObject *obj;
6749         static MonoClassField *missing_value_field = NULL;
6750         
6751         if (!missing_value_field) {
6752                 MonoClass *missing_klass;
6753                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6754                 mono_class_init (missing_klass);
6755                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6756                 g_assert (missing_value_field);
6757         }
6758         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6759         g_assert (obj);
6760         return obj;
6761 }
6762
6763 static MonoObject*
6764 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6765 {
6766         if (!*dbnull)
6767                 *dbnull = mono_get_dbnull_object (domain);
6768         return *dbnull;
6769 }
6770
6771 static MonoObject*
6772 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6773 {
6774         if (!*reflection_missing)
6775                 *reflection_missing = mono_get_reflection_missing_object (domain);
6776         return *reflection_missing;
6777 }
6778
6779 /*
6780  * mono_param_get_objects:
6781  * @domain: an app domain
6782  * @method: a method
6783  *
6784  * Return an System.Reflection.ParameterInfo array object representing the parameters
6785  * in the method @method.
6786  */
6787 MonoArray*
6788 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6789 {
6790         static MonoClass *System_Reflection_ParameterInfo;
6791         static MonoClass *System_Reflection_ParameterInfo_array;
6792         MonoArray *res = NULL;
6793         MonoReflectionMethod *member = NULL;
6794         MonoReflectionParameter *param = NULL;
6795         char **names, **blobs = NULL;
6796         guint32 *types = NULL;
6797         MonoType *type = NULL;
6798         MonoObject *dbnull = NULL;
6799         MonoObject *missing = NULL;
6800         MonoMarshalSpec **mspecs;
6801         MonoMethodSignature *sig;
6802         MonoVTable *pinfo_vtable;
6803         int i;
6804
6805         if (!System_Reflection_ParameterInfo_array) {
6806                 MonoClass *klass;
6807
6808                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6809                 mono_memory_barrier ();
6810                 System_Reflection_ParameterInfo = klass; 
6811         
6812                 klass = mono_array_class_get (klass, 1);
6813                 mono_memory_barrier ();
6814                 System_Reflection_ParameterInfo_array = klass;
6815         }
6816         
6817         if (!mono_method_signature (method)->param_count)
6818                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6819
6820         /* Note: the cache is based on the address of the signature into the method
6821          * since we already cache MethodInfos with the method as keys.
6822          */
6823         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6824
6825         sig = mono_method_signature (method);
6826         member = mono_method_get_object (domain, method, refclass);
6827         names = g_new (char *, sig->param_count);
6828         mono_method_get_param_names (method, (const char **) names);
6829
6830         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6831         mono_method_get_marshal_info (method, mspecs);
6832
6833         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6834         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6835         for (i = 0; i < sig->param_count; ++i) {
6836                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6837                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6838                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6839                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6840                 param->PositionImpl = i;
6841                 param->AttrsImpl = sig->params [i]->attrs;
6842
6843                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6844                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6845                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6846                         else
6847                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6848                 } else {
6849
6850                         if (!blobs) {
6851                                 blobs = g_new0 (char *, sig->param_count);
6852                                 types = g_new0 (guint32, sig->param_count);
6853                                 get_default_param_value_blobs (method, blobs, types); 
6854                         }
6855
6856                         /* Build MonoType for the type from the Constant Table */
6857                         if (!type)
6858                                 type = g_new0 (MonoType, 1);
6859                         type->type = types [i];
6860                         type->data.klass = NULL;
6861                         if (types [i] == MONO_TYPE_CLASS)
6862                                 type->data.klass = mono_defaults.object_class;
6863                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6864                                 /* For enums, types [i] contains the base type */
6865
6866                                         type->type = MONO_TYPE_VALUETYPE;
6867                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
6868                         } else
6869                                 type->data.klass = mono_class_from_mono_type (type);
6870
6871                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6872
6873                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6874                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6875                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6876                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6877                                 else
6878                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6879                         }
6880                         
6881                 }
6882
6883                 if (mspecs [i + 1])
6884                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6885                 
6886                 mono_array_setref (res, i, param);
6887         }
6888         g_free (names);
6889         g_free (blobs);
6890         g_free (types);
6891         g_free (type);
6892
6893         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6894                 if (mspecs [i])
6895                         mono_metadata_free_marshal_spec (mspecs [i]);
6896         g_free (mspecs);
6897         
6898         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6899 }
6900
6901 MonoArray*
6902 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6903 {
6904         return mono_param_get_objects_internal (domain, method, NULL);
6905 }
6906
6907 /*
6908  * mono_method_body_get_object:
6909  * @domain: an app domain
6910  * @method: a method
6911  *
6912  * Return an System.Reflection.MethodBody object representing the method @method.
6913  */
6914 MonoReflectionMethodBody*
6915 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6916 {
6917         static MonoClass *System_Reflection_MethodBody = NULL;
6918         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6919         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6920         MonoReflectionMethodBody *ret;
6921         MonoMethodHeader *header;
6922         guint32 method_rva, local_var_sig_token;
6923     char *ptr;
6924         unsigned char format, flags;
6925         int i;
6926
6927         if (!System_Reflection_MethodBody)
6928                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6929         if (!System_Reflection_LocalVariableInfo)
6930                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6931         if (!System_Reflection_ExceptionHandlingClause)
6932                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6933
6934         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6935
6936         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6937                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6938             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6939             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6940                 return NULL;
6941         header = mono_method_get_header (method);
6942         
6943         /* Obtain local vars signature token */
6944         method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6945         ptr = mono_image_rva_map (method->klass->image, method_rva);
6946         flags = *(const unsigned char *) ptr;
6947         format = flags & METHOD_HEADER_FORMAT_MASK;
6948         switch (format){
6949         case METHOD_HEADER_TINY_FORMAT:
6950                 local_var_sig_token = 0;
6951                 break;
6952         case METHOD_HEADER_FAT_FORMAT:
6953                 ptr += 2;
6954                 ptr += 2;
6955                 ptr += 4;
6956                 local_var_sig_token = read32 (ptr);
6957                 break;
6958         default:
6959                 g_assert_not_reached ();
6960         }
6961
6962         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6963
6964         ret->init_locals = header->init_locals;
6965         ret->max_stack = header->max_stack;
6966         ret->local_var_sig_token = local_var_sig_token;
6967         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6968         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6969
6970         /* Locals */
6971         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6972         for (i = 0; i < header->num_locals; ++i) {
6973                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6974                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6975                 info->is_pinned = header->locals [i]->pinned;
6976                 info->local_index = i;
6977                 mono_array_setref (ret->locals, i, info);
6978         }
6979
6980         /* Exceptions */
6981         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6982         for (i = 0; i < header->num_clauses; ++i) {
6983                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6984                 MonoExceptionClause *clause = &header->clauses [i];
6985
6986                 info->flags = clause->flags;
6987                 info->try_offset = clause->try_offset;
6988                 info->try_length = clause->try_len;
6989                 info->handler_offset = clause->handler_offset;
6990                 info->handler_length = clause->handler_len;
6991                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6992                         info->filter_offset = clause->data.filter_offset;
6993                 else if (clause->data.catch_class)
6994                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6995
6996                 mono_array_setref (ret->clauses, i, info);
6997         }
6998
6999         mono_metadata_free_mh (header);
7000         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7001         return ret;
7002 }
7003
7004 /**
7005  * mono_get_dbnull_object:
7006  * @domain: Domain where the object lives
7007  *
7008  * Returns the System.DBNull.Value singleton object
7009  *
7010  * Used as the value for ParameterInfo.DefaultValue 
7011  */
7012 MonoObject *
7013 mono_get_dbnull_object (MonoDomain *domain)
7014 {
7015         MonoObject *obj;
7016         static MonoClassField *dbnull_value_field = NULL;
7017         
7018         if (!dbnull_value_field) {
7019                 MonoClass *dbnull_klass;
7020                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7021                 mono_class_init (dbnull_klass);
7022                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7023                 g_assert (dbnull_value_field);
7024         }
7025         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7026         g_assert (obj);
7027         return obj;
7028 }
7029
7030 static void
7031 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7032 {
7033         guint32 param_index, i, lastp, crow = 0;
7034         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7035         gint32 idx;
7036
7037         MonoClass *klass = method->klass;
7038         MonoImage *image = klass->image;
7039         MonoMethodSignature *methodsig = mono_method_signature (method);
7040
7041         MonoTableInfo *constt;
7042         MonoTableInfo *methodt;
7043         MonoTableInfo *paramt;
7044
7045         if (!methodsig->param_count)
7046                 return;
7047
7048         mono_class_init (klass);
7049
7050         if (klass->image->dynamic) {
7051                 MonoReflectionMethodAux *aux;
7052                 if (method->is_inflated)
7053                         method = ((MonoMethodInflated*)method)->declaring;
7054                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7055                 if (aux && aux->param_defaults) {
7056                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7057                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7058                 }
7059                 return;
7060         }
7061
7062         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7063         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7064         constt = &image->tables [MONO_TABLE_CONSTANT];
7065
7066         idx = mono_method_get_index (method) - 1;
7067         g_assert (idx != -1);
7068
7069         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7070         if (idx + 1 < methodt->rows)
7071                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7072         else
7073                 lastp = paramt->rows + 1;
7074
7075         for (i = param_index; i < lastp; ++i) {
7076                 guint32 paramseq;
7077
7078                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7079                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7080
7081                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7082                         continue;
7083
7084                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7085                 if (!crow) {
7086                         continue;
7087                 }
7088         
7089                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7090                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7091                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7092         }
7093
7094         return;
7095 }
7096
7097 MonoObject *
7098 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7099 {
7100         void *retval;
7101         MonoClass *klass;
7102         MonoObject *object;
7103         MonoType *basetype = type;
7104
7105         if (!blob)
7106                 return NULL;
7107         
7108         klass = mono_class_from_mono_type (type);
7109         if (klass->valuetype) {
7110                 object = mono_object_new (domain, klass);
7111                 retval = ((gchar *) object + sizeof (MonoObject));
7112                 if (klass->enumtype)
7113                         basetype = mono_class_enum_basetype (klass);
7114         } else {
7115                 retval = &object;
7116         }
7117                         
7118         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7119                 return object;
7120         else
7121                 return NULL;
7122 }
7123
7124 static int
7125 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7126         int found_sep;
7127         char *s;
7128
7129         memset (assembly, 0, sizeof (MonoAssemblyName));
7130         assembly->name = p;
7131         assembly->culture = "";
7132         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7133
7134         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7135                 p++;
7136         found_sep = 0;
7137         while (g_ascii_isspace (*p) || *p == ',') {
7138                 *p++ = 0;
7139                 found_sep = 1;
7140                 continue;
7141         }
7142         /* failed */
7143         if (!found_sep)
7144                 return 1;
7145         while (*p) {
7146                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7147                         p += 8;
7148                         assembly->major = strtoul (p, &s, 10);
7149                         if (s == p || *s != '.')
7150                                 return 1;
7151                         p = ++s;
7152                         assembly->minor = strtoul (p, &s, 10);
7153                         if (s == p || *s != '.')
7154                                 return 1;
7155                         p = ++s;
7156                         assembly->build = strtoul (p, &s, 10);
7157                         if (s == p || *s != '.')
7158                                 return 1;
7159                         p = ++s;
7160                         assembly->revision = strtoul (p, &s, 10);
7161                         if (s == p)
7162                                 return 1;
7163                         p = s;
7164                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7165                         p += 8;
7166                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7167                                 assembly->culture = "";
7168                                 p += 7;
7169                         } else {
7170                                 assembly->culture = p;
7171                                 while (*p && *p != ',') {
7172                                         p++;
7173                                 }
7174                         }
7175                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7176                         p += 15;
7177                         if (strncmp (p, "null", 4) == 0) {
7178                                 p += 4;
7179                         } else {
7180                                 int len;
7181                                 gchar *start = p;
7182                                 while (*p && *p != ',') {
7183                                         p++;
7184                                 }
7185                                 len = (p - start + 1);
7186                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7187                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7188                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7189                         }
7190                 } else {
7191                         while (*p && *p != ',')
7192                                 p++;
7193                 }
7194                 found_sep = 0;
7195                 while (g_ascii_isspace (*p) || *p == ',') {
7196                         *p++ = 0;
7197                         found_sep = 1;
7198                         continue;
7199                 }
7200                 /* failed */
7201                 if (!found_sep)
7202                         return 1;
7203         }
7204
7205         return 0;
7206 }
7207
7208 /*
7209  * mono_reflection_parse_type:
7210  * @name: type name
7211  *
7212  * Parse a type name as accepted by the GetType () method and output the info
7213  * extracted in the info structure.
7214  * the name param will be mangled, so, make a copy before passing it to this function.
7215  * The fields in info will be valid until the memory pointed to by name is valid.
7216  *
7217  * See also mono_type_get_name () below.
7218  *
7219  * Returns: 0 on parse error.
7220  */
7221 static int
7222 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7223                              MonoTypeNameParse *info)
7224 {
7225         char *start, *p, *w, *temp, *last_point, *startn;
7226         int in_modifiers = 0;
7227         int isbyref = 0, rank, arity = 0, i;
7228
7229         start = p = w = name;
7230
7231         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7232         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7233         info->name = info->name_space = NULL;
7234         info->nested = NULL;
7235         info->modifiers = NULL;
7236         info->type_arguments = NULL;
7237
7238         /* last_point separates the namespace from the name */
7239         last_point = NULL;
7240         /* Skips spaces */
7241         while (*p == ' ') p++, start++, w++, name++;
7242
7243         while (*p) {
7244                 switch (*p) {
7245                 case '+':
7246                         *p = 0; /* NULL terminate the name */
7247                         startn = p + 1;
7248                         info->nested = g_list_append (info->nested, startn);
7249                         /* we have parsed the nesting namespace + name */
7250                         if (info->name)
7251                                 break;
7252                         if (last_point) {
7253                                 info->name_space = start;
7254                                 *last_point = 0;
7255                                 info->name = last_point + 1;
7256                         } else {
7257                                 info->name_space = (char *)"";
7258                                 info->name = start;
7259                         }
7260                         break;
7261                 case '.':
7262                         last_point = p;
7263                         break;
7264                 case '\\':
7265                         ++p;
7266                         break;
7267                 case '&':
7268                 case '*':
7269                 case '[':
7270                 case ',':
7271                 case ']':
7272                         in_modifiers = 1;
7273                         break;
7274                 case '`':
7275                         ++p;
7276                         i = strtol (p, &temp, 10);
7277                         arity += i;
7278                         if (p == temp)
7279                                 return 0;
7280                         p = temp-1;
7281                         break;
7282                 default:
7283                         break;
7284                 }
7285                 if (in_modifiers)
7286                         break;
7287                 // *w++ = *p++;
7288                 p++;
7289         }
7290         
7291         if (!info->name) {
7292                 if (last_point) {
7293                         info->name_space = start;
7294                         *last_point = 0;
7295                         info->name = last_point + 1;
7296                 } else {
7297                         info->name_space = (char *)"";
7298                         info->name = start;
7299                 }
7300         }
7301         while (*p) {
7302                 switch (*p) {
7303                 case '&':
7304                         if (isbyref) /* only one level allowed by the spec */
7305                                 return 0;
7306                         isbyref = 1;
7307                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7308                         *p++ = 0;
7309                         break;
7310                 case '*':
7311                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7312                         *p++ = 0;
7313                         break;
7314                 case '[':
7315                         if (arity != 0) {
7316                                 *p++ = 0;
7317                                 info->type_arguments = g_ptr_array_new ();
7318                                 for (i = 0; i < arity; i++) {
7319                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7320                                         gboolean fqname = FALSE;
7321
7322                                         g_ptr_array_add (info->type_arguments, subinfo);
7323
7324                                         if (*p == '[') {
7325                                                 p++;
7326                                                 fqname = TRUE;
7327                                         }
7328
7329                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7330                                                 return 0;
7331
7332                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7333                                         if (fqname && (*p != ']')) {
7334                                                 char *aname;
7335
7336                                                 if (*p != ',')
7337                                                         return 0;
7338                                                 *p++ = 0;
7339
7340                                                 aname = p;
7341                                                 while (*p && (*p != ']'))
7342                                                         p++;
7343
7344                                                 if (*p != ']')
7345                                                         return 0;
7346
7347                                                 *p++ = 0;
7348                                                 while (*aname) {
7349                                                         if (g_ascii_isspace (*aname)) {
7350                                                                 ++aname;
7351                                                                 continue;
7352                                                         }
7353                                                         break;
7354                                                 }
7355                                                 if (!*aname ||
7356                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7357                                                         return 0;
7358                                         } else if (fqname && (*p == ']')) {
7359                                                 *p++ = 0;
7360                                         }
7361
7362                                         if (i + 1 < arity) {
7363                                                 if (*p != ',')
7364                                                         return 0;
7365                                         } else {
7366                                                 if (*p != ']')
7367                                                         return 0;
7368                                         }
7369                                         *p++ = 0;
7370                                 }
7371
7372                                 arity = 0;
7373                                 break;
7374                         }
7375                         rank = 1;
7376                         *p++ = 0;
7377                         while (*p) {
7378                                 if (*p == ']')
7379                                         break;
7380                                 if (*p == ',')
7381                                         rank++;
7382                                 else if (*p == '*') /* '*' means unknown lower bound */
7383                                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7384                                 else
7385                                         return 0;
7386                                 ++p;
7387                         }
7388                         if (*p++ != ']')
7389                                 return 0;
7390                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7391                         break;
7392                 case ']':
7393                         if (is_recursed)
7394                                 goto end;
7395                         return 0;
7396                 case ',':
7397                         if (is_recursed)
7398                                 goto end;
7399                         *p++ = 0;
7400                         while (*p) {
7401                                 if (g_ascii_isspace (*p)) {
7402                                         ++p;
7403                                         continue;
7404                                 }
7405                                 break;
7406                         }
7407                         if (!*p)
7408                                 return 0; /* missing assembly name */
7409                         if (!assembly_name_to_aname (&info->assembly, p))
7410                                 return 0;
7411                         break;
7412                 default:
7413                         return 0;
7414                 }
7415                 if (info->assembly.name)
7416                         break;
7417         }
7418         // *w = 0; /* terminate class name */
7419  end:
7420         if (!info->name || !*info->name)
7421                 return 0;
7422         if (endptr)
7423                 *endptr = p;
7424         /* add other consistency checks */
7425         return 1;
7426 }
7427
7428 int
7429 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7430 {
7431         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7432 }
7433
7434 static MonoType*
7435 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7436 {
7437         gboolean type_resolve = FALSE;
7438         MonoType *type;
7439         MonoImage *rootimage = image;
7440
7441         if (info->assembly.name) {
7442                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7443                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7444                         /* 
7445                          * This could happen in the AOT compiler case when the search hook is not
7446                          * installed.
7447                          */
7448                         assembly = image->assembly;
7449                 if (!assembly) {
7450                         /* then we must load the assembly ourselve - see #60439 */
7451                         assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7452                         if (!assembly)
7453                                 return NULL;
7454                 }
7455                 image = assembly->image;
7456         } else if (!image) {
7457                 image = mono_defaults.corlib;
7458         }
7459
7460         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7461         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7462                 image = mono_defaults.corlib;
7463                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464         }
7465
7466         return type;
7467 }
7468
7469 static MonoType*
7470 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7471 {
7472         MonoClass *klass;
7473         GList *mod;
7474         int modval;
7475         gboolean bounded = FALSE;
7476         
7477         if (!image)
7478                 image = mono_defaults.corlib;
7479
7480         if (ignorecase)
7481                 klass = mono_class_from_name_case (image, info->name_space, info->name);
7482         else
7483                 klass = mono_class_from_name (image, info->name_space, info->name);
7484         if (!klass)
7485                 return NULL;
7486         for (mod = info->nested; mod; mod = mod->next) {
7487                 gpointer iter = NULL;
7488                 MonoClass *parent;
7489
7490                 parent = klass;
7491                 mono_class_init (parent);
7492
7493                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7494                         if (ignorecase) {
7495                                 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7496                                         break;
7497                         } else {
7498                                 if (strcmp (klass->name, mod->data) == 0)
7499                                         break;
7500                         }
7501                 }
7502                 if (!klass)
7503                         break;
7504         }
7505         if (!klass)
7506                 return NULL;
7507         mono_class_init (klass);
7508
7509         if (info->type_arguments) {
7510                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7511                 MonoReflectionType *the_type;
7512                 MonoType *instance;
7513                 int i;
7514
7515                 for (i = 0; i < info->type_arguments->len; i++) {
7516                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7517
7518                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7519                         if (!type_args [i]) {
7520                                 g_free (type_args);
7521                                 return NULL;
7522                         }
7523                 }
7524
7525                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7526
7527                 instance = mono_reflection_bind_generic_parameters (
7528                         the_type, info->type_arguments->len, type_args);
7529
7530                 g_free (type_args);
7531                 if (!instance)
7532                         return NULL;
7533
7534                 klass = mono_class_from_mono_type (instance);
7535         }
7536
7537         for (mod = info->modifiers; mod; mod = mod->next) {
7538                 modval = GPOINTER_TO_UINT (mod->data);
7539                 if (!modval) { /* byref: must be last modifier */
7540                         return &klass->this_arg;
7541                 } else if (modval == -1) {
7542                         klass = mono_ptr_class_get (&klass->byval_arg);
7543                 } else if (modval == -2) {
7544                         bounded = TRUE;
7545                 } else { /* array rank */
7546                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7547                 }
7548                 mono_class_init (klass);
7549         }
7550
7551         return &klass->byval_arg;
7552 }
7553
7554 /*
7555  * mono_reflection_get_type:
7556  * @image: a metadata context
7557  * @info: type description structure
7558  * @ignorecase: flag for case-insensitive string compares
7559  * @type_resolve: whenever type resolve was already tried
7560  *
7561  * Build a MonoType from the type description in @info.
7562  * 
7563  */
7564
7565 MonoType*
7566 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7567         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7568 }
7569
7570 static MonoType*
7571 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7572 {
7573         MonoReflectionAssemblyBuilder *abuilder;
7574         MonoType *type;
7575         int i;
7576
7577         g_assert (assembly->dynamic);
7578         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7579
7580         /* Enumerate all modules */
7581
7582         type = NULL;
7583         if (abuilder->modules) {
7584                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7585                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7586                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7587                         if (type)
7588                                 break;
7589                 }
7590         }
7591
7592         if (!type && abuilder->loaded_modules) {
7593                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7594                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7595                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7596                         if (type)
7597                                 break;
7598                 }
7599         }
7600
7601         return type;
7602 }
7603         
7604 MonoType*
7605 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7606 {
7607         MonoType *type;
7608         MonoReflectionAssembly *assembly;
7609         GString *fullName;
7610         GList *mod;
7611
7612         if (image && image->dynamic)
7613                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7614         else
7615                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7616         if (type)
7617                 return type;
7618         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7619                 return NULL;
7620
7621         if (type_resolve) {
7622                 if (*type_resolve) 
7623                         return NULL;
7624                 else
7625                         *type_resolve = TRUE;
7626         }
7627         
7628         /* Reconstruct the type name */
7629         fullName = g_string_new ("");
7630         if (info->name_space && (info->name_space [0] != '\0'))
7631                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7632         else
7633                 g_string_printf (fullName, "%s", info->name);
7634         for (mod = info->nested; mod; mod = mod->next)
7635                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7636
7637         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7638         if (assembly) {
7639                 if (assembly->assembly->dynamic)
7640                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7641                 else
7642                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7643                                                                                                           info, ignorecase);
7644         }
7645         g_string_free (fullName, TRUE);
7646         return type;
7647 }
7648
7649 void
7650 mono_reflection_free_type_info (MonoTypeNameParse *info)
7651 {
7652         g_list_free (info->modifiers);
7653         g_list_free (info->nested);
7654
7655         if (info->type_arguments) {
7656                 int i;
7657
7658                 for (i = 0; i < info->type_arguments->len; i++) {
7659                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7660
7661                         mono_reflection_free_type_info (subinfo);
7662                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7663                         g_free (subinfo);
7664                 }
7665
7666                 g_ptr_array_free (info->type_arguments, TRUE);
7667         }
7668 }
7669
7670 /*
7671  * mono_reflection_type_from_name:
7672  * @name: type name.
7673  * @image: a metadata context (can be NULL).
7674  *
7675  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7676  * it defaults to get the type from @image or, if @image is NULL or loading
7677  * from it fails, uses corlib.
7678  * 
7679  */
7680 MonoType*
7681 mono_reflection_type_from_name (char *name, MonoImage *image)
7682 {
7683         MonoType *type = NULL;
7684         MonoTypeNameParse info;
7685         char *tmp;
7686
7687         /* Make a copy since parse_type modifies its argument */
7688         tmp = g_strdup (name);
7689         
7690         /*g_print ("requested type %s\n", str);*/
7691         if (mono_reflection_parse_type (tmp, &info)) {
7692                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7693         }
7694
7695         g_free (tmp);
7696         mono_reflection_free_type_info (&info);
7697         return type;
7698 }
7699
7700 /*
7701  * mono_reflection_get_token:
7702  *
7703  *   Return the metadata token of OBJ which should be an object
7704  * representing a metadata element.
7705  */
7706 guint32
7707 mono_reflection_get_token (MonoObject *obj)
7708 {
7709         MonoClass *klass;
7710         guint32 token = 0;
7711
7712         klass = obj->vtable->klass;
7713
7714         if (strcmp (klass->name, "MethodBuilder") == 0) {
7715                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7716
7717                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7718         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7719                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7720
7721                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7722         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7723                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7724
7725                 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7726                 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7727         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7728                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7729                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7730         } else if (strcmp (klass->name, "MonoType") == 0) {
7731                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7732                 MonoClass *mc = mono_class_from_mono_type (type);
7733                 if (!mono_class_init (mc))
7734                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7735
7736                 token = mc->type_token;
7737         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7738                    strcmp (klass->name, "MonoMethod") == 0 ||
7739                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7740                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7741                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7742                 if (m->method->is_inflated) {
7743                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7744                         return inflated->declaring->token;
7745                 } else {
7746                         token = m->method->token;
7747                 }
7748         } else if (strcmp (klass->name, "MonoField") == 0) {
7749                 MonoReflectionField *f = (MonoReflectionField*)obj;
7750
7751                 if (is_field_on_inst (f->field)) {
7752                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7753                         int field_index = f->field - dgclass->fields;
7754                         MonoObject *obj;
7755
7756                         g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7757                         obj = dgclass->field_objects [field_index];
7758                         return mono_reflection_get_token (obj);
7759                 }
7760                 token = mono_class_get_field_token (f->field);
7761         } else if (strcmp (klass->name, "MonoProperty") == 0) {
7762                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7763
7764                 token = mono_class_get_property_token (p->property);
7765         } else if (strcmp (klass->name, "MonoEvent") == 0) {
7766                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7767
7768                 token = mono_class_get_event_token (p->event);
7769         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7770                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7771                 MonoClass *member_class = mono_object_class (p->MemberImpl);
7772                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7773
7774                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7775         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7776                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7777
7778                 token = m->token;
7779         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7780                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7781         } else {
7782                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7783                 MonoException *ex = mono_get_exception_not_implemented (msg);
7784                 g_free (msg);
7785                 mono_raise_exception (ex);
7786         }
7787
7788         return token;
7789 }
7790
7791 static void*
7792 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7793 {
7794         int slen, type = t->type;
7795         MonoClass *tklass = t->data.klass;
7796
7797 handle_enum:
7798         switch (type) {
7799         case MONO_TYPE_U1:
7800         case MONO_TYPE_I1:
7801         case MONO_TYPE_BOOLEAN: {
7802                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7803                 *bval = *p;
7804                 *end = p + 1;
7805                 return bval;
7806         }
7807         case MONO_TYPE_CHAR:
7808         case MONO_TYPE_U2:
7809         case MONO_TYPE_I2: {
7810                 guint16 *val = g_malloc (sizeof (guint16));
7811                 *val = read16 (p);
7812                 *end = p + 2;
7813                 return val;
7814         }
7815 #if SIZEOF_VOID_P == 4
7816         case MONO_TYPE_U:
7817         case MONO_TYPE_I:
7818 #endif
7819         case MONO_TYPE_R4:
7820         case MONO_TYPE_U4:
7821         case MONO_TYPE_I4: {
7822                 guint32 *val = g_malloc (sizeof (guint32));
7823                 *val = read32 (p);
7824                 *end = p + 4;
7825                 return val;
7826         }
7827 #if SIZEOF_VOID_P == 8
7828         case MONO_TYPE_U: /* error out instead? this should probably not happen */
7829         case MONO_TYPE_I:
7830 #endif
7831         case MONO_TYPE_U8:
7832         case MONO_TYPE_I8: {
7833                 guint64 *val = g_malloc (sizeof (guint64));
7834                 *val = read64 (p);
7835                 *end = p + 8;
7836                 return val;
7837         }
7838         case MONO_TYPE_R8: {
7839                 double *val = g_malloc (sizeof (double));
7840                 readr8 (p, val);
7841                 *end = p + 8;
7842                 return val;
7843         }
7844         case MONO_TYPE_VALUETYPE:
7845                 if (t->data.klass->enumtype) {
7846                         type = mono_class_enum_basetype (t->data.klass)->type;
7847                         goto handle_enum;
7848                 } else {
7849                         MonoClass *k =  t->data.klass;
7850                         
7851                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7852                                 guint64 *val = g_malloc (sizeof (guint64));
7853                                 *val = read64 (p);
7854                                 *end = p + 8;
7855                                 return val;
7856                         }
7857                 }
7858                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7859                 break;
7860                 
7861         case MONO_TYPE_STRING:
7862                 if (*p == (char)0xFF) {
7863                         *end = p + 1;
7864                         return NULL;
7865                 }
7866                 slen = mono_metadata_decode_value (p, &p);
7867                 *end = p + slen;
7868                 return mono_string_new_len (mono_domain_get (), p, slen);
7869         case MONO_TYPE_CLASS: {
7870                 char *n;
7871                 MonoType *t;
7872                 if (*p == (char)0xFF) {
7873                         *end = p + 1;
7874                         return NULL;
7875                 }
7876 handle_type:
7877                 slen = mono_metadata_decode_value (p, &p);
7878                 n = g_memdup (p, slen + 1);
7879                 n [slen] = 0;
7880                 t = mono_reflection_type_from_name (n, image);
7881                 if (!t)
7882                         g_warning ("Cannot load type '%s'", n);
7883                 g_free (n);
7884                 *end = p + slen;
7885                 if (t)
7886                         return mono_type_get_object (mono_domain_get (), t);
7887                 else
7888                         return NULL;
7889         }
7890         case MONO_TYPE_OBJECT: {
7891                 char subt = *p++;
7892                 MonoObject *obj;
7893                 MonoClass *subc = NULL;
7894                 void *val;
7895
7896                 if (subt == 0x50) {
7897                         goto handle_type;
7898                 } else if (subt == 0x0E) {
7899                         type = MONO_TYPE_STRING;
7900                         goto handle_enum;
7901                 } else if (subt == 0x1D) {
7902                         MonoType simple_type = {{0}};
7903                         int etype = *p;
7904                         p ++;
7905
7906                         if (etype == 0x51)
7907                                 /* See Partition II, Appendix B3 */
7908                                 etype = MONO_TYPE_OBJECT;
7909                         type = MONO_TYPE_SZARRAY;
7910                         simple_type.type = etype;
7911                         tklass = mono_class_from_mono_type (&simple_type);
7912                         goto handle_enum;
7913                 } else if (subt == 0x55) {
7914                         char *n;
7915                         MonoType *t;
7916                         slen = mono_metadata_decode_value (p, &p);
7917                         n = g_memdup (p, slen + 1);
7918                         n [slen] = 0;
7919                         t = mono_reflection_type_from_name (n, image);
7920                         if (!t)
7921                                 g_error ("Cannot load type '%s'", n);
7922                         g_free (n);
7923                         p += slen;
7924                         subc = mono_class_from_mono_type (t);
7925                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7926                         MonoType simple_type = {{0}};
7927                         simple_type.type = subt;
7928                         subc = mono_class_from_mono_type (&simple_type);
7929                 } else {
7930                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7931                 }
7932                 val = load_cattr_value (image, &subc->byval_arg, p, end);
7933                 obj = mono_object_new (mono_domain_get (), subc);
7934                 g_assert (!subc->has_references);
7935                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7936                 g_free (val);
7937                 return obj;
7938         }
7939         case MONO_TYPE_SZARRAY: {
7940                 MonoArray *arr;
7941                 guint32 i, alen, basetype;
7942                 alen = read32 (p);
7943                 p += 4;
7944                 if (alen == 0xffffffff) {
7945                         *end = p;
7946                         return NULL;
7947                 }
7948                 arr = mono_array_new (mono_domain_get(), tklass, alen);
7949                 basetype = tklass->byval_arg.type;
7950                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7951                         basetype = mono_class_enum_basetype (tklass)->type;
7952                 switch (basetype)
7953                 {
7954                         case MONO_TYPE_U1:
7955                         case MONO_TYPE_I1:
7956                         case MONO_TYPE_BOOLEAN:
7957                                 for (i = 0; i < alen; i++) {
7958                                         MonoBoolean val = *p++;
7959                                         mono_array_set (arr, MonoBoolean, i, val);
7960                                 }
7961                                 break;
7962                         case MONO_TYPE_CHAR:
7963                         case MONO_TYPE_U2:
7964                         case MONO_TYPE_I2:
7965                                 for (i = 0; i < alen; i++) {
7966                                         guint16 val = read16 (p);
7967                                         mono_array_set (arr, guint16, i, val);
7968                                         p += 2;
7969                                 }
7970                                 break;
7971                         case MONO_TYPE_R4:
7972                         case MONO_TYPE_U4:
7973                         case MONO_TYPE_I4:
7974                                 for (i = 0; i < alen; i++) {
7975                                         guint32 val = read32 (p);
7976                                         mono_array_set (arr, guint32, i, val);
7977                                         p += 4;
7978                                 }
7979                                 break;
7980                         case MONO_TYPE_R8:
7981                                 for (i = 0; i < alen; i++) {
7982                                         double val;
7983                                         readr8 (p, &val);
7984                                         mono_array_set (arr, double, i, val);
7985                                         p += 8;
7986                                 }
7987                                 break;
7988                         case MONO_TYPE_U8:
7989                         case MONO_TYPE_I8:
7990                                 for (i = 0; i < alen; i++) {
7991                                         guint64 val = read64 (p);
7992                                         mono_array_set (arr, guint64, i, val);
7993                                         p += 8;
7994                                 }
7995                                 break;
7996                         case MONO_TYPE_CLASS:
7997                         case MONO_TYPE_OBJECT:
7998                         case MONO_TYPE_STRING:
7999                                 for (i = 0; i < alen; i++) {
8000                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
8001                                         mono_array_setref (arr, i, item);
8002                                 }
8003                                 break;
8004                         default:
8005                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8006                 }
8007                 *end=p;
8008                 return arr;
8009         }
8010         default:
8011                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8012         }
8013         return NULL;
8014 }
8015
8016 static MonoObject*
8017 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8018 {
8019         static MonoClass *klass;
8020         static MonoMethod *ctor;
8021         MonoObject *retval;
8022         void *params [2], *unboxed;
8023
8024         if (!klass)
8025                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8026         if (!ctor)
8027                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8028         
8029         params [0] = mono_type_get_object (mono_domain_get (), t);
8030         params [1] = val;
8031         retval = mono_object_new (mono_domain_get (), klass);
8032         unboxed = mono_object_unbox (retval);
8033         mono_runtime_invoke (ctor, unboxed, params, NULL);
8034
8035         return retval;
8036 }
8037
8038 static MonoObject*
8039 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8040 {
8041         static MonoClass *klass;
8042         static MonoMethod *ctor;
8043         MonoObject *retval;
8044         void *unboxed, *params [2];
8045
8046         if (!klass)
8047                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8048         if (!ctor)
8049                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8050
8051         params [0] = minfo;
8052         params [1] = typedarg;
8053         retval = mono_object_new (mono_domain_get (), klass);
8054         unboxed = mono_object_unbox (retval);
8055         mono_runtime_invoke (ctor, unboxed, params, NULL);
8056
8057         return retval;
8058 }
8059
8060 static gboolean
8061 type_is_reference (MonoType *type)
8062 {
8063         switch (type->type) {
8064         case MONO_TYPE_BOOLEAN:
8065         case MONO_TYPE_CHAR:
8066         case MONO_TYPE_U:
8067         case MONO_TYPE_I:
8068         case MONO_TYPE_U1:
8069         case MONO_TYPE_I1:
8070         case MONO_TYPE_U2:
8071         case MONO_TYPE_I2:
8072         case MONO_TYPE_U4:
8073         case MONO_TYPE_I4:
8074         case MONO_TYPE_U8:
8075         case MONO_TYPE_I8:
8076         case MONO_TYPE_R8:
8077         case MONO_TYPE_R4:
8078         case MONO_TYPE_VALUETYPE:
8079                 return FALSE;
8080         default:
8081                 return TRUE;
8082         }
8083 }
8084
8085 static void
8086 free_param_data (MonoMethodSignature *sig, void **params) {
8087         int i;
8088         for (i = 0; i < sig->param_count; ++i) {
8089                 if (!type_is_reference (sig->params [i]))
8090                         g_free (params [i]);
8091         }
8092 }
8093
8094 /*
8095  * Find the field index in the metadata FieldDef table.
8096  */
8097 static guint32
8098 find_field_index (MonoClass *klass, MonoClassField *field) {
8099         int i;
8100
8101         for (i = 0; i < klass->field.count; ++i) {
8102                 if (field == &klass->fields [i])
8103                         return klass->field.first + 1 + i;
8104         }
8105         return 0;
8106 }
8107
8108 /*
8109  * Find the property index in the metadata Property table.
8110  */
8111 static guint32
8112 find_property_index (MonoClass *klass, MonoProperty *property) {
8113         int i;
8114
8115         for (i = 0; i < klass->ext->property.count; ++i) {
8116                 if (property == &klass->ext->properties [i])
8117                         return klass->ext->property.first + 1 + i;
8118         }
8119         return 0;
8120 }
8121
8122 /*
8123  * Find the event index in the metadata Event table.
8124  */
8125 static guint32
8126 find_event_index (MonoClass *klass, MonoEvent *event) {
8127         int i;
8128
8129         for (i = 0; i < klass->ext->event.count; ++i) {
8130                 if (event == &klass->ext->events [i])
8131                         return klass->ext->event.first + 1 + i;
8132         }
8133         return 0;
8134 }
8135
8136 static MonoObject*
8137 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8138 {
8139         const char *p = (const char*)data;
8140         const char *named;
8141         guint32 i, j, num_named;
8142         MonoObject *attr;
8143         void *params_buf [32];
8144         void **params;
8145         MonoMethodSignature *sig;
8146
8147         mono_class_init (method->klass);
8148
8149         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8150                 return NULL;
8151
8152         if (len == 0) {
8153                 attr = mono_object_new (mono_domain_get (), method->klass);
8154                 mono_runtime_invoke (method, attr, NULL, NULL);
8155                 return attr;
8156         }
8157
8158         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8159                 return NULL;
8160
8161         /*g_print ("got attr %s\n", method->klass->name);*/
8162
8163         sig = mono_method_signature (method);
8164         if (sig->param_count < 32)
8165                 params = params_buf;
8166         else
8167                 /* Allocate using GC so it gets GC tracking */
8168                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8169
8170         /* skip prolog */
8171         p += 2;
8172         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8173                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8174         }
8175
8176         named = p;
8177         attr = mono_object_new (mono_domain_get (), method->klass);
8178         mono_runtime_invoke (method, attr, params, NULL);
8179         free_param_data (method->signature, params);
8180         num_named = read16 (named);
8181         named += 2;
8182         for (j = 0; j < num_named; j++) {
8183                 gint name_len;
8184                 char *name, named_type, data_type;
8185                 named_type = *named++;
8186                 data_type = *named++; /* type of data */
8187                 if (data_type == MONO_TYPE_SZARRAY)
8188                         data_type = *named++;
8189                 if (data_type == MONO_TYPE_ENUM) {
8190                         gint type_len;
8191                         char *type_name;
8192                         type_len = mono_metadata_decode_blob_size (named, &named);
8193                         type_name = g_malloc (type_len + 1);
8194                         memcpy (type_name, named, type_len);
8195                         type_name [type_len] = 0;
8196                         named += type_len;
8197                         /* FIXME: lookup the type and check type consistency */
8198                         g_free (type_name);
8199                 }
8200                 name_len = mono_metadata_decode_blob_size (named, &named);
8201                 name = g_malloc (name_len + 1);
8202                 memcpy (name, named, name_len);
8203                 name [name_len] = 0;
8204                 named += name_len;
8205                 if (named_type == 0x53) {
8206                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8207                         void *val = load_cattr_value (image, field->type, named, &named);
8208                         mono_field_set_value (attr, field, val);
8209                         if (!type_is_reference (field->type))
8210                                 g_free (val);
8211                 } else if (named_type == 0x54) {
8212                         MonoProperty *prop;
8213                         void *pparams [1];
8214                         MonoType *prop_type;
8215
8216                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8217                         /* can we have more that 1 arg in a custom attr named property? */
8218                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8219                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8220                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
8221                         mono_property_set_value (prop, attr, pparams, NULL);
8222                         if (!type_is_reference (prop_type))
8223                                 g_free (pparams [0]);
8224                 }
8225                 g_free (name);
8226         }
8227
8228         if (params != params_buf)
8229                 mono_gc_free_fixed (params);
8230
8231         return attr;
8232 }
8233         
8234 /*
8235  * mono_reflection_create_custom_attr_data_args:
8236  *
8237  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8238  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8239  * NAMED_ARG_INFO will contain information about the named arguments.
8240  */
8241 void
8242 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)
8243 {
8244         MonoArray *typedargs, *namedargs;
8245         MonoClass *attrklass;
8246         MonoDomain *domain;
8247         const char *p = (const char*)data;
8248         const char *named;
8249         guint32 i, j, num_named;
8250         CattrNamedArg *arginfo = NULL;
8251
8252         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8253                 return;
8254
8255         mono_class_init (method->klass);
8256
8257         *typed_args = NULL;
8258         *named_args = NULL;
8259         *named_arg_info = NULL;
8260         
8261         domain = mono_domain_get ();
8262
8263         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8264                 return;
8265
8266         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8267         
8268         /* skip prolog */
8269         p += 2;
8270         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8271                 MonoObject *obj;
8272                 void *val;
8273
8274                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8275                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8276                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8277                 mono_array_setref (typedargs, i, obj);
8278
8279                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8280                         g_free (val);
8281         }
8282
8283         named = p;
8284         num_named = read16 (named);
8285         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8286         named += 2;
8287         attrklass = method->klass;
8288
8289         arginfo = g_new0 (CattrNamedArg, num_named);
8290         *named_arg_info = arginfo;
8291
8292         for (j = 0; j < num_named; j++) {
8293                 gint name_len;
8294                 char *name, named_type, data_type;
8295                 named_type = *named++;
8296                 data_type = *named++; /* type of data */
8297                 if (data_type == MONO_TYPE_SZARRAY)
8298                         data_type = *named++;
8299                 if (data_type == MONO_TYPE_ENUM) {
8300                         gint type_len;
8301                         char *type_name;
8302                         type_len = mono_metadata_decode_blob_size (named, &named);
8303                         type_name = g_malloc (type_len + 1);
8304                         memcpy (type_name, named, type_len);
8305                         type_name [type_len] = 0;
8306                         named += type_len;
8307                         /* FIXME: lookup the type and check type consistency */
8308                         g_free (type_name);
8309                 }
8310                 name_len = mono_metadata_decode_blob_size (named, &named);
8311                 name = g_malloc (name_len + 1);
8312                 memcpy (name, named, name_len);
8313                 name [name_len] = 0;
8314                 named += name_len;
8315                 if (named_type == 0x53) {
8316                         MonoObject *obj;
8317                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8318                         void *val;
8319
8320                         arginfo [j].type = field->type;
8321                         arginfo [j].field = field;
8322
8323                         val = load_cattr_value (image, field->type, named, &named);
8324                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8325                         mono_array_setref (namedargs, j, obj);
8326                         if (!type_is_reference (field->type))
8327                                 g_free (val);
8328                 } else if (named_type == 0x54) {
8329                         MonoObject *obj;
8330                         MonoType *prop_type;
8331                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8332                         void *val;
8333
8334                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8335                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8336
8337                         arginfo [j].type = prop_type;
8338                         arginfo [j].prop = prop;
8339
8340                         val = load_cattr_value (image, prop_type, named, &named);
8341                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8342                         mono_array_setref (namedargs, j, obj);
8343                         if (!type_is_reference (prop_type))
8344                                 g_free (val);
8345                 }
8346                 g_free (name);
8347         }
8348
8349         *typed_args = typedargs;
8350         *named_args = namedargs;
8351 }
8352
8353 static MonoObject*
8354 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8355 {
8356         MonoArray *typedargs, *namedargs;
8357         static MonoMethod *ctor;
8358         MonoDomain *domain;
8359         MonoObject *attr;
8360         void *params [3];
8361         CattrNamedArg *arginfo;
8362         int i;
8363
8364         mono_class_init (method->klass);
8365
8366         if (!ctor)
8367                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8368
8369         domain = mono_domain_get ();
8370         if (len == 0) {
8371                 /* This is for Attributes with no parameters */
8372                 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8373                 params [0] = mono_method_get_object (domain, method, NULL);
8374                 params [1] = params [2] = NULL;
8375                 mono_runtime_invoke (method, attr, params, NULL);
8376                 return attr;
8377         }
8378
8379         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8380         if (!typedargs || !namedargs)
8381                 return NULL;
8382
8383         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8384                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8385                 MonoObject *typedarg;
8386
8387                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8388                 mono_array_setref (typedargs, i, typedarg);
8389         }
8390
8391         for (i = 0; i < mono_array_length (namedargs); ++i) {
8392                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8393                 MonoObject *typedarg, *namedarg, *minfo;
8394
8395                 if (arginfo [i].prop)
8396                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8397                 else
8398                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8399
8400                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8401                 namedarg = create_cattr_named_arg (minfo, typedarg);
8402
8403                 mono_array_setref (namedargs, i, namedarg);
8404         }
8405
8406         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8407         params [0] = mono_method_get_object (domain, method, NULL);
8408         params [1] = typedargs;
8409         params [2] = namedargs;
8410         mono_runtime_invoke (ctor, attr, params, NULL);
8411         return attr;
8412 }
8413
8414 MonoArray*
8415 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8416 {
8417         MonoArray *result;
8418         MonoObject *attr;
8419         int i;
8420
8421         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8422         for (i = 0; i < cinfo->num_attrs; ++i) {
8423                 if (!cinfo->attrs [i].ctor)
8424                         /* The cattr type is not finished yet */
8425                         /* We should include the type name but cinfo doesn't contain it */
8426                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8427                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8428                 mono_array_setref (result, i, attr);
8429         }
8430         return result;
8431 }
8432
8433 static MonoArray*
8434 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8435 {
8436         MonoArray *result;
8437         MonoObject *attr;
8438         int i, n;
8439
8440         n = 0;
8441         for (i = 0; i < cinfo->num_attrs; ++i) {
8442                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8443                         n ++;
8444         }
8445
8446         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8447         n = 0;
8448         for (i = 0; i < cinfo->num_attrs; ++i) {
8449                 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8450                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8451                         mono_array_setref (result, n, attr);
8452                         n ++;
8453                 }
8454         }
8455         return result;
8456 }
8457
8458 static MonoArray*
8459 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8460 {
8461         MonoArray *result;
8462         MonoObject *attr;
8463         int i;
8464         
8465         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8466         for (i = 0; i < cinfo->num_attrs; ++i) {
8467                 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8468                 mono_array_setref (result, i, attr);
8469         }
8470         return result;
8471 }
8472
8473 /**
8474  * mono_custom_attrs_from_index:
8475  *
8476  * Returns: NULL if no attributes are found or if a loading error occurs.
8477  */
8478 MonoCustomAttrInfo*
8479 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8480 {
8481         guint32 mtoken, i, len;
8482         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8483         MonoTableInfo *ca;
8484         MonoCustomAttrInfo *ainfo;
8485         GList *tmp, *list = NULL;
8486         const char *data;
8487
8488         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8489
8490         i = mono_metadata_custom_attrs_from_index (image, idx);
8491         if (!i)
8492                 return NULL;
8493         i --;
8494         while (i < ca->rows) {
8495                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8496                         break;
8497                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8498                 ++i;
8499         }
8500         len = g_list_length (list);
8501         if (!len)
8502                 return NULL;
8503         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8504         ainfo->num_attrs = len;
8505         ainfo->image = image;
8506         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8507                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8508                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8509                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8510                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8511                         mtoken |= MONO_TOKEN_METHOD_DEF;
8512                         break;
8513                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8514                         mtoken |= MONO_TOKEN_MEMBER_REF;
8515                         break;
8516                 default:
8517                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8518                         break;
8519                 }
8520                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8521                 if (!ainfo->attrs [i].ctor) {
8522                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8523                         g_list_free (list);
8524                         g_free (ainfo);
8525                         return NULL;
8526                 }
8527
8528                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8529                         /*FIXME raising an exception here doesn't make any sense*/
8530                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8531                         g_list_free (list);
8532                         g_free (ainfo);
8533                         return NULL;
8534                 }
8535                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8536                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8537                 ainfo->attrs [i].data = (guchar*)data;
8538         }
8539         g_list_free (list);
8540
8541         return ainfo;
8542 }
8543
8544 MonoCustomAttrInfo*
8545 mono_custom_attrs_from_method (MonoMethod *method)
8546 {
8547         guint32 idx;
8548
8549         /*
8550          * An instantiated method has the same cattrs as the generic method definition.
8551          *
8552          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8553          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8554          */
8555         if (method->is_inflated)
8556                 method = ((MonoMethodInflated *) method)->declaring;
8557         
8558         if (method->dynamic || method->klass->image->dynamic)
8559                 return lookup_custom_attr (method->klass->image, method);
8560
8561         if (!method->token)
8562                 /* Synthetic methods */
8563                 return NULL;
8564
8565         idx = mono_method_get_index (method);
8566         idx <<= MONO_CUSTOM_ATTR_BITS;
8567         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8568         return mono_custom_attrs_from_index (method->klass->image, idx);
8569 }
8570
8571 MonoCustomAttrInfo*
8572 mono_custom_attrs_from_class (MonoClass *klass)
8573 {
8574         guint32 idx;
8575
8576         if (klass->generic_class)
8577                 klass = klass->generic_class->container_class;
8578
8579         if (klass->image->dynamic)
8580                 return lookup_custom_attr (klass->image, klass);
8581
8582         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8583                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8584                 idx <<= MONO_CUSTOM_ATTR_BITS;
8585                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8586         } else {
8587                 idx = mono_metadata_token_index (klass->type_token);
8588                 idx <<= MONO_CUSTOM_ATTR_BITS;
8589                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8590         }
8591         return mono_custom_attrs_from_index (klass->image, idx);
8592 }
8593
8594 MonoCustomAttrInfo*
8595 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8596 {
8597         guint32 idx;
8598         
8599         if (assembly->image->dynamic)
8600                 return lookup_custom_attr (assembly->image, assembly);
8601         idx = 1; /* there is only one assembly */
8602         idx <<= MONO_CUSTOM_ATTR_BITS;
8603         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8604         return mono_custom_attrs_from_index (assembly->image, idx);
8605 }
8606
8607 static MonoCustomAttrInfo*
8608 mono_custom_attrs_from_module (MonoImage *image)
8609 {
8610         guint32 idx;
8611         
8612         if (image->dynamic)
8613                 return lookup_custom_attr (image, image);
8614         idx = 1; /* there is only one module */
8615         idx <<= MONO_CUSTOM_ATTR_BITS;
8616         idx |= MONO_CUSTOM_ATTR_MODULE;
8617         return mono_custom_attrs_from_index (image, idx);
8618 }
8619
8620 MonoCustomAttrInfo*
8621 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8622 {
8623         guint32 idx;
8624         
8625         if (klass->image->dynamic) {
8626                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8627                 return lookup_custom_attr (klass->image, property);
8628         }
8629         idx = find_property_index (klass, property);
8630         idx <<= MONO_CUSTOM_ATTR_BITS;
8631         idx |= MONO_CUSTOM_ATTR_PROPERTY;
8632         return mono_custom_attrs_from_index (klass->image, idx);
8633 }
8634
8635 MonoCustomAttrInfo*
8636 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8637 {
8638         guint32 idx;
8639         
8640         if (klass->image->dynamic) {
8641                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8642                 return lookup_custom_attr (klass->image, event);
8643         }
8644         idx = find_event_index (klass, event);
8645         idx <<= MONO_CUSTOM_ATTR_BITS;
8646         idx |= MONO_CUSTOM_ATTR_EVENT;
8647         return mono_custom_attrs_from_index (klass->image, idx);
8648 }
8649
8650 MonoCustomAttrInfo*
8651 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8652 {
8653         guint32 idx;
8654         if (klass->image->dynamic) {
8655                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8656                 return lookup_custom_attr (klass->image, field);
8657         }
8658         idx = find_field_index (klass, field);
8659         idx <<= MONO_CUSTOM_ATTR_BITS;
8660         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8661         return mono_custom_attrs_from_index (klass->image, idx);
8662 }
8663
8664 MonoCustomAttrInfo*
8665 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8666 {
8667         MonoTableInfo *ca;
8668         guint32 i, idx, method_index;
8669         guint32 param_list, param_last, param_pos, found;
8670         MonoImage *image;
8671         MonoReflectionMethodAux *aux;
8672
8673         /*
8674          * An instantiated method has the same cattrs as the generic method definition.
8675          *
8676          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8677          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8678          */
8679         if (method->is_inflated)
8680                 method = ((MonoMethodInflated *) method)->declaring;
8681
8682         if (method->klass->image->dynamic) {
8683                 MonoCustomAttrInfo *res, *ainfo;
8684                 int size;
8685
8686                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8687                 if (!aux || !aux->param_cattr)
8688                         return NULL;
8689
8690                 /* Need to copy since it will be freed later */
8691                 ainfo = aux->param_cattr [param];
8692                 if (!ainfo)
8693                         return NULL;
8694                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8695                 res = g_malloc0 (size);
8696                 memcpy (res, ainfo, size);
8697                 return res;
8698         }
8699
8700         image = method->klass->image;
8701         method_index = mono_method_get_index (method);
8702         if (!method_index)
8703                 return NULL;
8704         ca = &image->tables [MONO_TABLE_METHOD];
8705
8706         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8707         if (method_index == ca->rows) {
8708                 ca = &image->tables [MONO_TABLE_PARAM];
8709                 param_last = ca->rows + 1;
8710         } else {
8711                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8712                 ca = &image->tables [MONO_TABLE_PARAM];
8713         }
8714         found = FALSE;
8715         for (i = param_list; i < param_last; ++i) {
8716                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8717                 if (param_pos == param) {
8718                         found = TRUE;
8719                         break;
8720                 }
8721         }
8722         if (!found)
8723                 return NULL;
8724         idx = i;
8725         idx <<= MONO_CUSTOM_ATTR_BITS;
8726         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8727         return mono_custom_attrs_from_index (image, idx);
8728 }
8729
8730 gboolean
8731 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8732 {
8733         int i;
8734         MonoClass *klass;
8735         for (i = 0; i < ainfo->num_attrs; ++i) {
8736                 klass = ainfo->attrs [i].ctor->klass;
8737                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8738                         return TRUE;
8739         }
8740         return FALSE;
8741 }
8742
8743 MonoObject*
8744 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8745 {
8746         int i, attr_index;
8747         MonoClass *klass;
8748         MonoArray *attrs;
8749
8750         attr_index = -1;
8751         for (i = 0; i < ainfo->num_attrs; ++i) {
8752                 klass = ainfo->attrs [i].ctor->klass;
8753                 if (mono_class_has_parent (klass, attr_klass)) {
8754                         attr_index = i;
8755                         break;
8756                 }
8757         }
8758         if (attr_index == -1)
8759                 return NULL;
8760
8761         attrs = mono_custom_attrs_construct (ainfo);
8762         if (attrs)
8763                 return mono_array_get (attrs, MonoObject*, attr_index);
8764         else
8765                 return NULL;
8766 }
8767
8768 /*
8769  * mono_reflection_get_custom_attrs_info:
8770  * @obj: a reflection object handle
8771  *
8772  * Return the custom attribute info for attributes defined for the
8773  * reflection handle @obj. The objects.
8774  *
8775  * FIXME this function leaks like a sieve for SRE objects.
8776  */
8777 MonoCustomAttrInfo*
8778 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8779 {
8780         MonoClass *klass;
8781         MonoCustomAttrInfo *cinfo = NULL;
8782         
8783         klass = obj->vtable->klass;
8784         if (klass == mono_defaults.monotype_class) {
8785                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8786                 klass = mono_class_from_mono_type (type);
8787                 if (!mono_class_init (klass))
8788                         mono_raise_exception (mono_class_get_exception_for_failure (klass));
8789                 cinfo = mono_custom_attrs_from_class (klass);
8790         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8791                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8792                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8793         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8794                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8795                 cinfo = mono_custom_attrs_from_module (module->image);
8796         } else if (strcmp ("MonoProperty", klass->name) == 0) {
8797                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8798                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8799         } else if (strcmp ("MonoEvent", klass->name) == 0) {
8800                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8801                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8802         } else if (strcmp ("MonoField", klass->name) == 0) {
8803                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8804                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8805         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8806                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8807                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8808         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8809                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8810                 cinfo = mono_custom_attrs_from_method (rmethod->method);
8811         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8812                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8813                 MonoClass *member_class = mono_object_class (param->MemberImpl);
8814                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8815                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8816                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8817                 } else if (is_sr_mono_property (member_class)) {
8818                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8819                         MonoMethod *method;
8820                         if (!(method = prop->property->get))
8821                                 method = prop->property->set;
8822                         g_assert (method);
8823
8824                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8825                 } 
8826 #ifndef DISABLE_REFLECTION_EMIT
8827                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8828                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8829                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8830                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8831                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8832                         MonoMethod *method = NULL;
8833                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
8834                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8835                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8836                                 method = ((MonoReflectionMethod *)c->cb)->method;
8837                         else
8838                                 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));
8839
8840                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8841                 } 
8842 #endif
8843                 else {
8844                         char *type_name = mono_type_get_full_name (member_class);
8845                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8846                         MonoException *ex = mono_get_exception_not_supported  (msg);
8847                         g_free (type_name);
8848                         g_free (msg);
8849                         mono_raise_exception (ex);
8850                 }
8851         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8852                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8853                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8854         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8855                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8856                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8857         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8858                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8859                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8860         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8861                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8862                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8863         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8864                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8865                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8866         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8867                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8868                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8869         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8870                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8871                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8872         } else { /* handle other types here... */
8873                 g_error ("get custom attrs not yet supported for %s", klass->name);
8874         }
8875
8876         return cinfo;
8877 }
8878
8879 /*
8880  * mono_reflection_get_custom_attrs_by_type:
8881  * @obj: a reflection object handle
8882  *
8883  * Return an array with all the custom attributes defined of the
8884  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
8885  * of that type are returned. The objects are fully build. Return NULL if a loading error
8886  * occurs.
8887  */
8888 MonoArray*
8889 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8890 {
8891         MonoArray *result;
8892         MonoCustomAttrInfo *cinfo;
8893
8894         cinfo = mono_reflection_get_custom_attrs_info (obj);
8895         if (cinfo) {
8896                 if (attr_klass)
8897                         result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8898                 else
8899                         result = mono_custom_attrs_construct (cinfo);
8900                 if (!cinfo->cached)
8901                         mono_custom_attrs_free (cinfo);
8902         } else {
8903                 if (mono_loader_get_last_error ())
8904                         return NULL;
8905                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8906         }
8907
8908         return result;
8909 }
8910
8911 /*
8912  * mono_reflection_get_custom_attrs:
8913  * @obj: a reflection object handle
8914  *
8915  * Return an array with all the custom attributes defined of the
8916  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8917  * occurs.
8918  */
8919 MonoArray*
8920 mono_reflection_get_custom_attrs (MonoObject *obj)
8921 {
8922         return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8923 }
8924
8925 /*
8926  * mono_reflection_get_custom_attrs_data:
8927  * @obj: a reflection obj handle
8928  *
8929  * Returns an array of System.Reflection.CustomAttributeData,
8930  * which include information about attributes reflected on
8931  * types loaded using the Reflection Only methods
8932  */
8933 MonoArray*
8934 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8935 {
8936         MonoArray *result;
8937         MonoCustomAttrInfo *cinfo;
8938
8939         cinfo = mono_reflection_get_custom_attrs_info (obj);
8940         if (cinfo) {
8941                 result = mono_custom_attrs_data_construct (cinfo);
8942                 if (!cinfo->cached)
8943                         mono_custom_attrs_free (cinfo);
8944         } else
8945                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8946
8947         return result;
8948 }
8949
8950 static MonoReflectionType*
8951 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8952 {
8953         static MonoMethod *method_get_underlying_system_type = NULL;
8954         MonoMethod *usertype_method;
8955
8956         if (!method_get_underlying_system_type)
8957                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8958         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8959         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8960 }
8961
8962
8963 static gboolean
8964 is_corlib_type (MonoClass *class)
8965 {
8966         return class->image == mono_defaults.corlib;
8967 }
8968
8969 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8970         static MonoClass *cached_class; \
8971         if (cached_class) \
8972                 return cached_class == _class; \
8973         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8974                 cached_class = _class; \
8975                 return TRUE; \
8976         } \
8977         return FALSE; \
8978 } while (0) \
8979
8980
8981 #ifndef DISABLE_REFLECTION_EMIT
8982 static gboolean
8983 is_sre_array (MonoClass *class)
8984 {
8985         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8986 }
8987
8988 static gboolean
8989 is_sre_byref (MonoClass *class)
8990 {
8991         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8992 }
8993
8994 static gboolean
8995 is_sre_pointer (MonoClass *class)
8996 {
8997         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8998 }
8999
9000 static gboolean
9001 is_sre_generic_instance (MonoClass *class)
9002 {
9003         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9004 }
9005
9006 static gboolean
9007 is_sre_type_builder (MonoClass *class)
9008 {
9009         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9010 }
9011
9012 static gboolean
9013 is_sre_method_builder (MonoClass *class)
9014 {
9015         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9016 }
9017
9018 static gboolean
9019 is_sre_ctor_builder (MonoClass *class)
9020 {
9021         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9022 }
9023
9024 static gboolean
9025 is_sre_field_builder (MonoClass *class)
9026 {
9027         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9028 }
9029
9030 static gboolean
9031 is_sre_method_on_tb_inst (MonoClass *class)
9032 {
9033         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9034 }
9035
9036 static gboolean
9037 is_sre_ctor_on_tb_inst (MonoClass *class)
9038 {
9039         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9040 }
9041
9042 MonoType*
9043 mono_reflection_type_get_handle (MonoReflectionType* ref)
9044 {
9045         MonoClass *class;
9046         if (!ref)
9047                 return NULL;
9048         if (ref->type)
9049                 return ref->type;
9050
9051         if (is_usertype (ref)) {
9052                 ref = mono_reflection_type_get_underlying_system_type (ref);
9053                 if (ref == NULL || is_usertype (ref))
9054                         return NULL;
9055                 if (ref->type)
9056                         return ref->type;
9057         }
9058
9059         class = mono_object_class (ref);
9060
9061         if (is_sre_array (class)) {
9062                 MonoType *res;
9063                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9064                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9065                 g_assert (base);
9066                 if (sre_array->rank == 0) //single dimentional array
9067                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9068                 else
9069                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9070                 sre_array->type.type = res;
9071                 return res;
9072         } else if (is_sre_byref (class)) {
9073                 MonoType *res;
9074                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9075                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9076                 g_assert (base);
9077                 res = &mono_class_from_mono_type (base)->this_arg;
9078                 sre_byref->type.type = res;
9079                 return res;
9080         } else if (is_sre_pointer (class)) {
9081                 MonoType *res;
9082                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9083                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9084                 g_assert (base);
9085                 res = &mono_ptr_class_get (base)->byval_arg;
9086                 sre_pointer->type.type = res;
9087                 return res;
9088         } else if (is_sre_generic_instance (class)) {
9089                 MonoType *res, **types;
9090                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9091                 int i, count;
9092
9093                 count = mono_array_length (gclass->type_arguments);
9094                 types = g_new0 (MonoType*, count);
9095                 for (i = 0; i < count; ++i) {
9096                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9097                         types [i] = mono_reflection_type_get_handle (t);
9098                         if (!types[i]) {
9099                                 g_free (types);
9100                                 return NULL;
9101                         }
9102                 }
9103
9104                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9105                 g_free (types);
9106                 g_assert (res);
9107                 gclass->type.type = res;
9108                 return res;
9109         }
9110
9111         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9112         return NULL;
9113 }
9114
9115
9116
9117 void
9118 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9119 {
9120         mono_reflection_type_get_handle (type);
9121 }
9122
9123 void
9124 mono_reflection_register_with_runtime (MonoReflectionType *type)
9125 {
9126         MonoType *res = mono_reflection_type_get_handle (type);
9127         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9128         MonoClass *class;
9129
9130         if (!res)
9131                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9132
9133         class = mono_class_from_mono_type (res);
9134
9135         mono_loader_lock (); /*same locking as mono_type_get_object*/
9136         mono_domain_lock (domain);
9137
9138         if (!class->image->dynamic) {
9139                 mono_class_setup_supertypes (class);
9140         } else {
9141                 if (!domain->type_hash)
9142                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash, 
9143                                         (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9144                 mono_g_hash_table_insert (domain->type_hash, res, type);
9145         }
9146         mono_domain_unlock (domain);
9147         mono_loader_unlock ();
9148 }
9149
9150 /**
9151  * LOCKING: Assumes the loader lock is held.
9152  */
9153 static MonoMethodSignature*
9154 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9155         MonoMethodSignature *sig;
9156         int count, i;
9157
9158         count = parameters? mono_array_length (parameters): 0;
9159
9160         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9161         sig->param_count = count;
9162         sig->sentinelpos = -1; /* FIXME */
9163         for (i = 0; i < count; ++i)
9164                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9165         return sig;
9166 }
9167
9168 /**
9169  * LOCKING: Assumes the loader lock is held.
9170  */
9171 static MonoMethodSignature*
9172 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9173         MonoMethodSignature *sig;
9174
9175         sig = parameters_to_signature (image, ctor->parameters);
9176         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9177         sig->ret = &mono_defaults.void_class->byval_arg;
9178         return sig;
9179 }
9180
9181 /**
9182  * LOCKING: Assumes the loader lock is held.
9183  */
9184 static MonoMethodSignature*
9185 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9186         MonoMethodSignature *sig;
9187
9188         sig = parameters_to_signature (image, method->parameters);
9189         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9190         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9191         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9192         return sig;
9193 }
9194
9195 static MonoMethodSignature*
9196 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9197         MonoMethodSignature *sig;
9198
9199         sig = parameters_to_signature (NULL, method->parameters);
9200         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9201         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9202         sig->generic_param_count = 0;
9203         return sig;
9204 }
9205
9206 static void
9207 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9208 {
9209         MonoClass *klass = mono_object_class (prop);
9210         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9211                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9212                 *name = mono_string_to_utf8 (pb->name);
9213                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9214         } else {
9215                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9216                 *name = g_strdup (p->property->name);
9217                 if (p->property->get)
9218                         *type = mono_method_signature (p->property->get)->ret;
9219                 else
9220                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9221         }
9222 }
9223
9224 static void
9225 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9226 {
9227         MonoClass *klass = mono_object_class (field);
9228         if (strcmp (klass->name, "FieldBuilder") == 0) {
9229                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9230                 *name = mono_string_to_utf8 (fb->name);
9231                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9232         } else {
9233                 MonoReflectionField *f = (MonoReflectionField *)field;
9234                 *name = g_strdup (mono_field_get_name (f->field));
9235                 *type = f->field->type;
9236         }
9237 }
9238
9239 #else /* DISABLE_REFLECTION_EMIT */
9240
9241 void
9242 mono_reflection_register_with_runtime (MonoReflectionType *type)
9243 {
9244         /* This is empty */
9245 }
9246
9247 static gboolean
9248 is_sre_type_builder (MonoClass *class)
9249 {
9250         return FALSE;
9251 }
9252
9253 static gboolean
9254 is_sre_generic_instance (MonoClass *class)
9255 {
9256         return FALSE;
9257 }
9258
9259 #endif /* !DISABLE_REFLECTION_EMIT */
9260
9261
9262 static gboolean
9263 is_sr_mono_field (MonoClass *class)
9264 {
9265         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9266 }
9267
9268 static gboolean
9269 is_sr_mono_property (MonoClass *class)
9270 {
9271         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9272 }
9273
9274 static gboolean
9275 is_sr_mono_method (MonoClass *class)
9276 {
9277         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9278 }
9279
9280 static gboolean
9281 is_sr_mono_cmethod (MonoClass *class)
9282 {
9283         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9284 }
9285
9286 static gboolean
9287 is_sr_mono_generic_method (MonoClass *class)
9288 {
9289         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9290 }
9291
9292 static gboolean
9293 is_sr_mono_generic_cmethod (MonoClass *class)
9294 {
9295         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9296 }
9297
9298 gboolean
9299 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9300 {
9301         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9302 }
9303
9304 static gboolean
9305 is_usertype (MonoReflectionType *ref)
9306 {
9307         MonoClass *class = mono_object_class (ref);
9308         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9309 }
9310
9311 static MonoReflectionType*
9312 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9313 {
9314         if (!type || type->type)
9315                 return type;
9316
9317         if (is_usertype (type)) {
9318                 type = mono_reflection_type_get_underlying_system_type (type);
9319                 if (is_usertype (type))
9320                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9321         }
9322
9323         return type;
9324 }
9325 /*
9326  * Encode a value in a custom attribute stream of bytes.
9327  * The value to encode is either supplied as an object in argument val
9328  * (valuetypes are boxed), or as a pointer to the data in the
9329  * argument argval.
9330  * @type represents the type of the value
9331  * @buffer is the start of the buffer
9332  * @p the current position in the buffer
9333  * @buflen contains the size of the buffer and is used to return the new buffer size
9334  * if this needs to be realloced.
9335  * @retbuffer and @retp return the start and the position of the buffer
9336  */
9337 static void
9338 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9339 {
9340         MonoTypeEnum simple_type;
9341         
9342         if ((p-buffer) + 10 >= *buflen) {
9343                 char *newbuf;
9344                 *buflen *= 2;
9345                 newbuf = g_realloc (buffer, *buflen);
9346                 p = newbuf + (p-buffer);
9347                 buffer = newbuf;
9348         }
9349         if (!argval)
9350                 argval = ((char*)arg + sizeof (MonoObject));
9351         simple_type = type->type;
9352 handle_enum:
9353         switch (simple_type) {
9354         case MONO_TYPE_BOOLEAN:
9355         case MONO_TYPE_U1:
9356         case MONO_TYPE_I1:
9357                 *p++ = *argval;
9358                 break;
9359         case MONO_TYPE_CHAR:
9360         case MONO_TYPE_U2:
9361         case MONO_TYPE_I2:
9362                 swap_with_size (p, argval, 2, 1);
9363                 p += 2;
9364                 break;
9365         case MONO_TYPE_U4:
9366         case MONO_TYPE_I4:
9367         case MONO_TYPE_R4:
9368                 swap_with_size (p, argval, 4, 1);
9369                 p += 4;
9370                 break;
9371         case MONO_TYPE_R8:
9372 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9373                 p [0] = argval [4];
9374                 p [1] = argval [5];
9375                 p [2] = argval [6];
9376                 p [3] = argval [7];
9377                 p [4] = argval [0];
9378                 p [5] = argval [1];
9379                 p [6] = argval [2];
9380                 p [7] = argval [3];
9381 #else
9382                 swap_with_size (p, argval, 8, 1);
9383 #endif
9384                 p += 8;
9385                 break;
9386         case MONO_TYPE_U8:
9387         case MONO_TYPE_I8:
9388                 swap_with_size (p, argval, 8, 1);
9389                 p += 8;
9390                 break;
9391         case MONO_TYPE_VALUETYPE:
9392                 if (type->data.klass->enumtype) {
9393                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9394                         goto handle_enum;
9395                 } else {
9396                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9397                 }
9398                 break;
9399         case MONO_TYPE_STRING: {
9400                 char *str;
9401                 guint32 slen;
9402                 if (!arg) {
9403                         *p++ = 0xFF;
9404                         break;
9405                 }
9406                 str = mono_string_to_utf8 ((MonoString*)arg);
9407                 slen = strlen (str);
9408                 if ((p-buffer) + 10 + slen >= *buflen) {
9409                         char *newbuf;
9410                         *buflen *= 2;
9411                         *buflen += slen;
9412                         newbuf = g_realloc (buffer, *buflen);
9413                         p = newbuf + (p-buffer);
9414                         buffer = newbuf;
9415                 }
9416                 mono_metadata_encode_value (slen, p, &p);
9417                 memcpy (p, str, slen);
9418                 p += slen;
9419                 g_free (str);
9420                 break;
9421         }
9422         case MONO_TYPE_CLASS: {
9423                 char *str;
9424                 guint32 slen;
9425                 if (!arg) {
9426                         *p++ = 0xFF;
9427                         break;
9428                 }
9429 handle_type:
9430                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9431                 slen = strlen (str);
9432                 if ((p-buffer) + 10 + slen >= *buflen) {
9433                         char *newbuf;
9434                         *buflen *= 2;
9435                         *buflen += slen;
9436                         newbuf = g_realloc (buffer, *buflen);
9437                         p = newbuf + (p-buffer);
9438                         buffer = newbuf;
9439                 }
9440                 mono_metadata_encode_value (slen, p, &p);
9441                 memcpy (p, str, slen);
9442                 p += slen;
9443                 g_free (str);
9444                 break;
9445         }
9446         case MONO_TYPE_SZARRAY: {
9447                 int len, i;
9448                 MonoClass *eclass, *arg_eclass;
9449
9450                 if (!arg) {
9451                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9452                         break;
9453                 }
9454                 len = mono_array_length ((MonoArray*)arg);
9455                 *p++ = len & 0xff;
9456                 *p++ = (len >> 8) & 0xff;
9457                 *p++ = (len >> 16) & 0xff;
9458                 *p++ = (len >> 24) & 0xff;
9459                 *retp = p;
9460                 *retbuffer = buffer;
9461                 eclass = type->data.klass;
9462                 arg_eclass = mono_object_class (arg)->element_class;
9463
9464                 if (!eclass) {
9465                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9466                         eclass = mono_defaults.object_class;
9467                 }
9468                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9469                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9470                         int elsize = mono_class_array_element_size (arg_eclass);
9471                         for (i = 0; i < len; ++i) {
9472                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9473                                 elptr += elsize;
9474                         }
9475                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9476                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9477                         int elsize = mono_class_array_element_size (eclass);
9478                         for (i = 0; i < len; ++i) {
9479                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9480                                 elptr += elsize;
9481                         }
9482                 } else {
9483                         for (i = 0; i < len; ++i) {
9484                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9485                         }
9486                 }
9487                 break;
9488         }
9489         case MONO_TYPE_OBJECT: {
9490                 MonoClass *klass;
9491                 char *str;
9492                 guint32 slen;
9493
9494                 /*
9495                  * The parameter type is 'object' but the type of the actual
9496                  * argument is not. So we have to add type information to the blob
9497                  * too. This is completely undocumented in the spec.
9498                  */
9499
9500                 if (arg == NULL) {
9501                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9502                         *p++ = 0xFF;
9503                         break;
9504                 }
9505                 
9506                 klass = mono_object_class (arg);
9507
9508                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9509                         *p++ = 0x50;
9510                         goto handle_type;
9511                 } else if (klass->enumtype) {
9512                         *p++ = 0x55;
9513                 } else if (klass == mono_defaults.string_class) {
9514                         simple_type = MONO_TYPE_STRING;
9515                         *p++ = 0x0E;
9516                         goto handle_enum;
9517                 } else if (klass->rank == 1) {
9518                         *p++ = 0x1D;
9519                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9520                                 /* See Partition II, Appendix B3 */
9521                                 *p++ = 0x51;
9522                         else
9523                                 *p++ = klass->element_class->byval_arg.type;
9524                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9525                         break;
9526                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9527                         *p++ = simple_type = klass->byval_arg.type;
9528                         goto handle_enum;
9529                 } else {
9530                         g_error ("unhandled type in custom attr");
9531                 }
9532                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9533                 slen = strlen (str);
9534                 if ((p-buffer) + 10 + slen >= *buflen) {
9535                         char *newbuf;
9536                         *buflen *= 2;
9537                         *buflen += slen;
9538                         newbuf = g_realloc (buffer, *buflen);
9539                         p = newbuf + (p-buffer);
9540                         buffer = newbuf;
9541                 }
9542                 mono_metadata_encode_value (slen, p, &p);
9543                 memcpy (p, str, slen);
9544                 p += slen;
9545                 g_free (str);
9546                 simple_type = mono_class_enum_basetype (klass)->type;
9547                 goto handle_enum;
9548         }
9549         default:
9550                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9551         }
9552         *retp = p;
9553         *retbuffer = buffer;
9554 }
9555
9556 static void
9557 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9558 {
9559         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9560                 char *str = type_get_qualified_name (type, NULL);
9561                 int slen = strlen (str);
9562
9563                 *p++ = 0x55;
9564                 /*
9565                  * This seems to be optional...
9566                  * *p++ = 0x80;
9567                  */
9568                 mono_metadata_encode_value (slen, p, &p);
9569                 memcpy (p, str, slen);
9570                 p += slen;
9571                 g_free (str);
9572         } else if (type->type == MONO_TYPE_OBJECT) {
9573                 *p++ = 0x51;
9574         } else if (type->type == MONO_TYPE_CLASS) {
9575                 /* it should be a type: encode_cattr_value () has the check */
9576                 *p++ = 0x50;
9577         } else {
9578                 mono_metadata_encode_value (type->type, p, &p);
9579                 if (type->type == MONO_TYPE_SZARRAY)
9580                         /* See the examples in Partition VI, Annex B */
9581                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9582         }
9583
9584         *retp = p;
9585 }
9586
9587 #ifndef DISABLE_REFLECTION_EMIT
9588 static void
9589 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9590 {
9591         int len;
9592         /* Preallocate a large enough buffer */
9593         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9594                 char *str = type_get_qualified_name (type, NULL);
9595                 len = strlen (str);
9596                 g_free (str);
9597         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9598                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9599                 len = strlen (str);
9600                 g_free (str);
9601         } else {
9602                 len = 0;
9603         }
9604         len += strlen (name);
9605
9606         if ((p-buffer) + 20 + len >= *buflen) {
9607                 char *newbuf;
9608                 *buflen *= 2;
9609                 *buflen += len;
9610                 newbuf = g_realloc (buffer, *buflen);
9611                 p = newbuf + (p-buffer);
9612                 buffer = newbuf;
9613         }
9614
9615         encode_field_or_prop_type (type, p, &p);
9616
9617         len = strlen (name);
9618         mono_metadata_encode_value (len, p, &p);
9619         memcpy (p, name, len);
9620         p += len;
9621         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9622         *retp = p;
9623         *retbuffer = buffer;
9624 }
9625
9626 /*
9627  * mono_reflection_get_custom_attrs_blob:
9628  * @ctor: custom attribute constructor
9629  * @ctorArgs: arguments o the constructor
9630  * @properties:
9631  * @propValues:
9632  * @fields:
9633  * @fieldValues:
9634  * 
9635  * Creates the blob of data that needs to be saved in the metadata and that represents
9636  * the custom attributed described by @ctor, @ctorArgs etc.
9637  * Returns: a Byte array representing the blob of data.
9638  */
9639 MonoArray*
9640 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
9641 {
9642         MonoArray *result;
9643         MonoMethodSignature *sig;
9644         MonoObject *arg;
9645         char *buffer, *p;
9646         guint32 buflen, i;
9647
9648         MONO_ARCH_SAVE_REGS;
9649
9650         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9651                 /* sig is freed later so allocate it in the heap */
9652                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9653         } else {
9654                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9655         }
9656
9657         g_assert (mono_array_length (ctorArgs) == sig->param_count);
9658         buflen = 256;
9659         p = buffer = g_malloc (buflen);
9660         /* write the prolog */
9661         *p++ = 1;
9662         *p++ = 0;
9663         for (i = 0; i < sig->param_count; ++i) {
9664                 arg = mono_array_get (ctorArgs, MonoObject*, i);
9665                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9666         }
9667         i = 0;
9668         if (properties)
9669                 i += mono_array_length (properties);
9670         if (fields)
9671                 i += mono_array_length (fields);
9672         *p++ = i & 0xff;
9673         *p++ = (i >> 8) & 0xff;
9674         if (properties) {
9675                 MonoObject *prop;
9676                 for (i = 0; i < mono_array_length (properties); ++i) {
9677                         MonoType *ptype;
9678                         char *pname;
9679
9680                         prop = mono_array_get (properties, gpointer, i);
9681                         get_prop_name_and_type (prop, &pname, &ptype);
9682                         *p++ = 0x54; /* PROPERTY signature */
9683                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9684                         g_free (pname);
9685                 }
9686         }
9687
9688         if (fields) {
9689                 MonoObject *field;
9690                 for (i = 0; i < mono_array_length (fields); ++i) {
9691                         MonoType *ftype;
9692                         char *fname;
9693
9694                         field = mono_array_get (fields, gpointer, i);
9695                         get_field_name_and_type (field, &fname, &ftype);
9696                         *p++ = 0x53; /* FIELD signature */
9697                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9698                         g_free (fname);
9699                 }
9700         }
9701
9702         g_assert (p - buffer <= buflen);
9703         buflen = p - buffer;
9704         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9705         p = mono_array_addr (result, char, 0);
9706         memcpy (p, buffer, buflen);
9707         g_free (buffer);
9708         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9709                 g_free (sig);
9710         return result;
9711 }
9712
9713 /*
9714  * mono_reflection_setup_internal_class:
9715  * @tb: a TypeBuilder object
9716  *
9717  * Creates a MonoClass that represents the TypeBuilder.
9718  * This is a trick that lets us simplify a lot of reflection code
9719  * (and will allow us to support Build and Run assemblies easier).
9720  */
9721 void
9722 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9723 {
9724         MonoError error;
9725         MonoClass *klass, *parent;
9726
9727         MONO_ARCH_SAVE_REGS;
9728
9729         RESOLVE_TYPE (tb->parent);
9730
9731         mono_loader_lock ();
9732
9733         if (tb->parent) {
9734                 /* check so we can compile corlib correctly */
9735                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9736                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9737                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9738                 } else {
9739                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9740                 }
9741         } else {
9742                 parent = NULL;
9743         }
9744         
9745         /* the type has already being created: it means we just have to change the parent */
9746         if (tb->type.type) {
9747                 klass = mono_class_from_mono_type (tb->type.type);
9748                 klass->parent = NULL;
9749                 /* fool mono_class_setup_parent */
9750                 klass->supertypes = NULL;
9751                 mono_class_setup_parent (klass, parent);
9752                 mono_class_setup_mono_type (klass);
9753                 mono_loader_unlock ();
9754                 return;
9755         }
9756
9757         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9758
9759         klass->image = &tb->module->dynamic_image->image;
9760
9761         klass->inited = 1; /* we lie to the runtime */
9762         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9763         if (!mono_error_ok (&error))
9764                 goto failure;
9765         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9766         if (!mono_error_ok (&error))
9767                 goto failure;
9768         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9769         klass->flags = tb->attrs;
9770         
9771         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9772
9773         klass->element_class = klass;
9774
9775         if (mono_class_get_ref_info (klass) == NULL) {
9776
9777                 mono_class_set_ref_info (klass, tb);
9778
9779                 /* Put into cache so mono_class_get () will find it.
9780                 Skip nested types as those should not be available on the global scope. */
9781                 if (!tb->nesting_type) {
9782                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9783                 } else {
9784                         klass->image->reflection_info_unregister_classes =
9785                                 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9786                 }
9787         } else {
9788                 g_assert (mono_class_get_ref_info (klass) == tb);
9789         }
9790
9791         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9792                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9793
9794         if (parent != NULL) {
9795                 mono_class_setup_parent (klass, parent);
9796         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9797                 const char *old_n = klass->name;
9798                 /* trick to get relative numbering right when compiling corlib */
9799                 klass->name = "BuildingObject";
9800                 mono_class_setup_parent (klass, mono_defaults.object_class);
9801                 klass->name = old_n;
9802         }
9803
9804         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9805                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9806                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9807                 klass->instance_size = sizeof (MonoObject);
9808                 klass->size_inited = 1;
9809                 mono_class_setup_vtable_general (klass, NULL, 0);
9810         }
9811
9812         mono_class_setup_mono_type (klass);
9813
9814         mono_class_setup_supertypes (klass);
9815
9816         /*
9817          * FIXME: handle interfaces.
9818          */
9819
9820         tb->type.type = &klass->byval_arg;
9821
9822         if (tb->nesting_type) {
9823                 g_assert (tb->nesting_type->type);
9824                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9825         }
9826
9827         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9828
9829         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9830         
9831         mono_loader_unlock ();
9832         return;
9833
9834 failure:
9835         mono_loader_unlock ();
9836         mono_error_raise_exception (&error);
9837 }
9838
9839 /*
9840  * mono_reflection_setup_generic_class:
9841  * @tb: a TypeBuilder object
9842  *
9843  * Setup the generic class before adding the first generic parameter.
9844  */
9845 void
9846 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9847 {
9848 }
9849
9850 /*
9851  * mono_reflection_create_generic_class:
9852  * @tb: a TypeBuilder object
9853  *
9854  * Creates the generic class after all generic parameters have been added.
9855  */
9856 void
9857 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9858 {
9859         MonoClass *klass;
9860         int count, i;
9861
9862         MONO_ARCH_SAVE_REGS;
9863
9864         klass = mono_class_from_mono_type (tb->type.type);
9865
9866         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9867
9868         if (klass->generic_container || (count == 0))
9869                 return;
9870
9871         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9872
9873         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9874
9875         klass->generic_container->owner.klass = klass;
9876         klass->generic_container->type_argc = count;
9877         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9878
9879         klass->is_generic = 1;
9880
9881         for (i = 0; i < count; i++) {
9882                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9883                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9884                 klass->generic_container->type_params [i] = *param;
9885                 /*Make sure we are a diferent type instance */
9886                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9887                 klass->generic_container->type_params [i].info.pklass = NULL;
9888                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9889
9890                 g_assert (klass->generic_container->type_params [i].param.owner);
9891         }
9892
9893         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9894 }
9895
9896 /*
9897  * mono_reflection_create_internal_class:
9898  * @tb: a TypeBuilder object
9899  *
9900  * Actually create the MonoClass that is associated with the TypeBuilder.
9901  */
9902 void
9903 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9904 {
9905         MonoClass *klass;
9906
9907         MONO_ARCH_SAVE_REGS;
9908
9909         klass = mono_class_from_mono_type (tb->type.type);
9910
9911         mono_loader_lock ();
9912         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9913                 MonoReflectionFieldBuilder *fb;
9914                 MonoClass *ec;
9915                 MonoType *enum_basetype;
9916
9917                 g_assert (tb->fields != NULL);
9918                 g_assert (mono_array_length (tb->fields) >= 1);
9919
9920                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9921
9922                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9923                         mono_loader_unlock ();
9924                         return;
9925                 }
9926
9927                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9928                 klass->element_class = mono_class_from_mono_type (enum_basetype);
9929                 if (!klass->element_class)
9930                         klass->element_class = mono_class_from_mono_type (enum_basetype);
9931
9932                 /*
9933                  * get the element_class from the current corlib.
9934                  */
9935                 ec = default_class_from_mono_type (enum_basetype);
9936                 klass->instance_size = ec->instance_size;
9937                 klass->size_inited = 1;
9938                 /* 
9939                  * this is almost safe to do with enums and it's needed to be able
9940                  * to create objects of the enum type (for use in SetConstant).
9941                  */
9942                 /* FIXME: Does this mean enums can't have method overrides ? */
9943                 mono_class_setup_vtable_general (klass, NULL, 0);
9944         }
9945         mono_loader_unlock ();
9946 }
9947
9948 static MonoMarshalSpec*
9949 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9950                                                                 MonoReflectionMarshal *minfo)
9951 {
9952         MonoMarshalSpec *res;
9953
9954         res = image_g_new0 (image, MonoMarshalSpec, 1);
9955         res->native = minfo->type;
9956
9957         switch (minfo->type) {
9958         case MONO_NATIVE_LPARRAY:
9959                 res->data.array_data.elem_type = minfo->eltype;
9960                 if (minfo->has_size) {
9961                         res->data.array_data.param_num = minfo->param_num;
9962                         res->data.array_data.num_elem = minfo->count;
9963                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9964                 }
9965                 else {
9966                         res->data.array_data.param_num = -1;
9967                         res->data.array_data.num_elem = -1;
9968                         res->data.array_data.elem_mult = -1;
9969                 }
9970                 break;
9971
9972         case MONO_NATIVE_BYVALTSTR:
9973         case MONO_NATIVE_BYVALARRAY:
9974                 res->data.array_data.num_elem = minfo->count;
9975                 break;
9976
9977         case MONO_NATIVE_CUSTOM:
9978                 if (minfo->marshaltyperef)
9979                         res->data.custom_data.custom_name =
9980                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9981                 if (minfo->mcookie)
9982                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9983                 break;
9984
9985         default:
9986                 break;
9987         }
9988
9989         return res;
9990 }
9991 #endif /* !DISABLE_REFLECTION_EMIT */
9992
9993 MonoReflectionMarshal*
9994 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9995                                                                                    MonoMarshalSpec *spec)
9996 {
9997         static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9998         MonoReflectionMarshal *minfo;
9999         MonoType *mtype;
10000
10001         if (!System_Reflection_Emit_UnmanagedMarshalClass) {
10002                 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
10003                    mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
10004                 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
10005         }
10006
10007         minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
10008         minfo->type = spec->native;
10009
10010         switch (minfo->type) {
10011         case MONO_NATIVE_LPARRAY:
10012                 minfo->eltype = spec->data.array_data.elem_type;
10013                 minfo->count = spec->data.array_data.num_elem;
10014                 minfo->param_num = spec->data.array_data.param_num;
10015                 break;
10016
10017         case MONO_NATIVE_BYVALTSTR:
10018         case MONO_NATIVE_BYVALARRAY:
10019                 minfo->count = spec->data.array_data.num_elem;
10020                 break;
10021
10022         case MONO_NATIVE_CUSTOM:
10023                 if (spec->data.custom_data.custom_name) {
10024                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10025                         if (mtype)
10026                                 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10027
10028                         MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10029                 }
10030                 if (spec->data.custom_data.cookie)
10031                         MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10032                 break;
10033
10034         default:
10035                 break;
10036         }
10037
10038         return minfo;
10039 }
10040
10041 #ifndef DISABLE_REFLECTION_EMIT
10042 static MonoMethod*
10043 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10044                                          ReflectionMethodBuilder *rmb,
10045                                          MonoMethodSignature *sig)
10046 {
10047         MonoError error;
10048         MonoMethod *m;
10049         MonoMethodWrapper *wrapperm;
10050         MonoMarshalSpec **specs;
10051         MonoReflectionMethodAux *method_aux;
10052         MonoImage *image;
10053         gboolean dynamic;
10054         int i;
10055
10056         mono_error_init (&error);
10057         /*
10058          * Methods created using a MethodBuilder should have their memory allocated
10059          * inside the image mempool, while dynamic methods should have their memory
10060          * malloc'd.
10061          */
10062         dynamic = rmb->refs != NULL;
10063         image = dynamic ? NULL : klass->image;
10064
10065         if (!dynamic)
10066                 g_assert (!klass->generic_class);
10067
10068         mono_loader_lock ();
10069
10070         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10071                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10072                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10073         else
10074                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10075
10076         wrapperm = (MonoMethodWrapper*)m;
10077
10078         m->dynamic = dynamic;
10079         m->slot = -1;
10080         m->flags = rmb->attrs;
10081         m->iflags = rmb->iattrs;
10082         m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10083         g_assert (mono_error_ok (&error));
10084         m->klass = klass;
10085         m->signature = sig;
10086         m->sre_method = TRUE;
10087         m->skip_visibility = rmb->skip_visibility;
10088         if (rmb->table_idx)
10089                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10090
10091         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10092                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10093                         m->string_ctor = 1;
10094
10095                 m->signature->pinvoke = 1;
10096         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10097                 m->signature->pinvoke = 1;
10098
10099                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10100
10101                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10102                 g_assert (mono_error_ok (&error));
10103                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10104                 g_assert (mono_error_ok (&error));
10105                 
10106                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10107
10108                 if (klass->image->dynamic)
10109                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10110
10111                 mono_loader_unlock ();
10112
10113                 return m;
10114         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10115                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10116                 MonoMethodHeader *header;
10117                 guint32 code_size;
10118                 gint32 max_stack, i;
10119                 gint32 num_locals = 0;
10120                 gint32 num_clauses = 0;
10121                 guint8 *code;
10122
10123                 if (rmb->ilgen) {
10124                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10125                         code_size = rmb->ilgen->code_len;
10126                         max_stack = rmb->ilgen->max_stack;
10127                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10128                         if (rmb->ilgen->ex_handlers)
10129                                 num_clauses = method_count_clauses (rmb->ilgen);
10130                 } else {
10131                         if (rmb->code) {
10132                                 code = mono_array_addr (rmb->code, guint8, 0);
10133                                 code_size = mono_array_length (rmb->code);
10134                                 /* we probably need to run a verifier on the code... */
10135                                 max_stack = 8; 
10136                         }
10137                         else {
10138                                 code = NULL;
10139                                 code_size = 0;
10140                                 max_stack = 8;
10141                         }
10142                 }
10143
10144                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10145                 header->code_size = code_size;
10146                 header->code = image_g_malloc (image, code_size);
10147                 memcpy ((char*)header->code, code, code_size);
10148                 header->max_stack = max_stack;
10149                 header->init_locals = rmb->init_locals;
10150                 header->num_locals = num_locals;
10151
10152                 for (i = 0; i < num_locals; ++i) {
10153                         MonoReflectionLocalBuilder *lb = 
10154                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10155
10156                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10157                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10158                 }
10159
10160                 header->num_clauses = num_clauses;
10161                 if (num_clauses) {
10162                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10163                                  rmb->ilgen, num_clauses);
10164                 }
10165
10166                 wrapperm->header = header;
10167         }
10168
10169         if (rmb->generic_params) {
10170                 int count = mono_array_length (rmb->generic_params);
10171                 MonoGenericContainer *container = rmb->generic_container;
10172
10173                 g_assert (container);
10174
10175                 container->type_argc = count;
10176                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10177                 container->owner.method = m;
10178
10179                 m->is_generic = TRUE;
10180                 mono_method_set_generic_container (m, container);
10181
10182                 for (i = 0; i < count; i++) {
10183                         MonoReflectionGenericParam *gp =
10184                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10185                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10186                         container->type_params [i] = *param;
10187                 }
10188
10189                 if (klass->generic_container) {
10190                         container->parent = klass->generic_container;
10191                         container->context.class_inst = klass->generic_container->context.class_inst;
10192                 }
10193                 container->context.method_inst = mono_get_shared_generic_inst (container);
10194         }
10195
10196         if (rmb->refs) {
10197                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10198                 int i;
10199                 void **data;
10200
10201                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10202
10203                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10204                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10205                 for (i = 0; i < rmb->nrefs; ++i)
10206                         data [i + 1] = rmb->refs [i];
10207         }
10208
10209         method_aux = NULL;
10210
10211         /* Parameter info */
10212         if (rmb->pinfo) {
10213                 if (!method_aux)
10214                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10215                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10216                 for (i = 0; i <= m->signature->param_count; ++i) {
10217                         MonoReflectionParamBuilder *pb;
10218                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10219                                 if ((i > 0) && (pb->attrs)) {
10220                                         /* Make a copy since it might point to a shared type structure */
10221                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10222                                         m->signature->params [i - 1]->attrs = pb->attrs;
10223                                 }
10224
10225                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10226                                         MonoDynamicImage *assembly;
10227                                         guint32 idx, def_type, len;
10228                                         char *p;
10229                                         const char *p2;
10230
10231                                         if (!method_aux->param_defaults) {
10232                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10233                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10234                                         }
10235                                         assembly = (MonoDynamicImage*)klass->image;
10236                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10237                                         /* Copy the data from the blob since it might get realloc-ed */
10238                                         p = assembly->blob.data + idx;
10239                                         len = mono_metadata_decode_blob_size (p, &p2);
10240                                         len += p2 - p;
10241                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10242                                         method_aux->param_default_types [i] = def_type;
10243                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10244                                 }
10245
10246                                 if (pb->name) {
10247                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10248                                         g_assert (mono_error_ok (&error));
10249                                 }
10250                                 if (pb->cattrs) {
10251                                         if (!method_aux->param_cattr)
10252                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10253                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10254                                 }
10255                         }
10256                 }
10257         }
10258
10259         /* Parameter marshalling */
10260         specs = NULL;
10261         if (rmb->pinfo)         
10262                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10263                         MonoReflectionParamBuilder *pb;
10264                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10265                                 if (pb->marshal_info) {
10266                                         if (specs == NULL)
10267                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10268                                         specs [pb->position] = 
10269                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10270                                 }
10271                         }
10272                 }
10273         if (specs != NULL) {
10274                 if (!method_aux)
10275                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10276                 method_aux->param_marshall = specs;
10277         }
10278
10279         if (klass->image->dynamic && method_aux)
10280                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10281
10282         mono_loader_unlock ();
10283
10284         return m;
10285 }       
10286
10287 static MonoMethod*
10288 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10289 {
10290         ReflectionMethodBuilder rmb;
10291         MonoMethodSignature *sig;
10292
10293         mono_loader_lock ();
10294         sig = ctor_builder_to_signature (klass->image, mb);
10295         mono_loader_unlock ();
10296
10297         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10298
10299         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10300         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10301
10302         /* If we are in a generic class, we might be called multiple times from inflate_method */
10303         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10304                 /* ilgen is no longer needed */
10305                 mb->ilgen = NULL;
10306         }
10307
10308         return mb->mhandle;
10309 }
10310
10311 static MonoMethod*
10312 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10313 {
10314         ReflectionMethodBuilder rmb;
10315         MonoMethodSignature *sig;
10316
10317         mono_loader_lock ();
10318         sig = method_builder_to_signature (klass->image, mb);
10319         mono_loader_unlock ();
10320
10321         reflection_methodbuilder_from_method_builder (&rmb, mb);
10322
10323         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10324         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10325
10326         /* If we are in a generic class, we might be called multiple times from inflate_method */
10327         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10328                 /* ilgen is no longer needed */
10329                 mb->ilgen = NULL;
10330         }
10331         return mb->mhandle;
10332 }
10333
10334 static MonoClassField*
10335 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10336 {
10337         MonoClassField *field;
10338         MonoType *custom;
10339
10340         field = g_new0 (MonoClassField, 1);
10341
10342         field->name = mono_string_to_utf8 (fb->name);
10343         if (fb->attrs || fb->modreq || fb->modopt) {
10344                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10345                 field->type->attrs = fb->attrs;
10346
10347                 g_assert (klass->image->dynamic);
10348                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10349                 g_free (field->type);
10350                 field->type = custom;
10351         } else {
10352                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10353         }
10354         if (fb->offset != -1)
10355                 field->offset = fb->offset;
10356         field->parent = klass;
10357         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10358
10359         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10360
10361         return field;
10362 }
10363 #endif
10364
10365 MonoType*
10366 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10367 {
10368         MonoClass *klass;
10369         MonoReflectionTypeBuilder *tb = NULL;
10370         gboolean is_dynamic = FALSE;
10371         MonoDomain *domain;
10372         MonoClass *geninst;
10373
10374         mono_loader_lock ();
10375
10376         domain = mono_object_domain (type);
10377
10378         if (is_sre_type_builder (mono_object_class (type))) {
10379                 tb = (MonoReflectionTypeBuilder *) type;
10380
10381                 is_dynamic = TRUE;
10382         } else if (is_sre_generic_instance (mono_object_class (type))) {
10383                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10384                 MonoReflectionType *gtd = rgi->generic_type;
10385
10386                 if (is_sre_type_builder (mono_object_class (gtd))) {
10387                         tb = (MonoReflectionTypeBuilder *)gtd;
10388                         is_dynamic = TRUE;
10389                 }
10390         }
10391
10392         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10393         if (tb && tb->generic_container)
10394                 mono_reflection_create_generic_class (tb);
10395
10396         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10397         if (!klass->generic_container) {
10398                 mono_loader_unlock ();
10399                 return NULL;
10400         }
10401
10402         if (klass->wastypebuilder) {
10403                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10404
10405                 is_dynamic = TRUE;
10406         }
10407
10408         mono_loader_unlock ();
10409
10410         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10411
10412         return &geninst->byval_arg;
10413 }
10414
10415 MonoClass*
10416 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10417 {
10418         MonoGenericClass *gclass;
10419         MonoGenericInst *inst;
10420
10421         g_assert (klass->generic_container);
10422
10423         inst = mono_metadata_get_generic_inst (type_argc, types);
10424         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10425
10426         return mono_generic_class_get_class (gclass);
10427 }
10428
10429 MonoReflectionMethod*
10430 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10431 {
10432         MonoClass *klass;
10433         MonoMethod *method, *inflated;
10434         MonoMethodInflated *imethod;
10435         MonoGenericContext tmp_context;
10436         MonoGenericInst *ginst;
10437         MonoType **type_argv;
10438         int count, i;
10439
10440         MONO_ARCH_SAVE_REGS;
10441
10442         /*FIXME but this no longer should happen*/
10443         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10444 #ifndef DISABLE_REFLECTION_EMIT
10445                 MonoReflectionMethodBuilder *mb = NULL;
10446                 MonoReflectionTypeBuilder *tb;
10447                 MonoClass *klass;
10448
10449                 mb = (MonoReflectionMethodBuilder *) rmethod;
10450                 tb = (MonoReflectionTypeBuilder *) mb->type;
10451                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10452
10453                 method = methodbuilder_to_mono_method (klass, mb);
10454 #else
10455                 g_assert_not_reached ();
10456                 method = NULL;
10457 #endif
10458         } else {
10459                 method = rmethod->method;
10460         }
10461
10462         klass = method->klass;
10463
10464         if (method->is_inflated)
10465                 method = ((MonoMethodInflated *) method)->declaring;
10466
10467         count = mono_method_signature (method)->generic_param_count;
10468         if (count != mono_array_length (types))
10469                 return NULL;
10470
10471         type_argv = g_new0 (MonoType *, count);
10472         for (i = 0; i < count; i++) {
10473                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10474                 type_argv [i] = mono_reflection_type_get_handle (garg);
10475         }
10476         ginst = mono_metadata_get_generic_inst (count, type_argv);
10477         g_free (type_argv);
10478
10479         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10480         tmp_context.method_inst = ginst;
10481
10482         inflated = mono_class_inflate_generic_method (method, &tmp_context);
10483         imethod = (MonoMethodInflated *) inflated;
10484
10485         /*FIXME but I think this is no longer necessary*/
10486         if (method->klass->image->dynamic) {
10487                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10488                 /*
10489                  * This table maps metadata structures representing inflated methods/fields
10490                  * to the reflection objects representing their generic definitions.
10491                  */
10492                 mono_loader_lock ();
10493                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10494                 mono_loader_unlock ();
10495         }
10496         
10497         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10498 }
10499
10500 #ifndef DISABLE_REFLECTION_EMIT
10501
10502 static MonoMethod *
10503 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10504 {
10505         MonoMethodInflated *imethod;
10506         MonoGenericContext *context;
10507         int i;
10508
10509         /*
10510          * With generic code sharing the klass might not be inflated.
10511          * This can happen because classes inflated with their own
10512          * type arguments are "normalized" to the uninflated class.
10513          */
10514         if (!klass->generic_class)
10515                 return method;
10516
10517         context = mono_class_get_context (klass);
10518
10519         if (klass->method.count && klass->methods) {
10520                 /* Find the already created inflated method */
10521                 for (i = 0; i < klass->method.count; ++i) {
10522                         g_assert (klass->methods [i]->is_inflated);
10523                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10524                                 break;
10525                 }
10526                 g_assert (i < klass->method.count);
10527                 imethod = (MonoMethodInflated*)klass->methods [i];
10528         } else {
10529                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10530         }
10531
10532         if (method->is_generic && method->klass->image->dynamic) {
10533                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10534
10535                 mono_loader_lock ();
10536                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10537                 mono_loader_unlock ();
10538         }
10539         return (MonoMethod *) imethod;
10540 }
10541
10542 static MonoMethod *
10543 inflate_method (MonoReflectionType *type, MonoObject *obj)
10544 {
10545         MonoMethod *method;
10546         MonoClass *gklass;
10547
10548         MonoClass *type_class = mono_object_class (type);
10549
10550         if (is_sre_generic_instance (type_class)) {
10551                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10552                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10553         } else if (is_sre_type_builder (type_class)) {
10554                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10555         } else if (type->type) {
10556                 gklass = mono_class_from_mono_type (type->type);
10557                 gklass = mono_class_get_generic_type_definition (gklass);
10558         } else {
10559                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10560         }
10561
10562         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10563                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10564                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10565                 else
10566                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10567         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10568                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10569         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10570                 method = ((MonoReflectionMethod *) obj)->method;
10571         else {
10572                 method = NULL; /* prevent compiler warning */
10573                 g_error ("can't handle type %s", obj->vtable->klass->name);
10574         }
10575
10576         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10577 }
10578
10579 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10580 void
10581 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
10582                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10583                                           MonoArray *events)
10584 {
10585         MonoGenericClass *gclass;
10586         MonoDynamicGenericClass *dgclass;
10587         MonoClass *klass, *gklass;
10588         MonoType *gtype;
10589         int i;
10590
10591         MONO_ARCH_SAVE_REGS;
10592
10593         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10594         klass = mono_class_from_mono_type (gtype);
10595         g_assert (gtype->type == MONO_TYPE_GENERICINST);
10596         gclass = gtype->data.generic_class;
10597
10598         if (!gclass->is_dynamic)
10599                 return;
10600
10601         dgclass = (MonoDynamicGenericClass *) gclass;
10602
10603         if (dgclass->initialized)
10604                 return;
10605
10606         gklass = gclass->container_class;
10607         mono_class_init (gklass);
10608
10609         dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10610         dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10611         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10612
10613         dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10614         dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10615         dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10616         dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10617         dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10618
10619         for (i = 0; i < dgclass->count_methods; i++) {
10620                 MonoObject *obj = mono_array_get (methods, gpointer, i);
10621
10622                 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10623         }
10624
10625         for (i = 0; i < dgclass->count_ctors; i++) {
10626                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10627
10628                 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10629         }
10630
10631         for (i = 0; i < dgclass->count_fields; i++) {
10632                 MonoObject *obj = mono_array_get (fields, gpointer, i);
10633                 MonoClassField *field, *inflated_field = NULL;
10634
10635                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10636                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10637                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10638                         field = ((MonoReflectionField *) obj)->field;
10639                 else {
10640                         field = NULL; /* prevent compiler warning */
10641                         g_assert_not_reached ();
10642                 }
10643
10644                 dgclass->fields [i] = *field;
10645                 dgclass->fields [i].parent = klass;
10646                 dgclass->fields [i].type = mono_class_inflate_generic_type (
10647                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10648                 dgclass->field_generic_types [i] = field->type;
10649                 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10650                 dgclass->field_objects [i] = obj;
10651
10652                 if (inflated_field) {
10653                         g_free (inflated_field);
10654                 } else {
10655                         dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10656                 }
10657         }
10658
10659         dgclass->initialized = TRUE;
10660 }
10661
10662 static void
10663 fix_partial_generic_class (MonoClass *klass)
10664 {
10665         MonoClass *gklass = klass->generic_class->container_class;
10666         MonoDynamicGenericClass *dgclass;
10667         int i;
10668
10669         if (klass->wastypebuilder)
10670                 return;
10671
10672         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
10673         if (klass->parent != gklass->parent) {
10674                 MonoError error;
10675                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10676                 if (mono_error_ok (&error)) {
10677                         MonoClass *parent = mono_class_from_mono_type (parent_type);
10678                         mono_metadata_free_type (parent_type);
10679                         if (parent != klass->parent) {
10680                                 /*fool mono_class_setup_parent*/
10681                                 klass->supertypes = NULL;
10682                                 mono_class_setup_parent (klass, parent);
10683                         }
10684                 } else {
10685                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10686                         mono_error_cleanup (&error);
10687                         if (gklass->wastypebuilder)
10688                                 klass->wastypebuilder = TRUE;
10689                         return;
10690                 }
10691         }
10692
10693         if (!dgclass->initialized)
10694                 return;
10695
10696         if (klass->method.count != gklass->method.count) {
10697                 klass->method.count = gklass->method.count;
10698                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10699
10700                 for (i = 0; i < klass->method.count; i++) {
10701                         klass->methods [i] = mono_class_inflate_generic_method_full (
10702                                 gklass->methods [i], klass, mono_class_get_context (klass));
10703                 }
10704         }
10705
10706         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10707                 klass->interface_count = gklass->interface_count;
10708                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10709                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10710
10711                 for (i = 0; i < gklass->interface_count; ++i) {
10712                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10713                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10714                         mono_metadata_free_type (iface_type);
10715
10716                         ensure_runtime_vtable (klass->interfaces [i]);
10717                 }
10718                 klass->interfaces_inited = 1;
10719         }
10720
10721         if (klass->field.count != gklass->field.count) {
10722                 klass->field.count = gklass->field.count;
10723                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10724
10725                 for (i = 0; i < klass->field.count; i++) {
10726                         klass->fields [i] = gklass->fields [i];
10727                         klass->fields [i].parent = klass;
10728                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10729                 }
10730         }
10731
10732         /*We can only finish with this klass once it's parent has as well*/
10733         if (gklass->wastypebuilder)
10734                 klass->wastypebuilder = TRUE;
10735         return;
10736 }
10737
10738 static void
10739 ensure_generic_class_runtime_vtable (MonoClass *klass)
10740 {
10741         MonoClass *gklass = klass->generic_class->container_class;
10742
10743         ensure_runtime_vtable (gklass); 
10744
10745         fix_partial_generic_class (klass);
10746 }
10747
10748 static void
10749 ensure_runtime_vtable (MonoClass *klass)
10750 {
10751         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10752         int i, num, j;
10753
10754         if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10755                 return;
10756         if (klass->parent)
10757                 ensure_runtime_vtable (klass->parent);
10758
10759         if (tb) {
10760                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10761                 num += tb->num_methods;
10762                 klass->method.count = num;
10763                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10764                 num = tb->ctors? mono_array_length (tb->ctors): 0;
10765                 for (i = 0; i < num; ++i)
10766                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10767                 num = tb->num_methods;
10768                 j = i;
10769                 for (i = 0; i < num; ++i)
10770                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10771         
10772                 if (tb->interfaces) {
10773                         klass->interface_count = mono_array_length (tb->interfaces);
10774                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10775                         for (i = 0; i < klass->interface_count; ++i) {
10776                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10777                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
10778                                 ensure_runtime_vtable (klass->interfaces [i]);
10779                         }
10780                         klass->interfaces_inited = 1;
10781                 }
10782         } else if (klass->generic_class){
10783                 ensure_generic_class_runtime_vtable (klass);
10784         }
10785
10786         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10787                 for (i = 0; i < klass->method.count; ++i)
10788                         klass->methods [i]->slot = i;
10789                 
10790                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10791                 mono_class_setup_interface_offsets (klass);
10792                 mono_class_setup_interface_id (klass);
10793         }
10794
10795         /*
10796          * The generic vtable is needed even if image->run is not set since some
10797          * runtime code like ves_icall_Type_GetMethodsByName depends on 
10798          * method->slot being defined.
10799          */
10800
10801         /* 
10802          * tb->methods could not be freed since it is used for determining 
10803          * overrides during dynamic vtable construction.
10804          */
10805 }
10806
10807 static MonoMethod*
10808 mono_reflection_method_get_handle (MonoObject *method)
10809 {
10810         MonoClass *class = mono_object_class (method);
10811         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10812                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10813                 return sr_method->method;
10814         }
10815         if (is_sre_method_builder (class)) {
10816                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10817                 return mb->mhandle;
10818         }
10819         if (is_sre_method_on_tb_inst (class)) {
10820                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10821                 MonoMethod *result;
10822                 /*FIXME move this to a proper method and unify with resolve_object*/
10823                 if (m->method_args) {
10824                         result = mono_reflection_method_on_tb_inst_get_handle (m);
10825                 } else {
10826                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10827                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
10828                         MonoMethod *mono_method;
10829
10830                         if (is_sre_method_builder (mono_object_class (m->mb)))
10831                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10832                         else if (is_sr_mono_method (mono_object_class (m->mb)))
10833                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10834                         else
10835                                 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)));
10836
10837                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10838                 }
10839                 return result;
10840         }
10841
10842         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10843         return NULL;
10844 }
10845
10846 void
10847 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10848 {
10849         MonoReflectionTypeBuilder *tb;
10850         int i, onum;
10851
10852         *overrides = NULL;
10853         *num_overrides = 0;
10854
10855         g_assert (klass->image->dynamic);
10856
10857         if (!mono_class_get_ref_info (klass))
10858                 return;
10859
10860         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10861
10862         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10863
10864         onum = 0;
10865         if (tb->methods) {
10866                 for (i = 0; i < tb->num_methods; ++i) {
10867                         MonoReflectionMethodBuilder *mb = 
10868                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10869                         if (mb->override_method)
10870                                 onum ++;
10871                 }
10872         }
10873
10874         if (onum) {
10875                 *overrides = g_new0 (MonoMethod*, onum * 2);
10876
10877                 onum = 0;
10878                 for (i = 0; i < tb->num_methods; ++i) {
10879                         MonoReflectionMethodBuilder *mb = 
10880                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10881                         if (mb->override_method) {
10882                                 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10883                                 (*overrides) [onum * 2 + 1] = mb->mhandle;
10884
10885                                 g_assert (mb->mhandle);
10886
10887                                 onum ++;
10888                         }
10889                 }
10890         }
10891
10892         *num_overrides = onum;
10893 }
10894
10895 static void
10896 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10897 {
10898         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10899         MonoReflectionFieldBuilder *fb;
10900         MonoClassField *field;
10901         MonoImage *image = klass->image;
10902         const char *p, *p2;
10903         int i;
10904         guint32 len, idx, real_size = 0;
10905
10906         klass->field.count = tb->num_fields;
10907         klass->field.first = 0;
10908
10909         mono_error_init (error);
10910
10911         if (tb->class_size) {
10912                 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10913                 klass->packing_size = tb->packing_size;
10914                 real_size = klass->instance_size + tb->class_size;
10915         }
10916
10917         if (!klass->field.count) {
10918                 klass->instance_size = MAX (klass->instance_size, real_size);
10919                 return;
10920         }
10921         
10922         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10923         mono_class_alloc_ext (klass);
10924         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10925         /*
10926         This is, guess what, a hack.
10927         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10928         On the static path no field class is resolved, only types are built. This is the right thing to do
10929         but we suck.
10930         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10931         */
10932         klass->size_inited = 1;
10933
10934         for (i = 0; i < klass->field.count; ++i) {
10935                 fb = mono_array_get (tb->fields, gpointer, i);
10936                 field = &klass->fields [i];
10937                 field->name = mono_string_to_utf8_image (image, fb->name, error);
10938                 if (!mono_error_ok (error))
10939                         return;
10940                 if (fb->attrs) {
10941                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10942                         field->type->attrs = fb->attrs;
10943                 } else {
10944                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10945                 }
10946                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10947                         klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10948                 if (fb->offset != -1)
10949                         field->offset = fb->offset;
10950                 field->parent = klass;
10951                 fb->handle = field;
10952                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10953
10954                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10955                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10956                 }
10957                 if (fb->def_value) {
10958                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10959                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10960                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10961                         /* Copy the data from the blob since it might get realloc-ed */
10962                         p = assembly->blob.data + idx;
10963                         len = mono_metadata_decode_blob_size (p, &p2);
10964                         len += p2 - p;
10965                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10966                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10967                 }
10968         }
10969
10970         klass->instance_size = MAX (klass->instance_size, real_size);
10971         mono_class_layout_fields (klass);
10972 }
10973
10974 static void
10975 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10976 {
10977         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10978         MonoReflectionPropertyBuilder *pb;
10979         MonoImage *image = klass->image;
10980         MonoProperty *properties;
10981         int i;
10982
10983         mono_error_init (error);
10984
10985         if (!klass->ext)
10986                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10987
10988         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10989         klass->ext->property.first = 0;
10990
10991         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10992         klass->ext->properties = properties;
10993         for (i = 0; i < klass->ext->property.count; ++i) {
10994                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10995                 properties [i].parent = klass;
10996                 properties [i].attrs = pb->attrs;
10997                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10998                 if (!mono_error_ok (error))
10999                         return;
11000                 if (pb->get_method)
11001                         properties [i].get = pb->get_method->mhandle;
11002                 if (pb->set_method)
11003                         properties [i].set = pb->set_method->mhandle;
11004
11005                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11006                 if (pb->def_value) {
11007                         guint32 len, idx;
11008                         const char *p, *p2;
11009                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11010                         if (!klass->ext->prop_def_values)
11011                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11012                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11013                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11014                         /* Copy the data from the blob since it might get realloc-ed */
11015                         p = assembly->blob.data + idx;
11016                         len = mono_metadata_decode_blob_size (p, &p2);
11017                         len += p2 - p;
11018                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11019                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11020                 }
11021         }
11022 }
11023
11024 MonoReflectionEvent *
11025 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11026 {
11027         MonoEvent *event = g_new0 (MonoEvent, 1);
11028         MonoClass *klass;
11029
11030         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11031
11032         event->parent = klass;
11033         event->attrs = eb->attrs;
11034         event->name = mono_string_to_utf8 (eb->name);
11035         if (eb->add_method)
11036                 event->add = eb->add_method->mhandle;
11037         if (eb->remove_method)
11038                 event->remove = eb->remove_method->mhandle;
11039         if (eb->raise_method)
11040                 event->raise = eb->raise_method->mhandle;
11041
11042 #ifndef MONO_SMALL_CONFIG
11043         if (eb->other_methods) {
11044                 int j;
11045                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11046                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11047                         MonoReflectionMethodBuilder *mb = 
11048                                 mono_array_get (eb->other_methods,
11049                                                 MonoReflectionMethodBuilder*, j);
11050                         event->other [j] = mb->mhandle;
11051                 }
11052         }
11053 #endif
11054
11055         return mono_event_get_object (mono_object_domain (tb), klass, event);
11056 }
11057
11058 static void
11059 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11060 {
11061         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11062         MonoReflectionEventBuilder *eb;
11063         MonoImage *image = klass->image;
11064         MonoEvent *events;
11065         int i;
11066
11067         mono_error_init (error);
11068
11069         if (!klass->ext)
11070                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11071
11072         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11073         klass->ext->event.first = 0;
11074
11075         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11076         klass->ext->events = events;
11077         for (i = 0; i < klass->ext->event.count; ++i) {
11078                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11079                 events [i].parent = klass;
11080                 events [i].attrs = eb->attrs;
11081                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11082                 if (!mono_error_ok (error))
11083                         return;
11084                 if (eb->add_method)
11085                         events [i].add = eb->add_method->mhandle;
11086                 if (eb->remove_method)
11087                         events [i].remove = eb->remove_method->mhandle;
11088                 if (eb->raise_method)
11089                         events [i].raise = eb->raise_method->mhandle;
11090
11091 #ifndef MONO_SMALL_CONFIG
11092                 if (eb->other_methods) {
11093                         int j;
11094                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11095                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11096                                 MonoReflectionMethodBuilder *mb = 
11097                                         mono_array_get (eb->other_methods,
11098                                                                         MonoReflectionMethodBuilder*, j);
11099                                 events [i].other [j] = mb->mhandle;
11100                         }
11101                 }
11102 #endif
11103                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11104         }
11105 }
11106
11107 static gboolean
11108 remove_instantiations_of_and_ensure_contents (gpointer key,
11109                                                   gpointer value,
11110                                                   gpointer user_data)
11111 {
11112         MonoType *type = (MonoType*)key;
11113         MonoClass *klass = (MonoClass*)user_data;
11114
11115         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11116                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11117                 return TRUE;
11118         } else
11119                 return FALSE;
11120 }
11121
11122 static void
11123 check_array_for_usertypes (MonoArray *arr)
11124 {
11125         int i;
11126
11127         if (!arr)
11128                 return;
11129
11130         for (i = 0; i < mono_array_length (arr); ++i)
11131                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11132 }
11133
11134 MonoReflectionType*
11135 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11136 {
11137         MonoError error;
11138         MonoClass *klass;
11139         MonoDomain* domain;
11140         MonoReflectionType* res;
11141         int i, j;
11142
11143         MONO_ARCH_SAVE_REGS;
11144
11145         domain = mono_object_domain (tb);
11146         klass = mono_class_from_mono_type (tb->type.type);
11147
11148         /*
11149          * Check for user defined Type subclasses.
11150          */
11151         RESOLVE_TYPE (tb->parent);
11152         check_array_for_usertypes (tb->interfaces);
11153         if (tb->fields) {
11154                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11155                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11156                         if (fb) {
11157                                 RESOLVE_TYPE (fb->type);
11158                                 check_array_for_usertypes (fb->modreq);
11159                                 check_array_for_usertypes (fb->modopt);
11160                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11161                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11162                         }
11163                 }
11164         }
11165         if (tb->methods) {
11166                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11167                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11168                         if (mb) {
11169                                 RESOLVE_TYPE (mb->rtype);
11170                                 check_array_for_usertypes (mb->return_modreq);
11171                                 check_array_for_usertypes (mb->return_modopt);
11172                                 check_array_for_usertypes (mb->parameters);
11173                                 if (mb->param_modreq)
11174                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11175                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11176                                 if (mb->param_modopt)
11177                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11178                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11179                         }
11180                 }
11181         }
11182         if (tb->ctors) {
11183                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11184                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11185                         if (mb) {
11186                                 check_array_for_usertypes (mb->parameters);
11187                                 if (mb->param_modreq)
11188                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11189                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11190                                 if (mb->param_modopt)
11191                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11192                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11193                         }
11194                 }
11195         }
11196
11197         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11198
11199         /* 
11200          * we need to lock the domain because the lock will be taken inside
11201          * So, we need to keep the locking order correct.
11202          */
11203         mono_loader_lock ();
11204         mono_domain_lock (domain);
11205         if (klass->wastypebuilder) {
11206                 mono_domain_unlock (domain);
11207                 mono_loader_unlock ();
11208                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11209         }
11210         /*
11211          * Fields to set in klass:
11212          * the various flags: delegate/unicode/contextbound etc.
11213          */
11214         klass->flags = tb->attrs;
11215         klass->has_cctor = 1;
11216         klass->has_finalize = 1;
11217
11218         /* fool mono_class_setup_parent */
11219         klass->supertypes = NULL;
11220         mono_class_setup_parent (klass, klass->parent);
11221         mono_class_setup_mono_type (klass);
11222
11223 #if 0
11224         if (!((MonoDynamicImage*)klass->image)->run) {
11225                 if (klass->generic_container) {
11226                         /* FIXME: The code below can't handle generic classes */
11227                         klass->wastypebuilder = TRUE;
11228                         mono_loader_unlock ();
11229                         mono_domain_unlock (domain);
11230                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11231                 }
11232         }
11233 #endif
11234
11235         /* enums are done right away */
11236         if (!klass->enumtype)
11237                 ensure_runtime_vtable (klass);
11238
11239         if (tb->subtypes) {
11240                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11241                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11242                         mono_class_alloc_ext (klass);
11243                         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)));
11244                 }
11245         }
11246
11247         klass->nested_classes_inited = TRUE;
11248
11249         /* fields and object layout */
11250         if (klass->parent) {
11251                 if (!klass->parent->size_inited)
11252                         mono_class_init (klass->parent);
11253                 klass->instance_size = klass->parent->instance_size;
11254                 klass->sizes.class_size = 0;
11255                 klass->min_align = klass->parent->min_align;
11256                 /* if the type has no fields we won't call the field_setup
11257                  * routine which sets up klass->has_references.
11258                  */
11259                 klass->has_references |= klass->parent->has_references;
11260         } else {
11261                 klass->instance_size = sizeof (MonoObject);
11262                 klass->min_align = 1;
11263         }
11264
11265         /* FIXME: handle packing_size and instance_size */
11266         typebuilder_setup_fields (klass, &error);
11267         if (!mono_error_ok (&error))
11268                 goto failure;
11269         typebuilder_setup_properties (klass, &error);
11270         if (!mono_error_ok (&error))
11271                 goto failure;
11272
11273         typebuilder_setup_events (klass, &error);
11274         if (!mono_error_ok (&error))
11275                 goto failure;
11276
11277         klass->wastypebuilder = TRUE;
11278
11279         /* 
11280          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11281          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11282          * we want to return normal System.MonoType objects, so clear these out from the cache.
11283          *
11284          * Together with this we must ensure the contents of all instances to match the created type.
11285          */
11286         if (domain->type_hash && klass->generic_container)
11287                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11288
11289         mono_domain_unlock (domain);
11290         mono_loader_unlock ();
11291
11292         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11293                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11294                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11295         }
11296
11297         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11298         g_assert (res != (MonoReflectionType*)tb);
11299
11300         return res;
11301
11302 failure:
11303         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11304         klass->wastypebuilder = TRUE;
11305         mono_domain_unlock (domain);
11306         mono_loader_unlock ();
11307         mono_error_raise_exception (&error);
11308         return NULL;
11309 }
11310
11311 void
11312 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11313 {
11314         MonoGenericParamFull *param;
11315         MonoImage *image;
11316         MonoClass *pklass;
11317
11318         MONO_ARCH_SAVE_REGS;
11319
11320         param = g_new0 (MonoGenericParamFull, 1);
11321
11322         if (gparam->mbuilder) {
11323                 if (!gparam->mbuilder->generic_container) {
11324                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11325                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11326                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11327                         gparam->mbuilder->generic_container->is_method = TRUE;
11328                         /* 
11329                          * Cannot set owner.method, since the MonoMethod is not created yet.
11330                          * Set the image field instead, so type_in_image () works.
11331                          */
11332                         gparam->mbuilder->generic_container->image = klass->image;
11333                 }
11334                 param->param.owner = gparam->mbuilder->generic_container;
11335         } else if (gparam->tbuilder) {
11336                 if (!gparam->tbuilder->generic_container) {
11337                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11338                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11339                         gparam->tbuilder->generic_container->owner.klass = klass;
11340                 }
11341                 param->param.owner = gparam->tbuilder->generic_container;
11342         }
11343
11344         param->info.name = mono_string_to_utf8 (gparam->name);
11345         param->param.num = gparam->index;
11346
11347         image = &gparam->tbuilder->module->dynamic_image->image;
11348         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11349
11350         gparam->type.type = &pklass->byval_arg;
11351
11352         mono_class_set_ref_info (pklass, gparam);
11353         mono_image_lock (image);
11354         image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11355         mono_image_unlock (image);
11356 }
11357
11358 MonoArray *
11359 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11360 {
11361         MonoReflectionModuleBuilder *module = sig->module;
11362         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11363         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11364         guint32 buflen, i;
11365         MonoArray *result;
11366         SigBuffer buf;
11367
11368         check_array_for_usertypes (sig->arguments);
11369
11370         sigbuffer_init (&buf, 32);
11371
11372         sigbuffer_add_value (&buf, 0x07);
11373         sigbuffer_add_value (&buf, na);
11374         if (assembly != NULL){
11375                 for (i = 0; i < na; ++i) {
11376                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11377                         encode_reflection_type (assembly, type, &buf);
11378                 }
11379         }
11380
11381         buflen = buf.p - buf.buf;
11382         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11383         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11384         sigbuffer_free (&buf);
11385
11386         return result;
11387 }
11388
11389 MonoArray *
11390 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11391 {
11392         MonoDynamicImage *assembly = sig->module->dynamic_image;
11393         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11394         guint32 buflen, i;
11395         MonoArray *result;
11396         SigBuffer buf;
11397
11398         check_array_for_usertypes (sig->arguments);
11399
11400         sigbuffer_init (&buf, 32);
11401
11402         sigbuffer_add_value (&buf, 0x06);
11403         for (i = 0; i < na; ++i) {
11404                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11405                 encode_reflection_type (assembly, type, &buf);
11406         }
11407
11408         buflen = buf.p - buf.buf;
11409         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11410         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11411         sigbuffer_free (&buf);
11412
11413         return result;
11414 }
11415
11416 void 
11417 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11418 {
11419         ReflectionMethodBuilder rmb;
11420         MonoMethodSignature *sig;
11421         MonoClass *klass;
11422         GSList *l;
11423         int i;
11424
11425         sig = dynamic_method_to_signature (mb);
11426
11427         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11428
11429         /*
11430          * Resolve references.
11431          */
11432         /* 
11433          * Every second entry in the refs array is reserved for storing handle_class,
11434          * which is needed by the ldtoken implementation in the JIT.
11435          */
11436         rmb.nrefs = mb->nrefs;
11437         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11438         for (i = 0; i < mb->nrefs; i += 2) {
11439                 MonoClass *handle_class;
11440                 gpointer ref;
11441                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11442
11443                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11444                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11445                         /*
11446                          * The referenced DynamicMethod should already be created by the managed
11447                          * code, except in the case of circular references. In that case, we store
11448                          * method in the refs array, and fix it up later when the referenced 
11449                          * DynamicMethod is created.
11450                          */
11451                         if (method->mhandle) {
11452                                 ref = method->mhandle;
11453                         } else {
11454                                 /* FIXME: GC object stored in unmanaged memory */
11455                                 ref = method;
11456
11457                                 /* FIXME: GC object stored in unmanaged memory */
11458                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11459                         }
11460                         handle_class = mono_defaults.methodhandle_class;
11461                 } else {
11462                         MonoException *ex = NULL;
11463                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11464                         if (!ref)
11465                                 ex = mono_get_exception_type_load (NULL, NULL);
11466                         else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11467                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11468
11469                         if (ex) {
11470                                 g_free (rmb.refs);
11471                                 mono_raise_exception (ex);
11472                                 return;
11473                         }
11474                 }
11475
11476                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11477                 rmb.refs [i + 1] = handle_class;
11478         }               
11479
11480         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11481
11482         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11483
11484         /* Fix up refs entries pointing at us */
11485         for (l = mb->referenced_by; l; l = l->next) {
11486                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11487                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11488                 gpointer *data;
11489                 
11490                 g_assert (method->mhandle);
11491
11492                 data = (gpointer*)wrapper->method_data;
11493                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11494                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11495                                 data [i + 1] = mb->mhandle;
11496                 }
11497         }
11498         g_slist_free (mb->referenced_by);
11499
11500         g_free (rmb.refs);
11501
11502         /* ilgen is no longer needed */
11503         mb->ilgen = NULL;
11504 }
11505
11506 #endif /* DISABLE_REFLECTION_EMIT */
11507
11508 void
11509 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11510 {
11511         g_assert (mb);
11512
11513         if (mb->mhandle)
11514                 mono_runtime_free_method (
11515                         mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11516 }
11517
11518 /**
11519  * 
11520  * mono_reflection_is_valid_dynamic_token:
11521  * 
11522  * Returns TRUE if token is valid.
11523  * 
11524  */
11525 gboolean
11526 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11527 {
11528         return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11529 }
11530
11531 #ifndef DISABLE_REFLECTION_EMIT
11532
11533 /**
11534  * mono_reflection_lookup_dynamic_token:
11535  *
11536  * Finish the Builder object pointed to by TOKEN and return the corresponding
11537  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
11538  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11539  * mapping table.
11540  *
11541  * LOCKING: Take the loader lock
11542  */
11543 gpointer
11544 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11545 {
11546         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11547         MonoObject *obj;
11548         MonoClass *klass;
11549
11550         mono_loader_lock ();
11551         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11552         mono_loader_unlock ();
11553         if (!obj) {
11554                 if (valid_token)
11555                         g_error ("Could not find required dynamic token 0x%08x", token);
11556                 else
11557                         return NULL;
11558         }
11559
11560         if (!handle_class)
11561                 handle_class = &klass;
11562         return resolve_object (image, obj, handle_class, context);
11563 }
11564
11565 MonoMethodSignature *
11566 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11567 {
11568         MonoMethodSignature *sig;
11569         g_assert (image->dynamic);
11570
11571         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11572         if (sig)
11573                 return sig;
11574
11575         return mono_method_signature (method);
11576 }
11577
11578 /*
11579  * ensure_complete_type:
11580  *
11581  *   Ensure that KLASS is completed if it is a dynamic type, or references
11582  * dynamic types.
11583  */
11584 static void
11585 ensure_complete_type (MonoClass *klass)
11586 {
11587         if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11588                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11589
11590                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11591
11592                 // Asserting here could break a lot of code
11593                 //g_assert (klass->wastypebuilder);
11594         }
11595
11596         if (klass->generic_class) {
11597                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11598                 int i;
11599
11600                 for (i = 0; i < inst->type_argc; ++i) {
11601                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11602                 }
11603         }
11604 }
11605
11606 static gpointer
11607 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11608 {
11609         gpointer result = NULL;
11610
11611         if (strcmp (obj->vtable->klass->name, "String") == 0) {
11612                 result = mono_string_intern ((MonoString*)obj);
11613                 *handle_class = mono_defaults.string_class;
11614                 g_assert (result);
11615         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11616                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11617                 MonoClass *mc = mono_class_from_mono_type (type);
11618                 if (!mono_class_init (mc))
11619                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
11620
11621                 if (context) {
11622                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
11623                         result = mono_class_from_mono_type (inflated);
11624                         mono_metadata_free_type (inflated);
11625                 } else {
11626                         result = mono_class_from_mono_type (type);
11627                 }
11628                 *handle_class = mono_defaults.typehandle_class;
11629                 g_assert (result);
11630         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11631                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11632                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11633                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11634                 result = ((MonoReflectionMethod*)obj)->method;
11635                 if (context)
11636                         result = mono_class_inflate_generic_method (result, context);
11637                 *handle_class = mono_defaults.methodhandle_class;
11638                 g_assert (result);
11639         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11640                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11641                 result = mb->mhandle;
11642                 if (!result) {
11643                         /* Type is not yet created */
11644                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11645
11646                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11647
11648                         /*
11649                          * Hopefully this has been filled in by calling CreateType() on the
11650                          * TypeBuilder.
11651                          */
11652                         /*
11653                          * TODO: This won't work if the application finishes another 
11654                          * TypeBuilder instance instead of this one.
11655                          */
11656                         result = mb->mhandle;
11657                 }
11658                 if (context)
11659                         result = mono_class_inflate_generic_method (result, context);
11660                 *handle_class = mono_defaults.methodhandle_class;
11661         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11662                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11663
11664                 result = cb->mhandle;
11665                 if (!result) {
11666                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11667
11668                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11669                         result = cb->mhandle;
11670                 }
11671                 if (context)
11672                         result = mono_class_inflate_generic_method (result, context);
11673                 *handle_class = mono_defaults.methodhandle_class;
11674         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11675                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11676
11677                 ensure_complete_type (field->parent);
11678                 if (context) {
11679                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11680                         MonoClass *class = mono_class_from_mono_type (inflated);
11681                         MonoClassField *inflated_field;
11682                         gpointer iter = NULL;
11683                         mono_metadata_free_type (inflated);
11684                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
11685                                 if (!strcmp (field->name, inflated_field->name))
11686                                         break;
11687                         }
11688                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11689                         result = inflated_field;
11690                 } else {
11691                         result = field;
11692                 }
11693                 *handle_class = mono_defaults.fieldhandle_class;
11694                 g_assert (result);
11695         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11696                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11697                 result = fb->handle;
11698
11699                 if (!result) {
11700                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11701
11702                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11703                         result = fb->handle;
11704                 }
11705
11706                 if (fb->handle && fb->handle->parent->generic_container) {
11707                         MonoClass *klass = fb->handle->parent;
11708                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11709                         MonoClass *inflated = mono_class_from_mono_type (type);
11710
11711                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11712                         g_assert (result);
11713                         mono_metadata_free_type (type);
11714                 }
11715                 *handle_class = mono_defaults.fieldhandle_class;
11716         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11717                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11718                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
11719                 MonoClass *klass;
11720
11721                 klass = type->data.klass;
11722                 if (klass->wastypebuilder) {
11723                         /* Already created */
11724                         result = klass;
11725                 }
11726                 else {
11727                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11728                         result = type->data.klass;
11729                         g_assert (result);
11730                 }
11731                 *handle_class = mono_defaults.typehandle_class;
11732         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11733                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11734                 MonoMethodSignature *sig;
11735                 int nargs, i;
11736
11737                 if (helper->arguments)
11738                         nargs = mono_array_length (helper->arguments);
11739                 else
11740                         nargs = 0;
11741
11742                 sig = mono_metadata_signature_alloc (image, nargs);
11743                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11744                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11745
11746                 if (helper->unmanaged_call_conv) { /* unmanaged */
11747                         sig->call_convention = helper->unmanaged_call_conv - 1;
11748                         sig->pinvoke = TRUE;
11749                 } else if (helper->call_conv & 0x02) {
11750                         sig->call_convention = MONO_CALL_VARARG;
11751                 } else {
11752                         sig->call_convention = MONO_CALL_DEFAULT;
11753                 }
11754
11755                 sig->param_count = nargs;
11756                 /* TODO: Copy type ? */
11757                 sig->ret = helper->return_type->type;
11758                 for (i = 0; i < nargs; ++i)
11759                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11760
11761                 result = sig;
11762                 *handle_class = NULL;
11763         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11764                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11765                 /* Already created by the managed code */
11766                 g_assert (method->mhandle);
11767                 result = method->mhandle;
11768                 *handle_class = mono_defaults.methodhandle_class;
11769         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11770                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11771                 type = mono_class_inflate_generic_type (type, context);
11772                 result = mono_class_from_mono_type (type);
11773                 *handle_class = mono_defaults.typehandle_class;
11774                 g_assert (result);
11775                 mono_metadata_free_type (type);
11776         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11777                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11778                 type = mono_class_inflate_generic_type (type, context);
11779                 result = mono_class_from_mono_type (type);
11780                 *handle_class = mono_defaults.typehandle_class;
11781                 g_assert (result);
11782                 mono_metadata_free_type (type);
11783         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11784                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11785                 MonoClass *inflated;
11786                 MonoType *type;
11787                 MonoClassField *field;
11788
11789                 if (is_sre_field_builder (mono_object_class (f->fb)))
11790                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11791                 else if (is_sr_mono_field (mono_object_class (f->fb)))
11792                         field = ((MonoReflectionField*)f->fb)->field;
11793                 else
11794                         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)));
11795
11796                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11797                 inflated = mono_class_from_mono_type (type);
11798
11799                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11800                 ensure_complete_type (field->parent);
11801                 g_assert (result);
11802                 mono_metadata_free_type (type);
11803                 *handle_class = mono_defaults.fieldhandle_class;
11804         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11805                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11806                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11807                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11808                 MonoMethod *method;
11809
11810                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11811                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11812                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11813                         method = ((MonoReflectionMethod *)c->cb)->method;
11814                 else
11815                         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)));
11816
11817                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11818                 *handle_class = mono_defaults.methodhandle_class;
11819                 mono_metadata_free_type (type);
11820         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11821                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11822                 if (m->method_args) {
11823                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11824                         if (context)
11825                                 result = mono_class_inflate_generic_method (result, context);
11826                 } else {
11827                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11828                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11829                         MonoMethod *method;
11830
11831                         if (is_sre_method_builder (mono_object_class (m->mb)))
11832                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11833                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11834                                 method = ((MonoReflectionMethod *)m->mb)->method;
11835                         else
11836                                 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)));
11837
11838                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11839                         mono_metadata_free_type (type);
11840                 }
11841                 *handle_class = mono_defaults.methodhandle_class;
11842         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11843                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11844                 MonoType *mtype;
11845                 MonoClass *klass;
11846                 MonoMethod *method;
11847                 gpointer iter;
11848                 char *name;
11849
11850                 mtype = mono_reflection_type_get_handle (m->parent);
11851                 klass = mono_class_from_mono_type (mtype);
11852
11853                 /* Find the method */
11854
11855                 name = mono_string_to_utf8 (m->name);
11856                 iter = NULL;
11857                 while ((method = mono_class_get_methods (klass, &iter))) {
11858                         if (!strcmp (method->name, name))
11859                                 break;
11860                 }
11861                 g_free (name);
11862
11863                 // FIXME:
11864                 g_assert (method);
11865                 // FIXME: Check parameters/return value etc. match
11866
11867                 result = method;
11868                 *handle_class = mono_defaults.methodhandle_class;
11869         } else if (is_sre_array (mono_object_get_class(obj)) ||
11870                                 is_sre_byref (mono_object_get_class(obj)) ||
11871                                 is_sre_pointer (mono_object_get_class(obj))) {
11872                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11873                 MonoType *type = mono_reflection_type_get_handle (ref_type);
11874                 result = mono_class_from_mono_type (type);
11875                 *handle_class = mono_defaults.typehandle_class;
11876         } else {
11877                 g_print ("%s\n", obj->vtable->klass->name);
11878                 g_assert_not_reached ();
11879         }
11880         return result;
11881 }
11882
11883 #else /* DISABLE_REFLECTION_EMIT */
11884
11885 MonoArray*
11886 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11887 {
11888         g_assert_not_reached ();
11889         return NULL;
11890 }
11891
11892 void
11893 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11894 {
11895         g_assert_not_reached ();
11896 }
11897
11898 void
11899 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11900 {
11901         g_assert_not_reached ();
11902 }
11903
11904 void
11905 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11906 {
11907         g_assert_not_reached ();
11908 }
11909
11910 void
11911 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11912 {
11913         g_assert_not_reached ();
11914 }
11915
11916 void
11917 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11918 {
11919         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11920 }
11921
11922 void
11923 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11924 {
11925         g_assert_not_reached ();
11926 }
11927
11928 void
11929 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11930 {
11931         g_assert_not_reached ();
11932 }
11933
11934 MonoReflectionModule *
11935 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11936 {
11937         g_assert_not_reached ();
11938         return NULL;
11939 }
11940
11941 guint32
11942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11943 {
11944         g_assert_not_reached ();
11945         return 0;
11946 }
11947
11948 guint32
11949 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11950 {
11951         g_assert_not_reached ();
11952         return 0;
11953 }
11954
11955 guint32
11956 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
11957                                                  gboolean create_methodspec, gboolean register_token)
11958 {
11959         g_assert_not_reached ();
11960         return 0;
11961 }
11962
11963 void
11964 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11965 {
11966 }
11967
11968 void
11969 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods, 
11970                                           MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11971                                           MonoArray *events)
11972 {
11973         g_assert_not_reached ();
11974 }
11975
11976 void
11977 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11978 {
11979         *overrides = NULL;
11980         *num_overrides = 0;
11981 }
11982
11983 MonoReflectionEvent *
11984 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11985 {
11986         g_assert_not_reached ();
11987         return NULL;
11988 }
11989
11990 MonoReflectionType*
11991 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11992 {
11993         g_assert_not_reached ();
11994         return NULL;
11995 }
11996
11997 void
11998 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11999 {
12000         g_assert_not_reached ();
12001 }
12002
12003 MonoArray *
12004 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12005 {
12006         g_assert_not_reached ();
12007         return NULL;
12008 }
12009
12010 MonoArray *
12011 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12012 {
12013         g_assert_not_reached ();
12014         return NULL;
12015 }
12016
12017 void 
12018 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12019 {
12020 }
12021
12022 gpointer
12023 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12024 {
12025         return NULL;
12026 }
12027
12028 MonoType*
12029 mono_reflection_type_get_handle (MonoReflectionType* ref)
12030 {
12031         if (!ref)
12032                 return NULL;
12033         return ref->type;
12034 }
12035
12036 #endif /* DISABLE_REFLECTION_EMIT */
12037
12038 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12039 const static guint32 declsec_flags_map[] = {
12040         0x00000000,                                     /* empty */
12041         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12042         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12043         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12044         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12045         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12046         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12047         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12048         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12049         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12050         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12051         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12052         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12053         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12054         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12055         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12056         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12057         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12058         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12059 };
12060
12061 /*
12062  * Returns flags that includes all available security action associated to the handle.
12063  * @token: metadata token (either for a class or a method)
12064  * @image: image where resides the metadata.
12065  */
12066 static guint32
12067 mono_declsec_get_flags (MonoImage *image, guint32 token)
12068 {
12069         int index = mono_metadata_declsec_from_index (image, token);
12070         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12071         guint32 result = 0;
12072         guint32 action;
12073         int i;
12074
12075         /* HasSecurity can be present for other, not specially encoded, attributes,
12076            e.g. SuppressUnmanagedCodeSecurityAttribute */
12077         if (index < 0)
12078                 return 0;
12079
12080         for (i = index; i < t->rows; i++) {
12081                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12082
12083                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12084                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12085                         break;
12086
12087                 action = cols [MONO_DECL_SECURITY_ACTION];
12088                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12089                         result |= declsec_flags_map [action];
12090                 } else {
12091                         g_assert_not_reached ();
12092                 }
12093         }
12094         return result;
12095 }
12096
12097 /*
12098  * Get the security actions (in the form of flags) associated with the specified method.
12099  *
12100  * @method: The method for which we want the declarative security flags.
12101  * Return the declarative security flags for the method (only).
12102  *
12103  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12104  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12105  */
12106 guint32
12107 mono_declsec_flags_from_method (MonoMethod *method)
12108 {
12109         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12110                 /* FIXME: No cache (for the moment) */
12111                 guint32 idx = mono_method_get_index (method);
12112                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12113                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12114                 return mono_declsec_get_flags (method->klass->image, idx);
12115         }
12116         return 0;
12117 }
12118
12119 /*
12120  * Get the security actions (in the form of flags) associated with the specified class.
12121  *
12122  * @klass: The class for which we want the declarative security flags.
12123  * Return the declarative security flags for the class.
12124  *
12125  * Note: We cache the flags inside the MonoClass structure as this will get 
12126  *       called very often (at least for each method).
12127  */
12128 guint32
12129 mono_declsec_flags_from_class (MonoClass *klass)
12130 {
12131         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12132                 if (!klass->ext || !klass->ext->declsec_flags) {
12133                         guint32 idx;
12134
12135                         idx = mono_metadata_token_index (klass->type_token);
12136                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12137                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12138                         mono_loader_lock ();
12139                         mono_class_alloc_ext (klass);
12140                         mono_loader_unlock ();
12141                         /* we cache the flags on classes */
12142                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12143                 }
12144                 return klass->ext->declsec_flags;
12145         }
12146         return 0;
12147 }
12148
12149 /*
12150  * Get the security actions (in the form of flags) associated with the specified assembly.
12151  *
12152  * @assembly: The assembly for which we want the declarative security flags.
12153  * Return the declarative security flags for the assembly.
12154  */
12155 guint32
12156 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12157 {
12158         guint32 idx = 1; /* there is only one assembly */
12159         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12160         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12161         return mono_declsec_get_flags (assembly->image, idx);
12162 }
12163
12164
12165 /*
12166  * Fill actions for the specific index (which may either be an encoded class token or
12167  * an encoded method token) from the metadata image.
12168  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12169  */
12170 static MonoBoolean
12171 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12172         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12173 {
12174         MonoBoolean result = FALSE;
12175         MonoTableInfo *t;
12176         guint32 cols [MONO_DECL_SECURITY_SIZE];
12177         int index = mono_metadata_declsec_from_index (image, token);
12178         int i;
12179
12180         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12181         for (i = index; i < t->rows; i++) {
12182                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12183
12184                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12185                         return result;
12186
12187                 /* if present only replace (class) permissions with method permissions */
12188                 /* if empty accept either class or method permissions */
12189                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12190                         if (!actions->demand.blob) {
12191                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12192                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12193                                 actions->demand.blob = (char*) (blob + 2);
12194                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12195                                 result = TRUE;
12196                         }
12197                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12198                         if (!actions->noncasdemand.blob) {
12199                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12200                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12201                                 actions->noncasdemand.blob = (char*) (blob + 2);
12202                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12203                                 result = TRUE;
12204                         }
12205                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12206                         if (!actions->demandchoice.blob) {
12207                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12208                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12209                                 actions->demandchoice.blob = (char*) (blob + 2);
12210                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12211                                 result = TRUE;
12212                         }
12213                 }
12214         }
12215
12216         return result;
12217 }
12218
12219 static MonoBoolean
12220 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12221         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12222 {
12223         guint32 idx = mono_metadata_token_index (klass->type_token);
12224         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12225         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12226         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12227 }
12228
12229 static MonoBoolean
12230 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12231         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12232 {
12233         guint32 idx = mono_method_get_index (method);
12234         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12235         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12236         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12237 }
12238
12239 /*
12240  * Collect all actions (that requires to generate code in mini) assigned for
12241  * the specified method.
12242  * Note: Don't use the content of actions if the function return FALSE.
12243  */
12244 MonoBoolean
12245 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12246 {
12247         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12248                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12249         MonoBoolean result = FALSE;
12250         guint32 flags;
12251
12252         /* quick exit if no declarative security is present in the metadata */
12253         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12254                 return FALSE;
12255
12256         /* we want the original as the wrapper is "free" of the security informations */
12257         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12258                 method = mono_marshal_method_from_wrapper (method);
12259                 if (!method)
12260                         return FALSE;
12261         }
12262
12263         /* First we look for method-level attributes */
12264         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12265                 mono_class_init (method->klass);
12266                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12267
12268                 result = mono_declsec_get_method_demands_params (method, demands, 
12269                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12270         }
12271
12272         /* Here we use (or create) the class declarative cache to look for demands */
12273         flags = mono_declsec_flags_from_class (method->klass);
12274         if (flags & mask) {
12275                 if (!result) {
12276                         mono_class_init (method->klass);
12277                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12278                 }
12279                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12280                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12281         }
12282
12283         /* The boolean return value is used as a shortcut in case nothing needs to
12284            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12285         return result;
12286 }
12287
12288
12289 /*
12290  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12291  *
12292  * Note: Don't use the content of actions if the function return FALSE.
12293  */
12294 MonoBoolean
12295 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12296 {
12297         MonoBoolean result = FALSE;
12298         guint32 flags;
12299
12300         /* quick exit if no declarative security is present in the metadata */
12301         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12302                 return FALSE;
12303
12304         /* we want the original as the wrapper is "free" of the security informations */
12305         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12306                 method = mono_marshal_method_from_wrapper (method);
12307                 if (!method)
12308                         return FALSE;
12309         }
12310
12311         /* results are independant - zeroize both */
12312         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12313         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12314
12315         /* First we look for method-level attributes */
12316         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12317                 mono_class_init (method->klass);
12318
12319                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12320                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12321         }
12322
12323         /* Here we use (or create) the class declarative cache to look for demands */
12324         flags = mono_declsec_flags_from_class (method->klass);
12325         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12326                 mono_class_init (method->klass);
12327
12328                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12329                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12330         }
12331
12332         return result;
12333 }
12334
12335 /*
12336  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12337  *
12338  * @klass       The inherited class - this is the class that provides the security check (attributes)
12339  * @demans      
12340  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12341  * 
12342  * Note: Don't use the content of actions if the function return FALSE.
12343  */
12344 MonoBoolean
12345 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12346 {
12347         MonoBoolean result = FALSE;
12348         guint32 flags;
12349
12350         /* quick exit if no declarative security is present in the metadata */
12351         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12352                 return FALSE;
12353
12354         /* Here we use (or create) the class declarative cache to look for demands */
12355         flags = mono_declsec_flags_from_class (klass);
12356         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12357                 mono_class_init (klass);
12358                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12359
12360                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12361                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12362         }
12363
12364         return result;
12365 }
12366
12367 /*
12368  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12369  *
12370  * Note: Don't use the content of actions if the function return FALSE.
12371  */
12372 MonoBoolean
12373 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12374 {
12375         /* quick exit if no declarative security is present in the metadata */
12376         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12377                 return FALSE;
12378
12379         /* we want the original as the wrapper is "free" of the security informations */
12380         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12381                 method = mono_marshal_method_from_wrapper (method);
12382                 if (!method)
12383                         return FALSE;
12384         }
12385
12386         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12387                 mono_class_init (method->klass);
12388                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12389
12390                 return mono_declsec_get_method_demands_params (method, demands, 
12391                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12392         }
12393         return FALSE;
12394 }
12395
12396
12397 static MonoBoolean
12398 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12399 {
12400         guint32 cols [MONO_DECL_SECURITY_SIZE];
12401         MonoTableInfo *t;
12402         int i;
12403
12404         int index = mono_metadata_declsec_from_index (image, token);
12405         if (index == -1)
12406                 return FALSE;
12407
12408         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12409         for (i = index; i < t->rows; i++) {
12410                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12411
12412                 /* shortcut - index are ordered */
12413                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12414                         return FALSE;
12415
12416                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12417                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12418                         entry->blob = (char*) (metadata + 2);
12419                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12420                         return TRUE;
12421                 }
12422         }
12423
12424         return FALSE;
12425 }
12426
12427 MonoBoolean
12428 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12429 {
12430         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12431                 guint32 idx = mono_method_get_index (method);
12432                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12433                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12434                 return get_declsec_action (method->klass->image, idx, action, entry);
12435         }
12436         return FALSE;
12437 }
12438
12439 MonoBoolean
12440 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12441 {
12442         /* use cache */
12443         guint32 flags = mono_declsec_flags_from_class (klass);
12444         if (declsec_flags_map [action] & flags) {
12445                 guint32 idx = mono_metadata_token_index (klass->type_token);
12446                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12447                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12448                 return get_declsec_action (klass->image, idx, action, entry);
12449         }
12450         return FALSE;
12451 }
12452
12453 MonoBoolean
12454 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12455 {
12456         guint32 idx = 1; /* there is only one assembly */
12457         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12458         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12459
12460         return get_declsec_action (assembly->image, idx, action, entry);
12461 }
12462
12463 gboolean
12464 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12465 {
12466         MonoObject *res, *exc;
12467         void *params [1];
12468         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12469         static MonoMethod *method = NULL;
12470
12471         if (!System_Reflection_Emit_TypeBuilder) {
12472                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12473                 g_assert (System_Reflection_Emit_TypeBuilder);
12474         }
12475         if (method == NULL) {
12476                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12477                 g_assert (method);
12478         }
12479
12480         /* 
12481          * The result of mono_type_get_object () might be a System.MonoType but we
12482          * need a TypeBuilder so use mono_class_get_ref_info (klass).
12483          */
12484         g_assert (mono_class_get_ref_info (klass));
12485         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12486
12487         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12488
12489         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12490         if (exc)
12491                 return FALSE;
12492         else
12493                 return *(MonoBoolean*)mono_object_unbox (res);
12494 }